| Table of contents |
Lights as shaders
Taking up this theme again, after a long hiatus. Provocation is the recent addition of methods on Light to identify "fake ambient" lights which shouldn't be written out for fancier ray-tracing backends. This raised the question whether such properties shouldn't be handled as attributes in the Appearance attached to the Light. Here's a proposal to shift the bulk of the light information into such attributes, while still leaving the light field in the SceneGraphComponent:- Change the type of the light field in SceneGraphComponent from Light to Geometry.
- Define final static instances of Geometry named POINT_LIGHT, DIRECTIONAL_LIGHT, and SPOT_LIGHT to replace the existing three subclasses of Light. Call setLight() with one of these three instances to replicate the existing behavior of lights.
- Fancier, area-lights could be implemented by attaching actual geometry via setLight().
- Move the current fields of these light subclasses into Appearance attributes attached to the SceneGraphComponent containing the light.
- We can decide whether we need another inheritance mechanism for these attributes -- I don't think so.
- Define interfaces in de.jreality.shader for PointLight, DirectionalLight, and SpotLight extracted from the existing classes with those names.
- Backends can use these interfaces along with AttributeEntity magic to get hold of instances that behave like the instances of existing subclasses of Light.
- Gunn 12:47, 7 Dec 2006 (CET)
Viewer VR feedback
Just a few random responses to the current state of the ViewerVR app (on the web site):- The perspective toggle doesn't do a very good job of keeping the same visual scale -- object becomes much bigger and no longer fits on screen. Use bounding box to fix this.
- Using tools in stereo mode is unreliable since picking doesn't seem to be aware that it's in cross-eyed stereo mode.
- Turning on "flatshading" in the "Appearance" menu yields strange results
- Gunn 16:55, 20 Nov 2006 (CET)
software viewer update
Since I was not at the last jReality-meeting, I want to report on the status of the software viewer here. For two month or so, I have develpoed and tested a rewrite/cleanup of the software viewer to address some of the issues with the old one. at the moment it is in the de.jreality.softwiever package in the src-soft-new dir. Here is a list of the most notable and noteworthy changes:
- does triangulate allways (so no "holes" in non planar polygons any more)
- uses the shader proxy system for getting the appearance
- support for face/edge/point color geom attributes
- support for edge/point radii as geom attribute
- level of detail for points and tubes to give a better look while keeping the performance penalty small.
- sky box works now (again) with the root appearance/cubeMap
- The PostScript and svg exports finally do intersect the triangles for a correct painters algorithm. This is still horribly slow but works now more less reliably.
At the moment there is only a double rasterizer which is slightly slower than the old integer rasterizer (that used fixpoint arithmetic but was allways problematic with non normalized texture coordinates)
Some of the changes give slight performance penalties but in general it is still o.k. to try it you can set -Dde.jreality.scene.Viewer="de.jreality.softviewer.SoftViewer" to have only the new softviewer available in the (vr)viewerapp (or add a ":" separated list of others to have the choice in the viewerapp)
Timh 13:36, 11 Nov 2006 (CET)
Update: I also added support for othographic camera now.
Timh 11:58, 13 Nov 2006 (CET)
Clean up of this page
I've removed all topics older than one year; they can still be accessed on the following page: Talk-09.11.06.
Selection
At yesterday's (Nov. 8) meeting, we discussed some issues related to selection in ViewerApp class. I'm wondering if we should think about providing selection support at a lower level (that is, not connected as currently to the ViewerApp class), so that users could take advantage of selection mechanisms without being forced to use the ViewerApp class. I've had good luck myself with providing a static lookup method on my SelectionManager class: public static SelectionManager selectionManagerForViewer(Viewer v) {};
which provides a mechanism for getting selection managers assigned to Viewer instances. The default behavior is that it looks in a hashmap to see if the viewer has a selection manager already; if not it allocates one and puts it into the table. This behavior could be overridden if we wanted to experiment with several viewers all sharing the same selection manager. In this way, a SelectionManager would then be available inside of Tool instances, since the Viewer instance is provided by the ToolContext class (which doesn't know about ViewerApp obviously). The current use of SelectionManager in ViewerApp could be easily changed to conform to this, by allocating the SelectionManager for the ViewerSwitch which belongs to the ViewerApp.
A second question related to selection arose regarding whether a Tool instance should be able to be included in a SceneGraphPath, as if it were a SceneGraphNode instance. I would favor such a strategy, since it fits in with being able to address top-level elements of SceneGraphComponents within a SceneGraphPath. Whether we want to extend SceneGraphPath to include finer level of detail is a separate issue which I won't address here.
- Gunn 11:56, 9 Nov 2006 (CET)
Tool system, revisited
Steffen has addressed almost all the issues I raised in my original posting below "Questions on tool system". One thing that I still want to understand better is the avatar path. Until now I haven't understood why this has to be part of the global tool system that we provide to jReality users. Can someone provide me with a simple example of a tool that needs to have this avatar path provided from a global state, rather than have the tool itself placed in such a way that the desired path is available locally? :Gunn 09:58, 30 Aug 2006 (CEST)
- Answer(Ulrich): The tool that pops up a control panel under double click on the SceneGraphComponent where it is attached places a control panel in front of the avatar. In a desktop situation this could be replaced by a camera path, but in the portal ...
I'm still not clear why this requires that the tool system knows about the avatar path. Why not put the tool mentioned above into the desired "avatar" node when you build the scene graph? I don't doubt that avatar is a reasonable concept; what I don't yet understand is why the tool system has to be aware of it. :Gunn 16:38, 20 Nov 2006 (CET)
Remarks on transparency
From my recent experiences using RenderMan, I've had some more thoughts about how jReality supports transparency. I've basically changed my mind about how to treat the alpha channel of colors. As far as possible, the "transparency" field in the appearance node should be used to control the transparency of the surface. To be exact:- RGBA colors should only be allowed as:
- texture map values or
- as vertex or face attribute colors.
- In these cases, the alpha channel and (1-transparency) should have a multiplicative effect on the opacity.
- All other colors -- chiefly those used in shaders -- should be considered to be RGB colors and the alpha channel implicitly treated as 1. Use the "transparency" appearance field to achieve transparency, not the alpha channel.
- Gunn 15:09, 9 Aug 2006 (CEST)
Questions on tool system
I've been trying to understand how the tool system works in the past few weeks. I've begun to get a picture of it, and it's clear that it is a very ambitious project that achieves some important aims. I'd like to understand better the following questions:- What is a ToolSystemViewer and why is it needed? I would have expected that by adding tools to your scene graph, you would automatically expect that they would be activated, perform, and be deactivated appropriately. But it seems that in order for tools to function you have to instantiate a ToolSystemViewer and massage it appropriately (e.g. by calling initializeTools()).
- What is the avatar path and why is it needed? I would have expected that by setting an avatar tool at the appropriate node, one would achieve avatar behaviour. Having to set a global variable (in the ToolSystemViewer instance referred to above) seems to contradict the spirit of the tool system that tools should be autonomous. What special about the avatar path? Who uses it?
- Answer: There are three tools that use getAvatarPath(): EncompassTool, PointerDisplayTool, ToolRotateTool. If I understand what how they work, the last two tools would work just as well if they were added to the avatar node from the beginning, and then they don't need to have it provided from outside. And encompass tool could have it as a field which the user would set when constructing the t ool.
- The configuration file (e.g., toolconfig.xml) seems a necessary evil. Are there ways to reduce the size of this file?
- For example, do we need to have virtual devices to multiply and invert matrices? Are the results cached and re-used, hence justifying the existence of such devices? Is the price worth it? (I personally am skeptical).
- Does anyone have any thoughts on how to avoid the proliferation of strings in the configuration file that then have to appear exactly correctly in various source files? (Reminds me of CommonAttributes).
- The package structure is very flat. There are approximately 70 classes. I'd recommend introducing some sub-packages:
- tool.tools specific tools (*Tool.java) : ~18
- tool.virtual virtual devices (Virtual*.java): ~23
- tool.animation animation related classes (Anima*.java): 4
- tool.device raw devices (*Raw*java + *Device*) 8
- tool everything else: ~18
- Do all these classes really belong in de.jreality.scene? Perhaps we should isolate the core classes and leave them there, and everything else should migrate to a new package (de.jreality.tools?).
- Should Tool be an interface? Are there other classes that should be interfaces?
- Should Tool include some methods for extracting static and dynamic documentation strings?
- We have provided a method setAuxiliaryRoot() in the Viewer interface, with the idea that objects that don't really belong to the scene graph would be added there, leaving the scene graph in its original pristine state.
- Geometry generated by tools are (for me anyway) the archetypal example of things that belong in the auxiliary root.
- At the current time, however, all the existing tools that add geometry, add it directly to the scene graph. Should we reconsider whether we need the auxiliary root?
- If we do, is that an alternative strategy to remove junk added by tools before the scene graph is written or passed on to other viewers?
- Bugs and questions:
- If a tool is activated by shift-button1 and you let up on the shift key before releasing the mouse, the tool never deactivates. How to fix that: We should remove the isShiftDown() test in DeviceMouse and instead create a virtual device that creates this input device.
- If a tool is attached to a scene graph component that appears in more than one spot in the scene graph, how is the method tc.getRootToTool() defined? Which path does it return? Is the same tool registered with the tool manager once for each time it appears, or what? Answer: The tool context is asociated to the current activation path - the path from the scene root to the pick that caused activation. This path is returned by the method tc.getRootToLocal(). tc.getRootToToolComponent() gives the sub-path of tc.getRootToLocal() to the component where the tool is attatched.
- Gunn 13:33, 18 May 2006 (CEST)
Appearance inheritance mechanism
- It seems like a good thing to write down the results of our discussion on March 17 related to inheritance of appearance attributes. ( I'm sure that I don't remember everything correctly, so please help out by correcting or expanding these remarks.) There were two sorts of inheritance we wanted to support:
- Global parameters like transparency, not restricted to any particular shader.
- Shader-specific parameters: bloo.blah.myShader.moo should inherit from bloo.myShader.moo.
- To clarify this difference, we introduced a new separater '#" and wrote the latter condition as:
- bloo.blah.myShader#moo should inherit from bloo.myShader#moo.
- The current inheritance mechanism supports the first type of inheritance but not the second. However AttributeEntity's, which are designed to implement shaders, do in fact support the second sort of inheritance by introducing essentially the '#' separater as noted above. (Correct me if I'm wrong Steffen).
- In order to support both types of inheritance, several solutions were proposed:
- Introduce a keyword any into the specification of attributes, so that if the attribute bloo.any.moo were set, then bloo.blah.myShader.moo would inherit from this value.
- Introduce a new separator '#' to identify shader-specific parameters. This would, in the simplest form, be restricted to the final separator, but could conceivably be extended to include the last n separators in a key. Such a separator would mean that the terms it separates should be considered as a single string with respect to the existing search algorithm based on the '.' separator.
- Don't introduce any new symbols, but rather add another layer to the lookup procedure in the effective appearance. To be precise, to look up bloo.blah.myShader.moo, search in order for the following keys:
- bloo.blah.myShader.moo (+)
- blah.myShader.moo (+)
- myShader.moo (+)
- bloo.blah.moo
- bloo.moo
- moo
- The keys marked with (+) are new and represent truncation from the left, while the current search mechanism is a kind of truncation from the right (ignoring the final keyword which stays there). (Steffen correct me if I'm wrong on this).
- Considerations. The following points were made regarding any possible changes:
- We should be very careful about changing the current evaluation algorithm in any way that complicates it in any way. Two reasons for this:
- Other users will be frustrated by trying to use it.
- The evaluation process will become more time-consuming and expensive.
- New syntax such as the '#' separator or the 'any' keyword should be introduced only when absolutely necessary and when the resulting algorithm is easy to explain and implement.
- Existing appearance specifications should as much as possible continue to work as they do now.
- We should be very careful about changing the current evaluation algorithm in any way that complicates it in any way. Two reasons for this:
- Gunn 10:13, 28 Mar 2006 (CEST)
Remarks on 3D/4D and non-euclidean signature
- It seems like a good time to remind everyone that jReality is designed to support both of these capabilities.
- They are separate capabilities: I can have non-euclidean geometry using 3-vectors (e.g., hyperbolic geometry can be so handled), and I can also use 4-vectors to represent Euclidean geometry.
- 3D/4D:
- Anytime you read out vertex or normal information from a data list, you need to check if its 3- or 4D. If it is 4D and you want a quick fix, just use Pn.dehomogenize()to convert to 3 vectors. If there are points "at infinity" (w=0) then you'll get errors, but it's better than ignoring the 4-th coordinate.
- Ideal would be to shift over to using 4-vectors as default, since then you're assured of doing the right thing. Most of the code in Pn and Rn is designed to make working with such vectors easy.
- There's a simple test case for checking compliance: data/testdata3d/oogl/trapezoid.4d.off
- Non-euclidean geometry ("signature").
- At some point soon the method getSignature() will disappear from Transformation class. For many purposes, this can be compensated by looking in the EffectiveAppearance for the key "signature". There still remains the getSignature() method on Viewer interface. The following method for example is useful for getting encompass() to work correctly.
- Getting the EffectiveAppearance from the ToolContext is implemented as a static method.
- Gunn 13:32, 15 Mar 2006 (CET)
picksystem and other things
I added support for texture coordinates in the AABB and soft pick system. It basically works well but I found some bad results now and then in a samble app. wwwhere one can cint on the helicoid. This is eicher due to numerics in the interpolation or the pick is incorrect (I suspect the first possibility) so more tests need to be done. I refactored the Swing component as a texture oorange network into a bunch of classes. It is basically a Component that takes a Swing component and gives you an appearance and a tool to attach to the geometry in question. It uses texture coordinates if available (so curved panels are possible now) and projects the pick point on the x-y-plane otherwise (like the network did before). I changed the way mouse events are dispatched as well. they should correctly report enter,exit events now, since swing does all the work. Still the system has to prove that it is working on more complex guis. Timh 16:57, 13 Feb 2006 (CET)some threading issues
I ran into an ugly thread problem (deadlock) when implementing the JTree: Changes to the tree must be done from inside the awt thread, so I tried to do a call likeEventQueue.invokeAndWait( reader )in some sort of listener - i.e. when a tool sets a Transformation. But the event is generated with a write lock on the node, and the read operation of course needs a readLock...
While I tried to fix this problem, I figured out that the current thread-safety-state is very poor - we do not support concurrent readers! The childrenAccept(..) simply synchronizes the whole call - so no other thread can visit the graph.
Another problem is that there is no way to write from inside a visitor, in the "makeSubgraphPickableVisitor" I had to do the following:
visit(SceneGraphComponent sgc) {
if (scg.getGeometry() != null && scg.getGeometry() instanceof IndexedFaceSet)
((IndexedFaceSet)scg.getGeometry()).setGeometryAttributes(...);
}
One way to fix that would be a childrenWriteAccept, that gets a writeLock before the visit is called (for all children), but I would prefer some way of specifying which node types the visitor wants to write.
Update: I started to get the core thread-safe. The new src is in cvs under src-core. Changes:
The Lock can change a writeLock into a readLock and back. So after all writes are done, the writeLock is changed into a readLock, and the (collected) events are distributed. So listeners can notify changes to different threads (i.e. the dispatch thread ;-). But there is still the need for writing from inside the event, this is handled as follows: The SceneEvent class has a method enqueueWriter( runnable ). After all listeners are informed, the lock is changed into a writeLock again and the (also collected) writers are executed. this repeats until no more writers are enqueued.
Generally all reads are surrounded by
startReader();
try {
return ...
} finally {
finishReader();
}
and the same for write methods. (with start/finishWriter();) The finishWriter() in SceneGraphNode calls writingFinished() when the last nested writing is done. In this method subclasses will distribute their collected events, the lock is already a readLock.
The visitors just do the same, so concurrent reads are possible now. Also writing is possible from a visitor now:
Instead of calling
sgc.childrenAccept(visitor);writing visitors call
sgc.childrenWriteAccept(visitor, writeTransformation, writeAppearance,
writeCamera, writeLight, writeGeometry, writeChildren);
the writeSth are booleans whether a certain child type will be written. If a visitor writes on components, it must be invoked with
Scene.executeWriter(rootNode, ...);
Status: Currently all nodes except Camera and Transformation are done and seem to work fine.
Todo: Transformation + Camera! AppearenceEvent+Listeners need to be changed to report multiple changed attributes. AddOn: I mad the AABBPick Visitor write sn AABBTree into the ifs if there was none. and found that the childrenWriteAccept was to slow. GEtting a write lock for every geometry all the time is to expensive. Now I had to check in the Component if the tree is absent and decide to either visit or visit with write. It might be better if every node had a writeAccept(..) then one could decide in the read visit that one has to change a thing and call writeAccept with a new Visitor that performs the change. Or as I mentioned in the last meeting: have aa childrenWriteAccept that takes a conditional (an interface with a metthod that returns on a given sceneNode wether a write is necessary.Timh 17:39, 13 Feb 2006 (CET)
unsortet things while looking through the shaders
- transparency at some pont was changed to default to .5 (which breakes some of the test scenes btw). I think things should not be transparent by default!
- I still think (and it was set up like that in the first place) that flat shading is a different shader than smooth shading. Thus the smooth shading flat
- I am not sure about the NORMALS_DRAW in the default point shader. A point generically has no normals.One probably wants a shader (maby a special geometry shader) that renders a vector field (and not necessarily the normals). Here one might even want to set things like arrow type or something like that.
Geometry factories
I finally converted almost all of my geometry creation code to use the factories. Based on this experience, here's some recommendations for these factories:- Some ideas on constructors:
- Remove constructors from IndexedFaceSetFactory which specify the booleans for generating various fields.
- These constructors are NOT inherited by the subclasses which makes them problematic in my view.
- Instead, give the boolean flags reasonable default values (true). The user can then explicitly set the flag to false. Or, if the corresponding field is explicitly set, the flag is also set to false. That is, if I provide face normals with setFaceNormals(), then the flag for generating face normals is set to false, and remains false until the method setGenerateFaceNormals(true) is called.
- The signature argument should be removed from the constructors. Being there complicates life unnecessarily, by forcing too many versions of the constructors. Most users will be operating in euclidean space anyway. If someone wants to set a non-Euclidean signature, he can do so with a method call setSignature(int s). The only side-effect of of such a call is to set any automatically generated normals to be dirty.
- The constructors which remain:
- should, like the current QuadMeshFactory, establish the basic parameters of the instance to be constructed. In the case of IndexedFaceSetFactory, this would look like IndexedFaceSetFactory(int numPoints, int numFaces).
- come in pairs, in one of which an existing instance of geometry is given as the first parameter. This allows more efficient operations on existing geometries.
- Remove constructors from IndexedFaceSetFactory which specify the booleans for generating various fields.
- Include an IndexedLineSetFactory explicitly rather than expecting users to use an IndexedFaceSetFactory for the purpose.
- Rename refactor()</t> to <tt>update() because it's more understandable.
- It appears that the version of the IndexedLineSetFactory which takes an existing instance, doesn't work if the number of points and/or faces is edited. There's an exception down in the StorageModel copying code indicating some problem with the size of the data lists being used.
- Gunn 12:19, 14 Nov 2005 (CET)
Old topices
For older topics see Talk-09.11.06.
- Gunn 11:21, 9 Nov 2006 (CET)