A place to discuss everything related to Newton Dynamics.
Moderators: Sascha Willems, walaber
by Julio Jerez » Sun Sep 29, 2013 6:36 pm
Ok, Here is a solution I propose.
I can write you a small function that given the point cloud, can create a reduce set of Boxes to pass to the scene collision.
I can see for example that for the point set that you passed, it will pas just one box.
The function should takes of the order of few microsecond to prose all the point, I down that will take more that a milliseconds even for an data set of billions points.
so you can use for real time.
do you think that could work for you?
-
Julio Jerez
- Moderator

-
- Posts: 12426
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Julio Jerez » Sun Sep 29, 2013 6:40 pm
if this is acceptable, in this code
- Code: Select all
for (int x = -512; x < 512; ++x)
{
for (int z = -512; z < 512; ++z)
{
Vector3i blockPosition(x, 0, z);
void* collisionNode = NewtonSceneCollisionAddSubCollision(sceneCollision, boxCollision);
NewtonSceneCollisionSetSubCollisionMatrix(sceneCollision, collisionNode, Matrix4x4::Translation(Vector3f(blockPosition)).Base());
}
}
How do you determine if a point is occupided of not? can you write and more representative code? so that I can see hwo to make more efficient for the scene collsion?
-
Julio Jerez
- Moderator

-
- Posts: 12426
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Layla » Sun Sep 29, 2013 6:42 pm
I think the problem with that would be the speed of re-adding all of the boxes on level edit. Unless there's a way to remove and add only the boxes that change.
Sure, I'll write something up now.
-
Layla
-
- Posts: 54
- Joined: Sat Sep 28, 2013 11:56 am
by Layla » Sun Sep 29, 2013 6:50 pm
This is just a rushed piece of code that I'm using now, it should give you an idea of what I need. I don't handle removing and adding of collision boxes after this is made yet.
IsBlockTypeSolid just checks a byte in an array to see if the block type is a solid type or not, so a block type of zero is air and is not solid.
- Code: Select all
void World::BuildPhysicsMap()
{
NewtonCollision* sceneCollision = NewtonCreateSceneCollision(m_physicsWorldNewton->GetNewtonWorld(), 0);
NewtonSceneCollisionBeginAddRemove(sceneCollision);
NewtonCollision* boxCollision = NewtonCreateBox(m_physicsWorldNewton->GetNewtonWorld(), 1.0f, 1.0f, 1.0f, 0, NULL);
LevelDefinition& levelDefinition = m_level->GetDefinition();
const Vector3i& levelSize = levelDefinition.GetSize();
size_t blockIndex = 0;
// loop through every cell in the map to find cells that need a collision box
for (int y = 0; y < levelSize.y; ++y)
{
for (int z = 0; z < levelSize.z; ++z)
{
for (int x = 0; x < levelSize.x; ++x)
{
// only blocks that are solid need a collision box
if (levelDefinition.IsBlockTypeSolid(levelDefinition.GetBlockType(blockIndex)))
{
Vector3i blockPosition(x, y, z);
// check all 6 adjacent blocks, if all 6 are solid then this block doesn't need a collision box
for (size_t faceDirection = 0; faceDirection < 6; ++faceDirection)
{
// found a side that's exposed so a collision box is needed
if (!levelDefinition.IsBlockTypeSolid(levelDefinition.GetBlockType(LevelDefinition::GetAdjacentPosition(blockPosition, faceDirection))))
{
Vector3i blockPosition(x, y, z);
// add the sub collision box and move it
void* collisionNode = NewtonSceneCollisionAddSubCollision(sceneCollision, boxCollision);
NewtonSceneCollisionSetSubCollisionMatrix(sceneCollision, collisionNode, Matrix4x4::Translation(Vector3f(blockPosition)).Base());
// don't need to check the other sides
break;
}
}
}
blockIndex++;
}
}
}
NewtonSceneCollisionEndAddRemove(sceneCollision);
NewtonDestroyCollision(boxCollision); // is this needed anymore?
PhysicsBodyNewton* physicsBodyBlocks = new PhysicsBodyNewton(*m_physicsWorldNewton, sceneCollision);
physicsBodyBlocks->SetMass(0.0f);
}
-
Layla
-
- Posts: 54
- Joined: Sat Sep 28, 2013 11:56 am
by Layla » Sun Sep 29, 2013 10:58 pm
So I got this working in a typical level and results are good speed wise. Memory isn't a huge problem if I'm careful but it potentially could be an issue depending on the map. I also need to keep an integer lookup for every single block so I can find the scene shape index to remove the physics block when I remove a block from the level. This is 32 megs for a 256x128x256 size level. Not crazy but it seems really unnecessary.
I also just noticed that I can't add or remove anything from the scene collision once I've made the rigid body.
Solved that. I had to get the scene collision back from the body and store that instead of the scene collision I pass into the body. Just incase anyone else has that same problem.
Is it safe to save the index from NewtonSceneCollisionGetNodeIndex to use as a handle to remove collisions?
-
Layla
-
- Posts: 54
- Joined: Sat Sep 28, 2013 11:56 am
by Julio Jerez » Mon Sep 30, 2013 6:57 am
Layla wrote:Is it safe to save the index from NewtonSceneCollisionGetNodeIndex to use as a handle to remove collisions?
yes.
-
Julio Jerez
- Moderator

-
- Posts: 12426
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Layla » Mon Sep 30, 2013 2:22 pm
It doesn't seem to be and I'm sure I'm doing everything correct. I create a vector full of indices so I can lookup the index from a block index. If I for example, remove a block from the level and add a block back in, the nodeCollision pointer returned from NewtonSceneCollisionAddSubCollision is NULL and I can't figure out why. Because of that I get a crash on NewtonSceneCollisionGetNodeIndex.
- Code: Select all
void World::BuildPhysicsMap()
{
NewtonCollision* sceneCollision = NewtonCreateSceneCollision(m_physicsWorldNewton->GetNewtonWorld(), 0);
m_boxCollision = NewtonCreateBox(m_physicsWorldNewton->GetNewtonWorld(), 1.0f, 1.0f, 1.0f, 0, NULL);
m_physicsBodyBlocks = new PhysicsBodyNewton(*m_physicsWorldNewton, sceneCollision);
m_physicsBodyBlocks->SetMass(0.0f);
m_sceneCollision = NewtonBodyGetCollision(m_physicsBodyBlocks->GetNewtonBody());
NewtonDestroyCollision(sceneCollision);
//NewtonSceneCollisionBeginAddRemove(m_sceneCollision);
LevelDefinition& levelDefinition = m_level->GetDefinition();
const Vector3i& levelSize = levelDefinition.GetSize();
size_t blockIndex = 0;
m_physicsBlockIndices.resize(Util::GetVectorVolume(levelSize));
// loop through every cell in the map to find cells that need a collision box
for (int y = 0; y < levelSize.y; ++y)
{
for (int z = 0; z < levelSize.z; ++z)
{
for (int x = 0; x < levelSize.x; ++x)
{
// only blocks that are solid need a collision box
if (levelDefinition.IsBlockTypeSolid(levelDefinition.GetBlockType(blockIndex)))
{
Vector3i blockPosition(x, y, z);
// check all 6 adjacent blocks, if all 6 are solid then this block doesn't need a collision box
for (size_t faceDirection = 0; faceDirection < 6; ++faceDirection)
{
// found a side that's exposed so a collision box is needed
if (!levelDefinition.IsBlockTypeSolid(levelDefinition.GetBlockType(LevelDefinition::GetAdjacentPosition(blockPosition, faceDirection))))
{
Vector3i blockPosition(x, y, z);
// matrix of the box collision
Matrix4x4 blockMatrix = Matrix4x4::Translation(Vector3f(blockPosition) + Vector3f(0.5f, 0.5f, 0.5f));
// add the sub collision box and move it
void* collisionNode = NewtonSceneCollisionAddSubCollision(m_sceneCollision, m_boxCollision);
NewtonSceneCollisionSetSubCollisionMatrix(m_sceneCollision, collisionNode, blockMatrix.Base());
// save the new node index
int nodeIndex = NewtonSceneCollisionGetNodeIndex(m_sceneCollision, collisionNode);
m_physicsBlockIndices[blockIndex] = nodeIndex;
// don't need to check the other sides
break;
}
}
}
blockIndex++;
}
}
}
//NewtonSceneCollisionEndAddRemove(m_sceneCollision);
}
void World::AddPhysicsBlock(const Vector3i& position)
{
// matrix of the box collision
Matrix4x4 blockMatrix = Matrix4x4::Translation(Vector3f(position) + Vector3f(0.5f, 0.5f, 0.5f));
// add the sub collision box and move it
void* collisionNode = NewtonSceneCollisionAddSubCollision(m_sceneCollision, m_boxCollision);
NewtonSceneCollisionSetSubCollisionMatrix(m_sceneCollision, collisionNode, blockMatrix.Base());
// save the new node index
size_t blockIndex = Util::Array1DFrom3DXZY(position, m_level->GetSize());
int nodeIndex = NewtonSceneCollisionGetNodeIndex(m_sceneCollision, collisionNode);
m_physicsBlockIndices[blockIndex] = nodeIndex;
}
void World::RemovePhysicsBlock(const Vector3i& position)
{
// lookup the node index
size_t blockIndex = Util::Array1DFrom3DXZY(position, m_level->GetSize());
int index = m_physicsBlockIndices[blockIndex];
// remove the box collision by index
NewtonSceneCollisionRemoveSubCollisionByIndex(m_sceneCollision, index);
// not needed anymore
m_physicsBlockIndices[blockIndex] = 0;
}
-
Layla
-
- Posts: 54
- Joined: Sat Sep 28, 2013 11:56 am
by Julio Jerez » Mon Sep 30, 2013 2:27 pm
you can set a break point on this function
- Code: Select all
void dgCollisionCompound::RemoveCollision (dgTree<dgNodeBase*, dgInt32>::dgTreeNode* const node)
{
if (node) {
dgCollisionInstance* const instance = node->GetInfo()->GetShape();
instance->AddRef();
RemoveCollision (node->GetInfo());
instance->Release();
m_array.Remove(node);
}
}
NewtonSceneCollisionRemoveSubCollisionByIndex(m_sceneCollision, index);
will call that and remove the node from the array, which is a map
all functions that change the a compound collision must be called from a
void NewtonSceneCollisionBeginAddRemove (NewtonCollision* const sceneCollision);
void NewtonSceneCollisionEndAddRemove (NewtonCollision* const sceneCollision);
-
Julio Jerez
- Moderator

-
- Posts: 12426
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Layla » Mon Sep 30, 2013 2:35 pm
That function seems to run as expected, doing everything it's supposed to do. The problem occurs when I add a block into the space I just removed (this doesn't happen if I add a new block after the world is created and I add/remove that one. That's why I think the indices aren't safe to use as handles. I'm trying to step through dgCollisionCompound::AddCollision to see why It's returning a NULL node pointer.
I did wrap any changes to the compound between NewtonSceneCollisionBeginAddRemove but the same problem still happens.
-
Layla
-
- Posts: 54
- Joined: Sat Sep 28, 2013 11:56 am
by Julio Jerez » Mon Sep 30, 2013 3:06 pm
Oh you are correct, I modified teh demo to re add a new shape, an dI do get a NULL poieten for handle.
- Code: Select all
void* handle1 = NewtonCompoundCollisionGetNodeByIndex (compound, 30);
void* handle2 = NewtonCompoundCollisionGetNodeByIndex (compound, 100);
NewtonCollision* const shape1 = NewtonCompoundCollisionGetCollisionFromNode (compound, handle1);
NewtonCollision* const shape2 = NewtonCompoundCollisionGetCollisionFromNode (compound, handle2);
NewtonCollision* const copyShape1 = NewtonCollisionCreateInstance (shape1);
NewtonCollision* const copyShape2 = NewtonCollisionCreateInstance (shape2);
// you can also remove shape by their index
NewtonCompoundCollisionRemoveSubCollisionByIndex (compound, 30);
NewtonCompoundCollisionRemoveSubCollisionByIndex (compound, 100);
handle1 = NewtonCompoundCollisionAddSubCollision (compound, copyShape1);
handle2 = NewtonCompoundCollisionAddSubCollision (compound, copyShape2);
NewtonDestroyCollision(copyShape1);
NewtonDestroyCollision(copyShape2);
The bug is here
- Code: Select all
dgTree<dgCollisionCompound::dgNodeBase*, dgInt32>::dgTreeNode* dgCollisionCompound::AddCollision (dgCollisionInstance* const shape)
{
dgNodeBase* const newNode = new (m_allocator) dgNodeBase (shape);
// this will add the new shape to the end, howover is a shape was remove the count will decrease and if a new shape was added the line will fail.
newNode->m_myNode = m_array.Insert(newNode, m_array.GetCount());
I will fix it, I am not sure if I spodul jsut added to teh end, in whic case teh index become useless, and keep track of deleted indices.
or not use the index and only use the pointer as handle, and use a monotonically increasing nimber.
Using poitenr as handle lead to har to fidn bugs, becaus a memory manegt cna return teh same pointer.
I think I will add a monotonically increasing number, for each shape.
do you suggest oteh idea?
-
Julio Jerez
- Moderator

-
- Posts: 12426
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Julio Jerez » Mon Sep 30, 2013 3:13 pm
ok fixed, sync to svn.
-
Julio Jerez
- Moderator

-
- Posts: 12426
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Layla » Mon Sep 30, 2013 3:32 pm
Thanks, it's fixed for me now.
the NewtonSceneCollisionBeginAddRemove calls do make editing a bit too slow but it seems to work without them calls. I'll see if I can make do with scene collisions but native support for these kinds of environments would still be very beneficial I think. Scene Collisions are amazing for lots of different sized convex parts but for this I think it's the wrong tool for the job.
There still seems to be some crashing going on in compound when removing a bunch of blocks, I need to see if I can replicate it though.
Nevermind, it seems to be a problem in my code.
-
Layla
-
- Posts: 54
- Joined: Sat Sep 28, 2013 11:56 am
by Layla » Mon Sep 30, 2013 4:15 pm
Everything seems to be working well now. One problem I overlooked is when objects go to sleep and the blocks under them get removed, the body stays asleep. I'm thinking I can just do NewtonWorldForEachBodyInAABBDo, the AABB being the block(s) I remove and wake anything in there up. Is that the best way to go about it?
-
Layla
-
- Posts: 54
- Joined: Sat Sep 28, 2013 11:56 am
by Julio Jerez » Mon Sep 30, 2013 4:32 pm
yes. that will be a good way.
-
Julio Jerez
- Moderator

-
- Posts: 12426
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Julio Jerez » Mon Sep 30, 2013 4:39 pm
Layla wrote:the NewtonSceneCollisionBeginAddRemove calls do make editing a bit too slow but it seems to work without them calls. I'll see if I can make do with scene collisions but native support for these kinds of environments would still be very beneficial I think. Scene Collisions are amazing for lots of different sized convex parts but for this I think it's the wrong tool for the job.
Yes I agree, a spcial collsion that take abatange of the similarity will be a better solution. but yo ucn astill work with this until it bacome a real problem.
I hava a plan for a voxel collsion system for soft bodies and cloth, mayeb then I can add teh special Voxel static shape simulat to compounds
you could skip NewtonSceneCollisionBeginAddRemove fi you are editing the scene and you are not updation the simulation.
The you can NewtonSceneCollisionBeginAddRemove when you are abput to simulation.
-
Julio Jerez
- Moderator

-
- Posts: 12426
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
Return to General Discussion
Who is online
Users browsing this forum: No registered users and 2 guests