Psychedelic Rendering

Psychedelic Rendering

Post by james.p.willi.. » Fri, 21 May 1999 04:00:00



I want to have every polygon belonging to a node or its descendent
nodes rendered with a different diffuse color, using BASE_COLOR for the
lighting model of the entire tree.  When this render is finished, I
need to return the tree to its normal, unpsychedelic state easily.  The
color used for a given polygon is unimportant, as long as it's unique
in the scene.  It should happen at the polygon level, not the triangle
level.  So, a SoCube would be rendered with six unique colors, and a
cyclinder having all parts would be rendered with three.

I've tried creating a SoMaterial with a large array of diffuse colors
combined with setting the value field in a SoMaterialBinding to both
SoMaterialBinding::PER_PART and SoMaterialBinding::PER_FACE.  This
seems to work for either the cube or the cylinder but not both.

Can anyone point me in the best direction for doing this?  Thanks for
any help you can provide.

Jim Williams

--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---

 
 
 

Psychedelic Rendering

Post by Mike Hec » Sun, 23 May 1999 04:00:00



Quote:>I want to have every polygon belonging to a node or its descendent
>nodes rendered with a different diffuse color, using BASE_COLOR for the
>lighting model of the entire tree.  When this render is finished, I
>need to return the tree to its normal, unpsychedelic state easily.  The
>color used for a given polygon is unimportant, as long as it's unique
>in the scene.  It should happen at the polygon level, not the triangle
>level.  So, a SoCube would be rendered with six unique colors, and a
>cyclinder having all parts would be rendered with three.

>I've tried creating a SoMaterial with a large array of diffuse colors
>combined with setting the value field in a SoMaterialBinding to both
>SoMaterialBinding::PER_PART and SoMaterialBinding::PER_FACE.  This
>seems to work for either the cube or the cylinder but not both.

PER_PART should what you want for Cube, Cylinder, Cone,
IndexedFaceSet, etc

Try the following .iv file (works on my machine).

-Mike
 TGS Inc, http://www.tgs.com
------------------------------------------------------------------------
-------------------------
#Inventor V2.1 ascii

Separator {
    LightModel { model BASE_COLOR }
    Material {
        diffuseColor [ 1 .5 .5, 1  .75 .5 , 1   0 .5, .5 1  0,
                       1  0  0, .5 1   .75, .75 1 .5, 0  .5 1,
                       1 .4  1, .75.5  1  , .5  0 1 , 0  0  1 ]
    }
    MaterialBinding { value PER_PART }

    Cube {}
    Translation { translation 2.5 0 0 }
    Cylinder {}
    Translation { translation 2.5 0 0 }
    Cone {}
    Translation { translation 3 0 0 }

    Coordinate3 {
        point [ -2  2 0,  -1  2 0,  0  2 0,  1  2 0,     #  0..3
                -2  1 0,  -1  1 0,  0  1 0,  1  1 0,     #  4..7
                -2  0 0,  -1  0 0,  0  0 0,  1  0 0,     #  8..11
                -2 -1 0,  -1 -1 0,  0 -1 0,  1 -1 0  ]   # 12..15
    }
    IndexedFaceSet {
        coordIndex [ 0, 4, 5, 1, -1, 1, 5, 6, 2, -1,  2, 6, 7, 3, -1,
                     4, 8, 9, 5, -1, 5, 9,10, 6, -1,  6,10,11, 7, -1,
                     8,12,13, 9, -1, 9,13,14,10, -1, 10,14,15,11      ]
    }

Quote:}


 
 
 

Psychedelic Rendering

Post by willi.. » Tue, 25 May 1999 04:00:00






>> I want to have every polygon belonging to a node or its descendent
>> nodes rendered with a different diffuse color, using BASE_COLOR for
the
>> lighting model of the entire tree...

>> I've tried creating a SoMaterial with a large array of diffuse colors
>> combined with setting the value field in a SoMaterialBinding to both
>> SoMaterialBinding::PER_PART and SoMaterialBinding::PER_FACE.  This
>> seems to work for either the cube or the cylinder but not both.

> PER_PART should what you want for Cube, Cylinder, Cone,
> IndexedFaceSet, etc

> Try the following .iv file (works on my machine)...

Thanks for your reply.  I want to correct something in my post and be
more specific about my question.  First, your example works here too.
The problem is what happens with SoQuadMesh's.  Using
SoMaterialBinding::PER_PART makes cylinders look right, but not
SoQuadMesh's, which appear as horizontal strips without being divided
vertically.  For them I need to use SoMaterialBinding::PER_FACE to get
what I want.

Given this, it seems like the following convoluted algorithm is the
best way to render a scene with every part/face a different color, and
return it back to normal when done.  Is there a better way?

Before render begins:
1) Find node having the largest number of parts/faces.  Allocate an
array of SoMFColor's with this many elements.
2) Insert a SoMaterial and a SoMaterialBinding near the root of the
scene.
3) Set override to true for the SoMaterial and SoMaterialBinding added
in 2).

During render, just before each node is rendered:
4) Set diffuseColor field of SoMaterial added in 2) to an array
containing the next set of unique colors.  Use the array created in 1).
5) Set value field of SoMaterialBinding added in 2) to
SoMaterialBinding::PER_FACE unless the node being rendered is a
SoCylinder, SoCone, or SoText3 (the only nodes that define a Part
enum).  For these, set the field to SoMaterialBinding::PER_PART.

After render has finished:
6) Remove SoMaterial and SoMaterialBinding nodes added in 2).
7) Delete array created in 1).

Is there a better way?  Is it safe to make the modifications in 4) and
5) during rendering, especially since this is done after they've
already been traversed?  Will they affect the appearance of the node
rendered next?

Thanks again.

Jim

--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---

 
 
 

Psychedelic Rendering

Post by Mike Hec » Thu, 27 May 1999 04:00:00



> Thanks for your reply.  I want to correct something in my post and be
> more specific about my question.  First, your example works here too.
> The problem is what happens with SoQuadMesh's.  Using
> SoMaterialBinding::PER_PART makes cylinders look right, but not
> SoQuadMesh's, which appear as horizontal strips without being divided
> vertically.  For them I need to use SoMaterialBinding::PER_FACE to get
> what I want.

Oh... you didn't say anything about quadmeshs. :-)
For whatever historical reason, that is the correct
behavior for an SoQuadmesh.

Quote:> Given this, it seems like the following convoluted algorithm is the
> best way to render a scene with every part/face a different color, and
> return it back to normal when done.  Is there a better way?

> Before render begins:
> 1) Find node having the largest number of parts/faces.  Allocate an
> array of SoMFColor's with this many elements.
> 2) Insert a SoMaterial and a SoMaterialBinding near the root of the
> scene.
> 3) Set override to true for the SoMaterial and SoMaterialBinding added
> in 2).

> During render, just before each node is rendered:
> 4) Set diffuseColor field of SoMaterial added in 2) to an array
> containing the next set of unique colors.  Use the array created in 1).
> 5) Set value field of SoMaterialBinding added in 2) to
> SoMaterialBinding::PER_FACE unless the node being rendered is a
> SoCylinder, SoCone, or SoText3 (the only nodes that define a Part
> enum).  For these, set the field to SoMaterialBinding::PER_PART.

> After render has finished:
> 6) Remove SoMaterial and SoMaterialBinding nodes added in 2).
> 7) Delete array created in 1).

> Is there a better way?  Is it safe to make the modifications in 4) and
> 5) during rendering, especially since this is done after they've
> already been traversed?  Will they affect the appearance of the node
> rendered next?

It's always somewhat dangerous to modify the scenegraph
during a traversal, but that's moot because this scheme
won't work.  Changing the contents of a node after the
node has been traversed will not change the values already
in the traversal state list.

The simplest solution would be to not use SoQuadmesh in
your application. :-)  But apparently you are hoping to
handle arbitrary scene graphs with unknown content.  One
approach would be to modify the scene graph immediately
after reading it in.  For example, find all SoQuadmesh
nodes and replace them with SoIndexedFaceSet nodes.

-Mike
 TGS Inc, http://www.tgs.com

 
 
 

Psychedelic Rendering

Post by willi.. » Fri, 28 May 1999 04:00:00





> > Thanks for your reply...
> > The problem is what happens with SoQuadMesh's.  Using
> > SoMaterialBinding::PER_PART makes cylinders look right, but not
> > SoQuadMesh's...
> > For them I need to use SoMaterialBinding::PER_FACE to get
> > what I want.

> Oh... you didn't say anything about quadmeshs. :-)
> For whatever historical reason, that is the correct
> behavior for an SoQuadmesh.

> > Given this, it seems like the following convoluted algorithm is the
> > best way to render a scene with every part/face a different color,
> > and return it back to normal when done.  Is there a better way?

> > ...

> > Is it safe to make the modifications in 4) and
> > 5) during rendering, especially since this is done after they've
> > already been traversed?  Will they affect the appearance of the node
> > rendered next?

> It's always somewhat dangerous to modify the scenegraph
> during a traversal, but that's moot because this scheme
> won't work.  Changing the contents of a node after the
> node has been traversed will not change the values already
> in the traversal state list.

So, how do I render each polygon in a different color and return the
tree to its normal state when done?  Can I add a new Element or modify
one during traversal?  I'm not too worried about the SoQuadMesh
problem, since I can replace them at startup as you say.

Quote:> The simplest solution would be to not use SoQuadmesh in
> your application. :-)  But apparently you are hoping to
> handle arbitrary scene graphs with unknown content.

Exactly.

Quote:> One approach would be to modify the scene graph immediately
> after reading it in.  For example, find all SoQuadmesh
> nodes and replace them with SoIndexedFaceSet nodes.

SoIndexedTriangleStripSet suffer from the same problem, so I'll have to
replace them too.  Are there any others?  It might be easier and affect
performance less if I go the other way, replacing Cones and Cylinders,
and use PER_FACE everywhere.  This is getting rather ugly.  I guess
there's no cure all for me.

Thanks,

Jim

--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---

 
 
 

Psychedelic Rendering

Post by Mike Hec » Fri, 28 May 1999 04:00:00




> So, how do I render each polygon in a different color and return the
> tree to its normal state when done?  Can I add a new Element or modify
> one during traversal?  I'm not too worried about the SoQuadMesh
> problem, since I can replace them at startup as you say.

Yes, you can modify the contents of a state Element
during a render traversal by including an SoCallback
node to the scene graph.  For what you're doing, if you
can preprocess the scene graph so everything responds
to PER_FACE (or PER_PART) then you can put the Material
node-of-many-colors and the MaterialBinding node (both
with override set as appropriate) at the top of the
scene graph under a Switch node.  Then you can toggle
psychedelic mode by changing "whichChild" on the Switch
and you wouldn't need to change elements.

-Mike
 TGS Inc, http://www.tgs.com