Oops! Sorry, the problem was really obvious All my models already have identity matrix, I just scale them in my program. However, since Iām going to do a level editor, scaling collision geometry along with objects is a necessary feature. I guess that means that after any scale modification Iāll have to create new collision shape?
Just do root.flattenLight() to bake any scales into the vertices.
David
Nope, that doesnāt work. Perhaps enn0x can override flattening methods to work on collision shapes, but itās not there yet. Perhaps Iāll just use an old build until scale synchronization will be fixed
I have to wait until panda\src\display\graphicsEngine.cxx is fixed again in CVS HEAD before I can investiagate further.
FYI: Flattening is marked as unsafe for all PandaNodes in the Bullet module.
What, is graphicsEngine.cxx broken right now?
Edit: ah, so it was. My bad, I forgot to check in a dependent file. Fixed.
David
Thank you David.
I found the problem. Seem like I have been too eager with optimizing. I passed a CPT(TransformState) by reference, which actually allows the called method to alter the transform state. Fixed it in CVS. Scale should work again. Sorry.
Edit: the latest snapshot build contains the fix.
Thanks! Now static geometry is scaled appropriately.
However, now scaled dynamic objects behave weird. In my particular case, I have a code like this:
def LoadShip(self):
_scl = 0.5
scl = Vec3(_scl, _scl, _scl)
ship = loader.loadModel("ship/ship")
ship.setScale(scl)
shape1 = BulletConvexHullShape()
shape1.addGeom(GetCollider(ship, "**/coll_hull", True))
shape1.setLocalScale(scl)
shape2 = BulletConvexHullShape()
shape2.addGeom(GetCollider(ship, "**/coll_top", True))
shape2.setLocalScale(scl)
self.ship = self.RigidBody([shape1, shape2], 1.0, False)
ship.reparentTo(self.ship)
self.ship.setScale(1.0 / _scl)
def RigidBody(self, shapes, mass=0, use_gravity=True, name="rigidbody"):
node = BulletRigidBodyNode(name)
node.setMass(mass)
for shape in shapes:
node.addShape(shape)
if not use_gravity: node.setGravity(Vec3(0, 0, 0))
np = render.attachNewNode(node)
self.world.attachRigidBody(node)
node.setPythonTag("NodePath", np)
return np
This is a hacky solution to make my ship more sensitive to torque while preserving its size and mass (I couldnāt find the API to change moment of inertia).
In 295 Windows build this code makes resulting collision shape twice as big as visible ship, and it looks like the shape often ānoticesā collisions when it already noticeably penetrated other object.
Of course, when I remove all scaling, the collisions are stable.
By the way, is there already a way to get/set moment of inertia?
Looking at your code you set scale at three places:
1.) The rigid body node
2.) The shapes
3.) The visual node, which is parented to the rigid body node!)
You should do it this way:
1.) set the scale on the rigid body node
The visual node is reparented to the rigid body node, so any scale set on the rigid body node is automatically set on all child nodes too.
The method shape.setLocalScale() is no longer required, since we internally call this method when the rigid bodyās scale has changed. I will remove the method one of the next days.
Inertia is currently re-computed automatically every time a shape is added or removed, or if the mass is changed. So far I didnāt want to expose a manual way to set inertia. However, I am aware that there are use cases for this. I will think about this a little bit. Maybe we can support both, automatic and manual.
About the interpenetration: this is to be expected when using scale on physics/collision nodes. I did warn you guys about this, repeatedly!
Previously I had some experience with Newton physics libraryā¦ It allowed to build a compound collision shape out of arbitrarily transformed primitive/convex shapes; I donāt remember exactly, but perhaps it was just converting them to convexes.
If I wanted to scale collision shape along with object, it was simply a matter of recreating the shape with different transformation matrices.
Iām not sure about raw PhysX, but in Unity this is even more simple: a bodyās shape is composed of its own collision component and all collision components of the children. If you move/rotate/scale these children, collision shape is updated accordingly.
To be honest, until recently I thought you were doing something similarā¦ Could you shed some light on your current design?
When using bullet default character controller, i noticed that character is kind of warpingā¦
It is evident in your(ennox) sample (sample 14) too.
Try walking in one direction, character will not move at
steady speed, itās not smooth, it will kind of stutter.
I think it also happens with rigid body (kinematic), if i move nodepath with āsetPosā, but in that case it is much much less noticeable.
Maybe i am even imagining itā¦
Is it(should it be) possible to move characterController np with setPos?
like:
node = BulletCharacterControllerNode(shape, 0.4, 'Player')
np = render.attachNewNode(node)
np.setY(np,1) #in real app, i would make it dependant on delta time
Platform win7 x64,panda build from september 6th.
Well, it is possible. But this is not the right way to move a character. The difference between setPos and moving the character with linear/angular speed is that setPos kinda teleports the character to the new location, without moving it along the space in between. At first this might not seem like a bad thing, if setPos is called every frame. But the poble is that setPos might place the character right inside the middle of some other object, and in the following frame huge forces will be applied. Moving the character with linear/angular speed checks for obstacles, and uses a ācollide and slideā algorithm.
We have to expose both ways of moving a character. setPos internally calls the Bullet btKinematicCharacterController method āwarpā. What I have done is to exchange the method called when moving with linear/angular speed. Previously it has been setVelocityForTimeInterval(v, dt). Now I used setWalkDirection(v * dt). Maybe the characters now move a bit more fluent.
Similar to the Newton (2.x) way, or similar to the Unity way? Those are different concepts, and also different from the way PhysX. I donāt understand what you want to tell me here. Should I try to mimic on of these concepts? I try to stick as close as possible to the Panda3D scene graph concept. Maybe you can phrase some concrete questions.
@enn0x
Just tried new panda build, it is still very ālaggyā.
I am using .setLinearVelocity()
It happens even when character is in air.
(I played with friction in fear that it may cause that warping effect, so tried jumping, but it is still very visible)
EDIT1: i took a look at source of bullet character controller, and i donāt have any idea why that would happen.
That last change should not be relevant, both end up calling stepForwardAndStrafe().
Could this be one way or another related to the same issue I flagged in June, ie movement lagging ? (btw. as of today Iāve not found a clear explaination)
This lag phenomenon is really a riddleā¦
I donāt think that is relevant, because issue is not visible if you use setPos on NP to rigidBodyNode.
And whole NP is lagging, its not just debug node.
Well the whole NP is lagging for me too and not only in debug mode!
It is just that by displaying the debug bound geometries attached to kinematics nodes, the phenomenom is even more apparent since the Bullet nodes appear to be left behind and every couple of frame are pulled back to the actual node positionā¦
I sincerely apologize
I meant āsimilar to Unityā, since Newtonās way is manual and as so doesnāt have any scale synchronization.
Here are the more (I hope) concrete questions:
-
If a rigidbody is parented to some node, what are your plans to handle this? I can see here the following options:
a) Rigidbody ingnores its parent (behaves as if parent was absent).
b) Rigidbody is excluded from the simulation until it gets rid of the parent.
c) If top-level parent is a body itself, the child bodyās shape is added to parentās shape. When the child becomes free, the shape is removed from parent.
d) Same as previous + childās mass is also added to/subtracted from parentās mass (and center of mass & inertia recalculated).
Depending on the situation, any of these options might be desirable, but (d) seems to be the most intuitive (aka āfastened bodiesā). So, the question: which behavior should we expect in PandaBullet, or will we be able to select the one we need? -
Even if (c) or (d) will not be the default behavior, itās still possible to add arbitrarily transformed collision shapes (like in Newton). However, current BulletBodyNode API seems to lack methods to remove some/all shapes. Recreating the whole BulletBodyNode seems like overkillā¦ I suppose shape removal methods will be added at some point?
-
With (c) and (d) thereās also the issue of synchronization. Any modification to childās matrix/shape/mass/etc. would require recalculating shape/mass/etc. for top-level parent body. This is doable (though noticeably more cumbersome if done through python-level API)ā¦ But I guess such deep synchronization is not in your plans. Or is it?
Well, there are several places which might be the origin for this, not only the PandaBullet module: your python code (or my python samples), Panda itself, or Bullet itself. The character controller is not really a figurehead of Bullet - currently there are still lots of features missing, like for example proper collision response.
Anyway, a perceived lag is not enough. If we want to find the cause we first have to create a (1) reproducable and (2) measurable effect. And this is where you could help.
A starting point would be to write a python sample in which a character controller is moving at a constant speed in one direction. The lag should be perceivable here too. Next we need to quantify the lag. This means to observe the amount of movement each frame (read the nodeās position, calculate delta, and convert it to speed using the time elapsed between two frames). Log all these values to a text file. If there is a measurable lag then there should be a one or more frames where the speed drops significantly (drop to zero, or just get a few percent slower?). Oh, and it might be worth to also add not only the elapsed time provided by Panda3D, but also the real time. Iām not talking about secure time like in SRTP - the Python time.time should be enough.
Once we have measure the lag we can go on and try to locate the cause.
Here is basic sample, going to write some statistics gathering code next.
pastie.org/2505119
EDIT1:
Here is basic snippet for viewing speed
pastie.org/2505153
try to change sync video to true to fix not moved bug.
I left unlimited FPS, because those 0.0 while moving look bad.
And here is text data from sample run (with sync video on). Moving only in y-positive direction, removed rotation (setH on character) from code.
pastie.org/2505179
(a) is the option which is currently realized, and there are no plans to change this behavious. Each rigid body is a single node. A rigid body can have more than one shape, but it still is one rigid nody. For example a table could be made from five boxes, one for the table plate and four for the table legs.
If there are āremovableā parts, for example an aircraft carrying a bomb, then the aircraft and the bomb would be two bodies, and the bomb should be fixed to the aircraft using a joint. With PhysX it is possible to define how much force has to be applied until the joint breaks. With Bullet Iām not yet sure how to realize this.
Option (d) would mean that internally there is only one Bullet body, and I have to add up mass and inertia internally. This is something you could do one the Python side yourself, and then just create one BulletRigidBodyNode.
Regarding such thing my strategy is to keep as close to the original physics engines as possible.
For certain combinations of objects I want to add meaningfull parent/child relationships:
ā a ghost obects being the child of a rigid/soft/character, i.e. example a sensor zone which moves with a body.
ā a character controller being the child of a rigid body, i.e. a character on a moving platform. Because Bulletās character controllers are kinematic and donāt care about friction between the charcter and the ground on which it moves.
Actually, the first case has been implemented until I redesigned the internal synchronisation mechanism two weeks ago. Currently it is disabled, but will be back.
Current BulletBodyNode API has both addShape and removeShape methods, so it is possible to remove some/all shapes.
https://www.panda3d.org/reference/devel/python/classpanda3d.bullet.BulletBodyNode.php
It wonāt be possible to add arbitrarily transformed collision shapes. It is possible to add shapes with offset and rotation. And it is possible to apply a scale, but the scale will be applied to all shapes. It wonāt be possible to apply shear.
None of the big commercial physics engines support transforms beyond translation + orientation, and this has a reason. Iām in doubt if non-uniform scale and shear can be supported properly. It is not only the effect on collision detection, but also on inertia and contact response. If Newton 2.x handles these things corretly then I have highest respect for Julio Jerez. Anyway, Bullet donāt support arbitrary transforms, and I canāt add this feature on the wrapper/integration layer. You might want to talk to the Bullet developers here.
Of course. Any change of transforms within the subtree lead to modified mass properties and some other effects. Since the Panda3D scene graph doesnāt provide the necessary hook I would have to check all physics nodes each frame, calculate their delta transforms, and so onā¦ costs some performance.
What I currently do is to loop over all physics nodes each frame twice, once before stepping the simulation and once after stepping the simulation. Before I do the Panda3Dā>Bullet sync, and afterwards the Bulletā>Panda3D sync.