hitting a speed limit

My earlier reply seems to have gotten garbled.

The gist is, if I use the “parallel scene” method, yes, the source of the data will be copied from time to time. Maybe you picture parallel structures as being necessarily back-and-forth.

But, I’d still like to find a way to make the RBC work without a huge performance hit. That rules out the morphs. But surely the RBC must still be able to “get” to its GVD, so I’d like to follow that trail.

The RBC doesn’t store the GVD, since it doesn’t care about it once it’s been created. But you can extract it from the Geom(s) that can be found within the RBC’s internal scene, e.g.:

gvd = rbc.find(’**/+GeomNode’).node().getGeom(0).getVertexData()

David

Ok, now that looks tempting. Is it the same GeomVertexData or a copy? What guarantees that an index on one is the same as the index on the other? Are changes made to it honored?

Good news and bad news.

‘gvd’ got the correct value, a GVD with a Tristrips with 4 rows, when I called it on a scene with 10 cards.

But!

wr= GeomVertexWriter( gvd, 'texcoord' )

failed with

and

rd= GeomVertexReader( gvd, 'texcoord' )

succeeded, implying that ‘gvd’ is not a non-const GVD. Bad news!

There was no colors array present, but changing texcoords would be sufficient.

This is repaired by utilizing modifyNode and modifyVertexData instead of get. Then my writer is created successfully.

Alas! No change. Row 3 reads the change:

card
  4 rows.
  Array 0 (00E54EB4, [ vertex(3f) normal(3f) texcoord(2f) ]):
...
    row 3:
      vertex 1 0 0.5
      normal 0 -1 0
      texcoord 1 0

But the card looks the same on the screen. So that means I didn’t get the right vdata, that the GeomVertexData that the graphics card is using is somewhere else. When I call collect again:

the tile turns into a trapezoid as expected. So, the vertex data gets copied to get into the video card or somewhere that the engine looks every frame, and I want to get to that place.

Am I correct that the color data is stored somewhere else altogether?

Ah, my mistake. I gave you the wrong command.

The command I gave you found the original card’s geometry, which is indeed just original copy of the data that is ultimately rendered. But you can get a pointer to the data that is to be rendered:

gvd = rbc.getInternalScene().find('**/+GeomNode').node().getGeom(0).getVertexData() 

The key is, of course, rbc.getInternalScene().

However, there is absolutely no matching up of index numbers. The index numbers in the internal scene are appended in the order in which they are encountered by the RBC. I guess you could ensure that the cards are attached to the scene graph in a particular order, and assume that same order will be observed in the resulting internal scene. I think that will consistently be the case, but note that even if it is true, this is technically undocumented behavior and is therefore not guaranteed to remain true for future releases of Panda.

David

Aha, at this point it sounds exactly like what I’m looking for. It looks like it favors my strategy of the UVs instead of colors, since colors didn’t show up in the other internal scene I examined, although the normals option appears to be available too.

I would love to get some guarantee about the index or order of addition, but I also like the idea of playing “it” by “ear” for now, for relevant definitions of “it” and “ear”. Am I guaranteed that the order will remain the same between frames, after it’s established, say until ‘collect’ is called again for example? With a little extra work, I can read the array and populate my mapping index that way, say, by using a tiny floating point coordinate for one corner of the tristrip to identify it, then index it, then reset the coordinate and run the program.

If the vertex, normal, and texcoord are stored in rdb.GetInternalScene( ), which I presume is writable by the way, where is the color?

I start off with this code:

cm= CardMaker( 'cm' )
cs= [ NodePath( cm.generate( ) ) for j in range( 10 ) ]
rbcN= RigidBodyCombiner( 'rbc' )
rbc= NodePath( rbcN )
rbc.reparentTo( render )

for c in cs:
    p1= ran.uniform( 0, 10 ), ran.uniform( 0, 10 ), ran.uniform( 0, 10 )
    c.setPos( *p1 )
    r, g= ran.uniform( .8, 1 ), ran.uniform( .8, 1 )
    b= 2.5- r- g
    c.setColor( r, g, b, 1 )
    c.reparentTo( rbc )
rbcN.collect( )

Then:

-->print rbcN.getInternalScene( ).node().modifyGeom( 0 ).modifyVertexData( )
card
  40 rows.
  Array 0 (00E5905C, [ vertex(3f) normal(3f) texcoord(2f) ]):
    row 0:
      vertex 0 0 1
      normal 0 -1 0
      texcoord 0 1
    row 1:

…for 40 rows-- 4 vertices in a tristrip per card. But then:

  Array 1 (00E58CDC, [ transform_blend(1s) ]):
    row 0:
      transform_blend 1
    row 1:

…for 40 rows, then:

Transform blend table:
  0. empty
  1. NodeVertexTransform(cm):1
  2. NodeVertexTransform(cm):1

Then:

-->vdata= rbcN.getInternalScene( ).node().modifyGeom( 0 ).modifyVertexData( )
-->wr= GeomVertexWriter( vdata, 'vertex' )
-->rd= GeomVertexReader( vdata, 'vertex' )
-->rd.setRow( 0 )
-->print rd.getData3f( )
VBase3(0, 0, 1)
-->wr.setRow( 0 )
-->wr.setData3f( 0, 0, .8 )
-->rd.setRow( 0 )
-->print rd.getData3f( )
VBase3(0, 0, 0.8)

as we expect; creating a GeomVertexWriter and changing the variables changes the geometry on screen! Ta-da! So I’m expecting that our earlier texcoord trick will get me my colors.

But what is the meaning of …modifyGeom( 1 )? Is it one of the other constructors for GeomVertexWriter that will get me access to the transform blend tables? Will I find the nodes’ spatial transforms there? Where is the color?
[/code]

modifyGeom(1) would mean the second Geom in the list. It might have the same GeomVertexData anyway, so it may not matter.

The color will be in the scene graph, unless you force it into the vertices with:

c.setColor( r, g, b, 1 ) 
c.flattenLight()

which is a good thing to do anyway, to better optimize the RBC’s grouping. Ideally, the RBC can combine all of your nodes into a single Geom, which is only possible if they all share the same scene graph state. If there is more than one Geom in the internal scene, then some of your nodes had a different scene graph state.

David

This doesn’t make sense because

-->vdata= rbcN.getInternalScene( ).node().modifyGeom( 0 ).modifyVertexData( )
-->vdata2= rbcN.getInternalScene( ).node().modifyGeom( 1 ).modifyVertexData( )
-->print id(vdata), id( vdata2)
10809144 10807296
-->print vdata is vdata2
False

but they both have 40 rows! And,

-->print rbcN.getInternalScene( ).node().getGeoms( )
[Geom [ GeomTristrips ], 2 faces, Geom [ GeomTristrips ], 2 faces, Geom [ GeomTristrips ],
 2 faces, Geom [ GeomTristrips ], 2 faces, Geom [ GeomTristrips ], 2 faces, Geom [ GeomTri
strips ], 2 faces, Geom [ GeomTristrips ], 2 faces, Geom [ GeomTristrips ], 2 faces, Geom
[ GeomTristrips ], 2 faces, Geom [ GeomTristrips ], 2 faces]

So what data is this all and does it overlap and if so how?

c.setColor( r, g, b, 1 ) 
c.flattenLight()

When I called it, the vdata became:

-->card
  40 rows.
  Array 0 (00E577F4, [ vertex(3f) normal(3f) texcoord(2f) ]):
    row 0:
      vertex 0 0 0.5
      normal 0 -1 0
      texcoord 0 1
    row 1:
      vertex 2.5766 0.352811 1.42701
      normal 0 -1 0
      texcoord 0 0

So I will not be able to write relative vertices, but that wasn’t one of my requirements, not one of the things I was planning to do anyway, so. However, a color array did not appear.

Also, what all attributes are there in a RenderState?

All Geoms under an RBC share the very same GeomVertexData object, at least initially. Although when you call modifyVertexData(), it may force a copy. So it’s best to ensure there is only one Geom under the RBC to begin with; or if there are multiple, then after you force the copy you should reapply the copy to all Geoms with setVertexData() so that there is once again only one GeomVertexData.

Hmm, you’re right, flattenLight() isn’t enough to create a color column. You’ll have to take the vertex data and use:

gvd = root.getGeom(0).getVertexData()
gvd = gvd.setColor((1, 1, 1, 1), 4, Geom.NTUint8, Geom.CColor)
root.modifyGeom(0).setVertexData(gvd)

to force the color column to be added. Then you’ll want to use node.setColorOff(1) to ensure scene graph color is disabled, and allow vertex color to be visible.

Dozens of them, as described in the manual under “Common State Changes” and “Render Attributes”.

David

What is root, and what is node? Do I have to setColorOff all the ancestors in between, or just the leafs? Will setColor have an effect, or will I have to setColor on the CardMaker before I generate cards?

By root I mean rbc.getInternalScene(). By node I meant the individual cards when you add them to the rbc, though you could also apply the state to the rbc node instead (or any parent node) and it would propagate down to all children automatically, by virtue of Panda’s scene graph.

node.setColor() applies a state to the scene graph that sets a particular color for all geometry at that node and below, overriding whatever appears in the GeomVertexData (if any). This is not what you want; you want the color that appears in the GeomVertexData to be visible instead. To do this, you specify node.setColorOff() on the scene graph, and ensure there is a color column on the vertices.

If you call CardMaker.setColor(), all it does is an implicit node.setColor() on the card it generates.

David

That still doesn’t explain how to get the colors on the nodes in the first place.

You’ll have to apply them one at a time to the vertices, via GeomVertexWriter. Either apply them to the original cards, or to the GeomVertexData you extract from the RBC.

David

My attempt to apply them to the original cards failed.

When I set the cardmaker color, then generate a card c, then call c.setColorOff, I get all white cards, and array 2 contains all 1s on all vertices. When I just set the color and generate a card, I get colored cards, but array 2 contains all 1s.

Therefore I still don’t have the data that was sent to the graphics card.

Is there some way to set a string tag to accompany primitives through the pipeline, that I can read with a GeomVertexReader later?

Right, that’s the expected behavior. You can’t use node.setColor() or cardMaker.setColor() to change the data in the GeomVertexData. All that does is change the scene graph color, which supercedes the data in the GeomVertexData. (When you change the color from the scene graph, Panda plays tricks with lighting to make the object appear a particular solid color, regardless of the color values that appear in the vertex data.)

But this isn’t useful for your purposes. You need to use the color in the GeomVertexData, so you can set each tile to a different color independently. This means you need to use setColorOff(), and then you need to use a GeomVertexWriter to set the designed color directly on the vertices.

David

Ok, then. What is your advice about identifying them? My ideas were try to hack-in a string tag or pyobject tag, or use unique floating point values at 1st to identify them, then reset them.

I think unique floating-point values are your only viable solution. You can’t store a tag on a per-vertex basis.

David

This is when they always say, “Surely, there must.”