PhysX

Yep. This is even possible from Python. You only need to use GeomVertexWriter if your data is not already formatted for rendering; if it is already in a block of data ready to be rendered, then you can just stuff it directly in a GeomVertexArrayData.

The trick is to create the appropriate GeomVertexFormat structure that accurately represents your one or several arrays. Set this format on your GeomVertexData, and it will create the corresponding GeomVertexArrayData objects. Then for each GeomVertexArrayData you can call data.modifyHandle().setData(string) to stuff a Python string into the data buffer, very quickly.

David

thanks for your quick and profound replies! as i am quite happy for now with cloth rendering performance (even tearing works fine if you allocate enough memory) i will change the softbody source to act like the cloth source. but good to know that there is direct access too!

…falling more and more in love with panda :slight_smile:

regards
β

one question concerning triggers: i want to catch the onTrigger callback with the NxUserTriggerReport class. i thought i have to define a new python class which inherits from NxUserTriggerReport like this:

class sbTriggerReport(DirectObject, Nx.NxUserTriggerReport):

    def onTrigger(self, shape1, shape2, status):

in my app i do this:

self.triggerReporter = sbTriggerReport()
self.scene.setUserTriggerReport(self.triggerReporter)

but unfortunately onTrigger never gets called

if i do it like this:

self.triggerReporter = Nx.NxUserTriggerReport()
self.scene.setUserTriggerReport(self.triggerReporter)

i get an error when an object enters the trigger (which proofs that the trigger itself is set up correctly):
AttributeError: onTrigger

so how should i do this correctly? (i’m still a python noob…)

thanks!

The problem is the way Python handles multiple inheritance. You derive sbTriggerReport from DirectObject AND NxUserTriggerReport. In this case you have to call the init methods yourself, for example like this:

class sbTriggerReport(DirectObject, Nx.NxUserTriggerReport):

    def __init__( self ):
        Nx.NxUserTriggerReport.__init__( self )
        DirectObject.__init__( self )

    def onTrigger(self, shape1, shape2, status): 

I think you can leave away the DirectObject init call, but you can not leave away the NxUserTriggerReport call.

With single inheritance you don’t need an explicit init method. If no init method is found on the object, then the init method of the parent object is called. But with two parents the compiler doesn’t know what to do (call both, but in which order?).

If you don’t need the DirectObject inheritance then you should leave it away, or handle user input in another object (not the trigger callback object).

enn0x

ah ok that sounds reasonable… i just wanted the DirectObject for receiving events from the messenger.

so now i try to implement the direct passing the pointers of mesh data from ageia to panda. i understand the structures and formats of GeomVertexData, but i dont understand what to do with GeomVertexArrayDataHandle.setData(string):

e.g. for the vertex data: ageia gives me a pointer to the beginning of a bunch of vertices (one vertex occupies 3 float32), and it tells me how many vertices there are. so i will create one GeomVertexArrayData which holds only the vertices (GeomVertexFormat.getV3()), get the handle to it, and then i call setData

but what should i pass here? the pointer to the first vertex as a string?
the API says it replaces this string replaces the whole raw array data, so do i have to pass the content of the whole array? wouldnt this mean that all the data gets copied again?

thanks for your help!

void GeomVertexArrayDataHandle::set_data(string const &data);

This one? Here data get passed by reference (&), so it is not copied.
Maybe a reinterprete cast helps. Haven’t been working with these methods so far.

yes this one, but in the c++ source it looks like there is something copied:

void GeomVertexArrayDataHandle::set_data(const string &data) {
...
_cdata->_buffer.unclean_realloc(data.size());
memcpy(_cdata->_buffer.get_write_pointer(), data.data(), data.size());
...

or does that mean that just the adress of this string is copied?

anyway, another question is how to pass the pointer of the indices array to GeomTriangles? i couldnt find a handle or setData method. maybe they would still have to be copied…

Ah… ok, you are right. memcpy is a standard C function defined in string.h. It makes a binary copy. I would guess this is still way faster than feeding every vertex by hand to GeomVertexWriter.

Thanks drwr for this tip. Next time I touch the mesh code I will try to use the GeomVertexArrayData.

enn0x

i just installed panda3d 1.5.
when importing NxPanda, i get the following error (in german):
“Der Prozedureinsprungpunkt “?_global_ptr@ObjectDeletor@@0PAXA” wurde in der DLL “libpandaexpress.dll” nicht gefunden”
any ideas how to solve this?

greets

By compiling NxPanda for Panda3D 1.5.0. The current binaries are compiled for Panda3D 1.4.2.

I don’t have Panda3D 1.5.0 installed right now, and I am using a different version of the PhysX SDK. But I think I have some spare time during the easter days. So perhaps I can compile it for you. It not, the source is included.

enn0x

ohhhh sure… what a dumb question, sorry i am stupid hehe…
anyway, thanks for your answer!
for anyone who needs it, here is the NxPanda.pyd for panda 1.5

http://kampfgnu.ka.funpic.de/stuff/NxPanda.zip

greets, kampfgnu

p.s.: ennox, thanks for sharing your work, ageia rocks

Not a dumb question. I think I should have compiled right after 1.5.0 was released. Thanks for sparing me some work :slight_smile:

Here is some new info releated to NxPanda:

  • PhysX 1.8.0 is out, but there are major changes in the API, and NxPanda won’t compile out of the box for the new SDK version.

  • Nvidia has bought AGEIA. Nvidia has not revealed their plans yet. I don’t know if Nvidia wants to continue separate physics hardware cards, or if they want to integrate the chips on their graphics cards (maybe to push users to buy SLI systems?). Whatever, I guess they will continue to use the SW physics engine. Hopefully with a royalty-free license form too.

  • I am currently not improving NxPanda, but started a new PhysX project which integrates PhysX and Panda3D much stronger. I won’t be a native Python extension but will use interrogate for wrapping to Python. And so far it compiles on Linux too.

  • Since this has come up in several other threads: I don’t think NxPanda can ever be part of Panda3D, like for example pro-rsoft’s PGMM module. This is not because I don’t want to, but because the PhysX license. Well, maybe this changes too with Nvidia.

enn0x

so you mean nxpanda will “die”/you won’t go on working on it ?
and your new physX-project…do you again use ageia?

i will soon do a project for university (making a game), that i would really like to make with panda and nx (or maybe your new physxs-thing). do you think this is just a dream :cry: ?

ok and another question concerning the current nxPanda:
i am trying to limit a joint:

jointDesc.flags |= 1 #NX_RJF_LIMIT_ENABLED
jointDesc.limit.high.value = 0.25*math.pi
jointDesc.limit.high.restitution = 1
jointDesc.limit.low.value = -0.25*math.pi
jointDesc.limit.low.restitution = 1

but i get this error:
“AttributeError: attribute ‘limit’ of ‘NxPanda.NxRevoluteJointDesc’ objects is not readable”

the same here:

jointDesc.flags |= 1
limit = Nx.NxJointLimitPairDesc()
limit.high.value = 0.25*math.pi
limit.high.restitution = 1
limit.low.value = -0.25*math.pi
limit.low.restitution = 1
jointDesc.limit = limit

AttributeError: attribute ‘high’ of ‘NxPanda.NxJointLimitPairDesc’ objects is not readable

what can i do?

This “new” Project is PhysX too. AGEIA is the name of the company, and PhysX the name of the physics engine. So no, it won’t die. I just try to figure out how to make NxPanda more “Panda3D-like”, and take lots of the complexity away into the C++ layer. It will be a step back for the first time though, since I focus on “basic” features: rigid body & character controllers. Oh, and Linux too :slight_smile:

Adapting NxPanda from PhysX 2.7.3 (current) to 2.8.0 will be about 40 hours of (boring) work. More than I have in the next two month, so it will be some time before this happens. But I will continue (slow) work on NxPanda. right now I suggest you stick with the current 2.7.3 bindings.

Right. I didn’t implement getters for these attributes. ThePython wrapper objects are structs for C++ pointer (even the “desc” objects). I have considered making getters too, using the template below, but then I would have a problem if the new PyObject deallocated while the “original” PyObject is still in use. So I decided not to implement getters (only setters).

template<typename V, typename T>
static inline PyObject *
getter_value( const V &value, T * &_o, PyTypeObject &type )
{
    _o = PyObject_New( T, &type );
    _o->ptr = &value;
    return (PyObject *)_o;
}

You can work around this by using only setters. More complex, but it should work. Not tested though…

highLimit = JointLimitDesc( )
highLimit.value = 0.25*math.pi
highLimit.restitution = 1

lowLimit = JointLimitDesc( )
lowLimit.value = -0.25*math.pi
lowLimit.restitution = 1

limit = Nx.NxJointLimitPairDesc()
limit.high = highLimit
limit.low = lowLimit

jointDesc = NxJointDesc( )
jointDesc.flags |= 1
jointDesc.limit = limit

enn0x

how can i access a joint after creation?

#create revolutejoint
joint = self.scene.createJoint( revjointDesc )
print joint

<NxPanda.NxRevoluteJoint object at 0x00A5C1E0>

joint.getFlags()

AttributeError: ‘NxPanda.NxRevoluteJoint’ object has no attribute ‘getFlags’

when i do a “print dir(joint)”, i get the functions of NxJoint.
i tried to cast the joint (although it still seems to be a NxRevoluteJoint):

Nx.NxRevoluteJoint(joint).getFlags()

TypeError: cannot create ‘NxPanda.NxRevoluteJoint’ instances

greets

I just looked at the source, and… well, none of the NxRevoluteJoint methods are wrapped. Same for most other joint types. It wouldn’t be hard to add these methods, just apply the same pattern as found in other objects. NxPanda is far away from being complete, I know.

By the way: casting is something you can do in C++ and some other languages, but not in Python. And I think this is a good thing.

(Almost) all NxPanda objects are created using factory methods, which take an descriptor object as argument. So I have explicitly disallowed to create the Python wrapper objects for these classes.

enn0x