A place to discuss everything related to Newton Dynamics.
Moderators: Sascha Willems, walaber
by Cannos » Mon Sep 19, 2016 8:46 pm
First, I apologize if this has been asked and answered before. I searched through the forums and saw many threads discussing similar things. But some info is old, incomplete, or confusing. So here goes:
I want to move an infinite mass body and for it to push dynamic objects around. Basically a moving platform with infinite mass. What is the best way to do this?Notes:
- In other physics engines, this might be called kinematic, but one of the posts I read suggested that Newton kinematic bodies needed a finite mass. So I wasn't sure if kinematic bodies were the right thing.
- Plus, I am still on Newton 2.0 and it doesn't have NewtonCreateKinematicBody.
- I tried using a joint as suggested here but that also doesn't work with infinite mass bodies either.
I am willing to move to Newton 3.0 if I need to, but a solution for Newton 2.0 would be appreciated too, if possible. Thanks for the help!
-
Cannos
-
- Posts: 129
- Joined: Thu Mar 04, 2010 5:41 pm
by JoeJ » Tue Sep 20, 2016 3:33 am
1. You can attach a kinematic joint to a dynamic body with mass, and so move it at will.
This works for 2.0. You can also set a maximum force for the joint ('maxFriction'), so the body will still stop, e.g. if a barrel is below an elevator.
2. You can use a kinematic body and move it at will.
You should also set the velocity of that body to the correct value to ensure other bodies move properly, e.g. to make a barrel on top a platform move along with it as expected.
This works with infinite mass, but is not recommended. IIRC infinite mass can cause huge contact forces, setting mass keeps them in reasonable values.
Looking at elevator above barrel example again, with this method the barrel will either go through the elevator or the floor, but the elevator will follow your settings exactly.
The update to 3.x should only take a hour, recommended anyways
-
JoeJ
-
- Posts: 1453
- Joined: Tue Dec 21, 2010 6:18 pm
by Cannos » Tue Sep 20, 2016 1:14 pm
I need an infinite mass platform to guarantee it will be at the exact location specified. So the platform shouldn't have any forces applied to it by dynamic bodies it is pushing, nor should it have any limitations to it's movement imposed by joint min/max limits. So it sounds like the 2.0 version with joints probably won't work for this case.
I played around a bit with infinite mass kinematic bodies in the 3.x samples but also couldn't get the behavior I was expecting. I'll keep looking at that and post results.
-
Cannos
-
- Posts: 129
- Joined: Thu Mar 04, 2010 5:41 pm
by Julio Jerez » Tue Sep 20, 2016 1:35 pm
if you play 3.xx, check out the player controller. It is made of kinematic bodies.
In Newton, bodies with infinite mass are not considered kinematic.
you can move them around but that is not advised since they will generate infinite collision impulse.
for that 3.0 has the kinematic body which are bodies that can have mass and velocity by the have not update position and velocity update, you need to move then manually
-
Julio Jerez
- Moderator
-
- Posts: 12249
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Cannos » Tue Sep 20, 2016 2:09 pm
I just tried out the player controller example in the latest code and it looks like it has the behavior I want. Basically a body that can be moved manually, can push dynamic bodies, and will not be pushed back. Thanks, I will look into it further.
-
Cannos
-
- Posts: 129
- Joined: Thu Mar 04, 2010 5:41 pm
by JoeJ » Tue Sep 20, 2016 2:12 pm
reply to late, but anyways...
Cannos wrote:platform to guarantee it will be at the exact location specified. So the platform shouldn't have any forces applied to it by dynamic bodies it is pushing, nor should it have any limitations to it's movement
This is exactly what kinematic bodies are doing, keep in mind:
You set mass only to avoid infinite impulses on other bodies.
You set velovity only to affect other bodies in contact.
Neither of both settings have any effect one motion of the kinetic body itself, you have full control of it's position.
E.g. if you set velocity, a dynamic body on top will move like on a conveyor belt, but the kinetic body does not move anywhere.
-
JoeJ
-
- Posts: 1453
- Joined: Tue Dec 21, 2010 6:18 pm
by Cannos » Tue Sep 20, 2016 2:22 pm
Great, yeah that sounds like what I need. When I was trying kinematic bodies with mass in the 3.xx examples they weren't behaving right, so I must have had something set up wrong.
Last edited by
Cannos on Tue Sep 20, 2016 7:08 pm, edited 1 time in total.
-
Cannos
-
- Posts: 129
- Joined: Thu Mar 04, 2010 5:41 pm
by Cannos » Tue Sep 20, 2016 6:03 pm
Okay looks like one problem I had is that I forgot to call NewtonBodySetCollidable(kinematicBody, true). Once I put that in, the kinematic body started pushing the dynamic ones around.
So it is now pushing dynamic bodies, but I'm seeing a fair amount of penetration, even with a very large kinematic body mass. Dynamic bodies are mass=1, I've tried masses up to 10000 for the kinematic body. I am setting both the position and velocity of the kinematic body.
Any ideas on how to decrease the penetration?
-
Cannos
-
- Posts: 129
- Joined: Thu Mar 04, 2010 5:41 pm
by JoeJ » Wed Sep 21, 2016 1:32 am
My guess is that you calculate velocity wrong, and because of this collisions are not resolved by collision responce, but by error correction.
With error correction i mean Newtons behaviour to seperate intersecting bodies just slowly at constant speed.
This could be explain it, experiment with large velocity constants to see what effect they have to proof given velocity is working at all.
If you don't think that's the reason post code and a video.
A little bit of interpenetration is normal. I use kinetic platforms to test balancing ragdoll (which is worst case because multi 20 bodies system resting an a single platform), and there i get penetration of about 1 cm.
-
JoeJ
-
- Posts: 1453
- Joined: Tue Dec 21, 2010 6:18 pm
by Julio Jerez » Wed Sep 21, 2016 11:29 am
setting a mass of so high render the thing useless.
you need to set the velocity and angular velocity currently, there is a function that you can use to integrate the body.
can you make a video so that I can see what is it that you are try to do?
-
Julio Jerez
- Moderator
-
- Posts: 12249
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Cannos » Wed Sep 21, 2016 7:07 pm
Here's a video of what I'm trying:
https://www.dropbox.com/s/dnd4nii3jwfe20y/kinematictest.mp4?dl=0This is a modification of the BasicRestitution sample. I just make a large kinematic box (the green one) and move it upward, then snap it back to the bottom and move it upward again in a cycle. You can see that the bottom sphere sinks into the kinematic box.
Here's the code for the modified BasicRestitution.cpp. The new part I added was the MovingPlatformEntity. Perhaps you can spot any mistakes I'm making:
- Code: Select all
/* Copyright (c) <2009> <Newton Game Dynamics>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely
*/
#include <toolbox_stdafx.h>
#include "SkyBox.h"
#include "DemoEntityManager.h"
#include "DemoCamera.h"
#include "PhysicsUtils.h"
#include "DemoMesh.h"
#include "OpenGlUtil.h"
static void UserContactRestitution (const NewtonJoint* contactJoint, dFloat timestep, int threadIndex)
{
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
dFloat mass;
NewtonBody* body;
NewtonBody* body0;
NewtonBody* body1;
// call the basic call back
GenericContactProcess (contactJoint, timestep, threadIndex);
body0 = NewtonJointGetBody0(contactJoint);
body1 = NewtonJointGetBody1(contactJoint);
body = body0;
NewtonBodyGetMass (body, &mass, &Ixx, &Iyy, &Izz);
if (mass == 0.0f) {
body = body1;
}
NewtonCollision* const collision = NewtonBodyGetCollision(body);
void* userData = NewtonCollisionGetUserData (collision);
dFloat restitution = *((dFloat*)&userData);
for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
NewtonMaterial* const material = NewtonContactGetMaterial (contact);
NewtonMaterialSetContactElasticity (material, restitution);
}
}
const float cMaxTime = 2.0f;
const dVector cStartPos(0.0f, -1.0f, 0.0f);
const dVector cEndPos(0.0f, 5.0f, 0.0f);
class MovingPlatformEntity : public DemoEntity
{
public:
MovingPlatformEntity(DemoEntityManager* const scene, int materialID) :
DemoEntity(dGetIdentityMatrix(), NULL),
m_boxBody(NULL),
elapsed(0.0f)
{
scene->Append(this);
NewtonWorld* const world = scene->GetNewton();
dMatrix offsetMatrix(dGetIdentityMatrix());
dVector boxSize(20.0f, 2.0f, 20.0f, 0.0f);
NewtonCollision* const boxCollision = CreateConvexCollision(world, offsetMatrix, boxSize, _BOX_PRIMITIVE, 0);
DemoMesh* const boxMesh = new DemoMesh("box", boxCollision, "smilli.tga", "smilli.tga", "smilli.tga");
DemoSubMesh& subMesh = boxMesh->GetFirst()->GetInfo();
dVector color = dVector(0.0f, 0.5f, 0.0f, 0.5f);
subMesh.m_specular = color;
subMesh.m_diffuse = color;
subMesh.m_ambient = color;
boxMesh->OptimizeForRender();
SetMesh(boxMesh, offsetMatrix);
dMatrix matrix(dGetIdentityMatrix());
matrix.m_posit.m_x = cStartPos.m_x;
matrix.m_posit.m_y = cStartPos.m_y;
matrix.m_posit.m_z = cStartPos.m_z;
float mass = 100.0f;
NewtonBody* const rigidBody = NewtonCreateKinematicBody(world, boxCollision, &matrix[0][0]);
NewtonBodySetMassProperties(rigidBody, mass, boxCollision);
NewtonBodySetUserData(rigidBody, this);
NewtonBodySetMaterialGroupID(rigidBody, materialID);
NewtonBodySetDestructorCallback(rigidBody, PhysicsBodyDestructor);
NewtonBodySetTransformCallback(rigidBody, DemoEntity::TransformCallback);
NewtonBodySetCollidable(rigidBody, true);
//NewtonBodySetForceAndTorqueCallback(rigidBody, PhysicsApplyGravityForce);
NewtonDestroyCollision(boxCollision);
m_boxBody = rigidBody;
elapsed = 0.0f;
}
virtual void SimulationPreListener(DemoEntityManager* const scene, DemoEntityManager::dListNode* const mynode, dFloat timestep)
{
if (m_boxBody)
{
elapsed += timestep;
if (elapsed > cMaxTime)
elapsed = 0.0f;
// Current position
dMatrix currentMtx;
NewtonBodyGetMatrix(m_boxBody, ¤tMtx[0][0]);
// Calculate desired position
float t = elapsed / cMaxTime;
dVector desiredPos;
desiredPos.m_x = cStartPos.m_x * (1.0f - t) + cEndPos.m_x * t;
desiredPos.m_y = cStartPos.m_y * (1.0f - t) + cEndPos.m_y * t;
desiredPos.m_z = cStartPos.m_z * (1.0f - t) + cEndPos.m_z * t;
// Set new position
dMatrix mtx(dGetIdentityMatrix());
mtx.m_posit.m_x = desiredPos.m_x;
mtx.m_posit.m_y = desiredPos.m_y;
mtx.m_posit.m_z = desiredPos.m_z;
NewtonBodySetMatrix(m_boxBody, &mtx[0][0]);
// Calculate velocity
dVector vel = desiredPos - currentMtx.m_posit;
vel.Scale(1.0f / timestep);
// Set velocity / angular velocity
NewtonBodySetVelocity(m_boxBody, &vel[0]);
dVector angVel(0.0f, 0.0f, 0.0f);
NewtonBodySetOmega(m_boxBody, &angVel[0]);
}
}
NewtonBody* m_boxBody;
float elapsed;
};
void Restitution (DemoEntityManager* const scene)
{
scene->CreateSkyBox();
// customize the scene after loading
// set a user friction variable in the body for variable friction demos
// later this will be done using LUA script
NewtonWorld* const world = scene->GetNewton();
dMatrix offsetMatrix (dGetIdentityMatrix());
int defaultMaterialID = NewtonMaterialGetDefaultGroupID (world);
NewtonMaterialSetCollisionCallback (world, defaultMaterialID, defaultMaterialID, NULL, UserContactRestitution);
CreateLevelMesh (scene, "flatPlane.ngd", 1);
dVector location (0.0f, 0.0f, 0.0f, 0.0f);
// create some spheres
dVector sphSize (2.0f, 2.0f, 2.0f, 0.0f);
NewtonCollision* const sphereCollision = CreateConvexCollision (world, offsetMatrix, sphSize, _SPHERE_PRIMITIVE, 0);
DemoMesh* const sphereMesh = new DemoMesh("sphere", sphereCollision, "smilli.tga", "smilli.tga", "smilli.tga");
// create some boxes too
dVector boxSize (2.0f, 2.0f, 2.0f, 0.0f);
NewtonCollision* const boxCollision = CreateConvexCollision (world, offsetMatrix, boxSize, _BOX_PRIMITIVE, 0);
DemoMesh* const boxMesh = new DemoMesh("box", boxCollision, "smilli.tga", "smilli.tga", "smilli.tga");
//int zCount = 10;
int zCount = 1;
dFloat spacing = 4.0f;
dMatrix matrix (dGetIdentityMatrix());
dVector origin (matrix.m_posit);
origin.m_x -= 0.0f;
// create a simple scene
for (int i = 0; i < zCount; i ++) {
dFloat restitution = i * 0.1f + 0.083f;
NewtonBody* body;
NewtonCollision* collision;
dFloat z;
dFloat x;
dFloat mass;
x = origin.m_x;
z = origin.m_z + (i - zCount / 2) * spacing;
mass = 1.0f;
matrix.m_posit = FindFloor (world, dVector (x, 100.0f, z), 200.0f);
matrix.m_posit.m_w = 1.0f;
matrix.m_posit.m_y += 6.0f;
body = CreateSimpleSolid (scene, sphereMesh, mass, matrix, sphereCollision, defaultMaterialID);
NewtonBodySetLinearDamping (body, 0.0f);
collision = NewtonBodyGetCollision(body);
NewtonCollisionSetUserData (collision, *((void**)&restitution));
matrix.m_posit.m_y += 6.0f;
//body = CreateSimpleSolid (scene, boxMesh, mass, matrix, boxCollision, defaultMaterialID);
body = CreateSimpleSolid (scene, sphereMesh, mass, matrix, sphereCollision, defaultMaterialID);
NewtonBodySetLinearDamping (body, 0.0f);
collision = NewtonBodyGetCollision(body);
NewtonCollisionSetUserData (collision, *((void**)&restitution));
matrix.m_posit.m_y += 6.0f;
body = CreateSimpleSolid (scene, sphereMesh, mass, matrix, sphereCollision, defaultMaterialID);
NewtonBodySetLinearDamping (body, 0.0f);
collision = NewtonBodyGetCollision(body);
NewtonCollisionSetUserData (collision, *((void**)&restitution));
matrix.m_posit.m_y += 6.0f;
body = CreateSimpleSolid (scene, boxMesh, mass, matrix, boxCollision, defaultMaterialID);
//body = CreateSimpleSolid (scene, sphereMesh, mass, matrix, sphereCollision, defaultMaterialID);
NewtonBodySetLinearDamping (body, 0.0f);
collision = NewtonBodyGetCollision(body);
NewtonCollisionSetUserData (collision, *((void**)&restitution));
}
boxMesh->Release();
sphereMesh->Release();
NewtonDestroyCollision(boxCollision);
NewtonDestroyCollision(sphereCollision);
dMatrix camMatrix (dGetIdentityMatrix());
dQuaternion rot (camMatrix);
origin = dVector (-25.0f, 5.0f, 0.0f, 0.0f);
scene->SetCameraMatrix(rot, origin);
new MovingPlatformEntity(scene, defaultMaterialID);
}
Thanks for the help!
-
Cannos
-
- Posts: 129
- Joined: Thu Mar 04, 2010 5:41 pm
by LordHexahedron » Thu Sep 22, 2016 1:02 am
I would probably make it a static mesh and move it manually per what's described here:
http://newtondynamics.com/wiki/index.ph ... TriMesh%3FSometimes you may wish to move portions of static game world for creating elevators, trains and other special animations.
that sounds a lot like what you want, since it's static other dynamic bodies do not affect it.
That's at least my understanding of the API, I could be entirely wrong but it's worth a shot as it seems relatively trivial to implement.
-
LordHexahedron
-
- Posts: 11
- Joined: Sat Sep 03, 2016 10:05 pm
by JoeJ » Thu Sep 22, 2016 2:31 am
Hehe, fallen into Julios math lib trap
You have:
// Calculate velocity
dVector vel = desiredPos - currentMtx.m_posit;
vel.Scale(1.0f / timestep); // <- does nothing
but you need to assign the value returned fram the scale:
vel = vel.Scale(1.0f / timestep);
... same thing happens to me again and again
"Scale" is indeed misleading, "Scaled" might be better.
-
JoeJ
-
- Posts: 1453
- Joined: Tue Dec 21, 2010 6:18 pm
by Cannos » Thu Sep 22, 2016 12:28 pm
Right you are, fixing the scale assignment looks like it worked. Thanks!
I should have known something strange was happening when I raised the scale arbitrarily and didn't see anything change. Better than when I was using the operator* on the vector to try to scale and instead got a cross product through!
-
Cannos
-
- Posts: 129
- Joined: Thu Mar 04, 2010 5:41 pm
by Julio Jerez » Fri Sep 23, 2016 10:11 am
glad you have going,
Cannos wrote:Better than when I was using the operator* on the vector to try to scale and instead got a cross product through!
btw the operation * and % has been replaced with CrossProduct and DotProduct functions name.
the old function are still there but the engine do no uses then anywhere.
-
Julio Jerez
- Moderator
-
- Posts: 12249
- 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 13 guests