I am making a racing game as part of an assignment using DirectX 11, and I have loaded in a model of a car into a ID3D11Buffer. From this, I was wondering how to rotate the wheels of the car separately to the rest of the model. I have the start and end indices of each part of the car, so I know which part it is to be rotated, just not how to translate it separately. (I'm not sure if me including code would help, but if so, just let me know)
Why not load the model to mess? the wheels is part of the car, and thus a sub-mess of the car.
with sub-mess, you can transform and render it separately without changes the other parts.
If you really want to load it into a ID3DBuffer, I recommend you create two buffers, one hold the static part of the car, another hold the wheels, in this way, you can transform and render the wheels while keep the static part unchanged.
Immediately after asking, I figured it out, and now I have it implemented so that it works fine.
Given that .obj files support groups of vertices, when you load in the file, store the start and end location of each group of vertices, the name of each part that's preceded in the .obj file with a 'g' at the beginning of a line, and calculate the centre point of each group.
Then, make sure that you have a XMFLOAT4X4 for each part that you want to transform separately, as well as one for the whole object. In this case, I have objectMatrix, and wheel1-4Matrix. I apply any transformations I want to the objectMatrix that is general world transformations to do with moving the car. For each wheel, do the following translation
XMMATRIX translate;
translate = XMMatrixTranslation(-centre.x, -centre.y, -centre.z);
translate *= XMMatrixRotationX(angleToBeMoved);
translate *= XMMatrixTranslation(centre.x, centre.y, centre.z);
translate = XMMatrixMultiply(translate, XMLoadFloat4x4(&objectMatrix));
XMStoreFloat4x4(&wheel1, translate);
Apply this to each wheel during the update. During the Draw method, make sure that you're using the DrawIndexed method, pass it both the start and end index for each group, and update your constant buffer's world view matrix with the relevant wheel matrix if it's a wheel, or with the objectMatrix in all other circumstances.
Related
I want to create a vtkGlyph3D from a vtkPolyData containing points, triangles and colors
polydata->SetPoints(points);
polydata->SetPolys(triangles);
polydata->GetPointData()->SetScalars(colors);
Now in all the examples for vtkGlyph3D there is always the call to SetSourceConnection to which a vtkAlgorithmOutput object is passed.
Since i don't use a vtkCubeSource or vtkConeSource or the like, i don't know what i should pass here.
Can i just omit this call and simply do this
vtkNew<vtkGlyph3D> glyph3D;
glyph3D->SetColorModeToColorByScalar();
glyph3D->SetInputData(polydata);
glyph3D->ScalingOff();
glyph3D->Update();
to build my glyph?
Or do i somehow have to create a vtkAlgorithmOutput from my polydata?
From the doc, vtkGlyph3D
copy oriented and scaled glyph geometry to every input point
In other word, this filter copy the Source geometry on every (Nth) points of your Input (and some more option of scale / orientation). So it does not make sense to use it without a SetSourceConnection (with any kind of source/reader/filter providing a polydata)
I'm trying to implement AABBs/OOBBs with MathGeoLib since the ease to operate with BBs (and because I wanted to test some things with that library).
The problem is that the engine's objects transformations are based on glm since we started with glm (and they work properly) but when it comes to transform the OOBBs according to an object, it doesn't work very well.
What I basically do is to pass to a function the game object's translation, orientation and scale (I tried to pass a global matrix but it doesn't work, it seems to 'add' the transformation instead of setting it, and I can't access the oobb's matrix). That function does the next:
glm::vec3 pos = passedPosition - OOBBPreviousPos;
glm::mat4 Transformation = glm::translate(glm::mat4(1.0f), pos) *
glm::mat4_cast(passedRot) * glm::scale(glm::mat4(1.0f), passedScale);
glm::mat4 resMat = glm::transpose(Transformation);
math::float4x4 mat = math::float4x4::identity;
mat.Set(glm::value_ptr(resMat));
Which basically transposes the glm matrix (I have seen that that's they way of 'translating' them), passes it to a float* and then it constructs the MathGeoLib matrix with that. I have debugged it and the values seem to be right according to the object, so the next thing I do is actually transform the OOBB and then, enclose the AABB to have it inside, like this:
m_OBB.Transform(mat);
m_AABB.SetNegativeInfinity(); //Sets AABB to "null"
m_AABB.Enclose(m_OBB);
The final behaviour is pretty strange, believe me if I say that is the most close I've been from having it right, I've been some days testing different things and nothing works better (passing global/local matrices directly, trying different ways of passing/constructing transformation data, checking if the glm-MathGLib is correct...). It rotates but not around its own axis, and the scaling gets him crazy (although translation works). Its current behaviour can be seen here: https://gfycat.com/quarrelsomefineduck (blue cubes are AABBs, green ones are OOBBs).
Am I doing something wrong with the mathematics calculations or data transfer?
I still been looking on that but then some friend made me look into another direction, so I finally solved it (or better said: I "worked-around it") by storing an initial object's AABB and passing to the mentioned function the game object's global matrix. Then, inside the function, I used another MathGeoLib function to transform the OOBB.
That function finally looks like:
glm::mat4 resMat = glm::transpose(GlobalMatrixPassed);
math::float4x4 mat = math::float4x4::identity;
mat.Set(glm::value_ptr(resMat)); //"Translate" glm matrix passed into a MathGeoLib one
m_OOBB.SetFrom(m_InitialAABB); //Set OOBB from the initial aabb
m_OOBB.Transform(mat); //Transform it
m_AABB.SetFrom(m_OOBB); //Set the AABB in function of the transformed OOBB
I'm currently doing real time growing trees, and i'm using an instanced static mesh component for the foliage, since every leaf is unique. When I add an leaf instance to my component, I put a random rotation on it. But for some reason, this rotation is not set, all my leaves have a zerorotator. The scale is set, the transform too, but not the rotation.
Here is the code :
//Instanced static mesh component instanciation, as a component of the tree
foliage = NewObject<UInstancedStaticMeshComponent>(this);
foliage->SetWorldLocation(GetActorLocation());
foliage->RegisterComponent();
foliage->SetStaticMesh(data->leaves[treeType]);
foliage->SetFlags(RF_Transactional);
this->AddInstanceComponent(foliage);
//Adding a instance of foliage
const FTransform leafTrans = FTransform(
FMath::VRandCone(normals[branches[i].segments[j].firstVertice + 2], 2.0f).Rotation(),
vertices[branches[i].segments[j].firstVertice + 2], FVector::ZeroVector);
foliage->AddInstance(leafTrans);
I recently changed the Instanced Static Mesh Component, I beggined to put it on a child actor, and the rotation worked. But I had to remove it for an other issue.
I'm sure it's a small thing I'm missing, but I'm losing too much time searching on the internet, and there is not that much documentation on this subject...
Thanks :)
Ok, the problem was the scale. For some reason, if it is set to zero, it also set the rotation to zero...
To summarize the problem(s):
I have two bodies in my world so far, one being the ground, the other one being a falling box called "fallingStar".
1) I do not understand why my bullet world is not aligned with my drawn world unless I set an offset of btVector3(2,2,2) to the (btDefault)MotionState.
There is no fancy magic going on anywhere in the code that would explain the offset. Or at least I could not find any reason, not in the shaders, not anywhere.
2) I expected to be able to use multiple instances of btDefaultMotionState, to be precise, I wanted to use one instance for the falling entity and place it somewhere above the ground and then create another instance for the ground that should simply be aligned with my graphics-ground, ever unmoving.
What I am experiencing in regards to 2) is that for whatever reason the btDefaultMotionState instance for the falling entity is always also influencing the one for the ground, without any reference.
Now to the code:
Creation of the fallingBox:
btCollisionShape *fallingBoxShape = new btBoxShape(btVector3(1,1,1));
btScalar fallingBoxMass = 1;
btVector3 fallingBoxInertia(0,0,0);
fallingBoxShape->calculateLocalInertia(fallingBoxMass, fallingBoxInertia);
// TODO this state somehow defines where exactly _ALL_ of the physicsWorld is...
btDefaultMotionState *fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(2,2,2)));
//btDefaultMotionState *fallMotionState = new btDefaultMotionState();
btRigidBody::btRigidBodyConstructionInfo fallingBoxBodyCI(fallingBoxMass, fallMotionState, fallingBoxShape, fallingBoxInertia);
/*btTransform initialTransform;
initialTransform.setOrigin(btVector3(0,5,0));*/
this->fallingBoxBody = new btRigidBody(fallingBoxBodyCI);
/*fallMotionState->setWorldTransform(initialTransform);
this->fallingBoxBody->setWorldTransform(initialTransform);*/
this->physicsWorld->addBody(*fallingBoxBody);
Now the interesting parts to me are the necessary offset of btVector3(2,2,2) to align it with my drawn world and this:
btTransform initialTransform;
initialTransform.setOrigin(btVector3(0,5,0));
this->fallingStarBody = new btRigidBody(fallingStarBodyCI);
fallMotionState->setWorldTransform(initialTransform);
If I reenable this part of the code ALL the bodies again show an offset, but NOT just 5 up, which I could somehow comprehend if for whatever reason the worldTransform would effect every entity, but about 2,2,2 off... which I cannot grasp at all.
I guess that this line is useless:
fallMotionState->setWorldTransform(initialTransform); as it does not change anything whether it's there or not.
Now to the code of the ground creation:
btCompoundShape *shape = new btCompoundShape();
... just some logic, nothing to do with bullet
btTransform transform;
transform.setIdentity();
transform.setOrigin(btVector3(x + (this->x * Ground::width),
y + (this->y * Ground::height),
z + (this->z * Ground::depth)));
btBoxShape *boxShape = new btBoxShape(btVector3(1,0,1)); // flat surface, no box
shape->addChildShape(transform, boxShape);
(this portion just creates a compoundshape for each surface tile :)
btRigidBody::btRigidBodyConstructionInfo info(0, nullptr, shape);
return new btRigidBody(info);
Here I purposely set the motionstate to nullptr, but this doesn't change anything.
Now I really am curious... I thought maybe the implementation of btDefaultMotionState is a singleton, but it doesn't look so, so... why the hell is setting the motionState of one body affecting the whole world?
Bullet is a good library but only few dedicate time to write good documentation.
To set position of a btRigidBody, try this :-
btTransform transform = body -> getCenterOfMassTransform();
transform.setOrigin(aNewPosition); //<- set orientation / position that you like
body -> setCenterOfMassTransform(transform);
If your code is wrong only at the set transformation part (that is what I guess from skimming your code), it should be solved.
Note that this snippet works only for dynamic body, not static body.
About CompoundBody:-
If it is a compound body, e.g. shape B contains shape C.
Setting transformation of B would work (set body of B), but not work for C.
(because C is just a shape, transformation support only body.)
If I want to change relative transformation of C to B, I would create a whole new compound shape and a new rigid body. Don't forget to remove old body & shape.
That is a library limitation.
P.S.
I can't answer some of your doubt/questions, these information are what I gathered after stalking in Bullet forum for a while, and tested by myself.
(I am also coding game + game library from scratch, using Bullet and other open sources.)
Edit: (about the new problem)
it just slowly falls down (along with the ground itself, which should
not move as I gave it a mass of 0)
I would try to solve it in this order.
Idea A
Set to the compound mass = 0 instead, because setting a child shape's mass has no meaning.
Idea B
First check -> getCenterOfMassTransform() every time-step , is it really falling?
If it is actually falling, to be sure, try dynamicsWorld->setGravity(btVector3(0,0,0));.
If still not work, try with very simple world (1 simple object, no compound) and see.
Idea C (now I start to be desperate)
Ensure your camera position is constant.
If the problem is still alive, I think you now can create a simple test-case and post it in Bullet forum without too much effort.
Lower amounts of lines of code = better feedback
What you are describing is not normal bullet behavior. Your understanding of the library is correct.
What you are most likely dealing with is either a buffer overrun or a dangling pointer. The code you have posted does not have an obvious one of either, so it would be coming from somewhere else in your codebase. You might be able to track that down using a well-placed memory breakpoint.
You "might" be dealing with a header/binary version inconsistency issue, but that's less likely as you would probably be seeing other major issues.
Just had the exact same type of behavior with the DebugDrawer suspended on top of the world. Solved it by passing to Bullet Physics the projectionview matrix alone, without the model matrix that he has and multiplies with already:
glUseProgram(shaderID);
m_MVP = m_camera->getProjectionViewMatrix();
glUniformMatrix4fv(shaderIDMVP, 1, GL_FALSE, &m_MVP[0][0]);
if (m_dynamicWorld) m_dynamicWorld->debugDrawWorld();
I'm trying to make a system of "chunks" in Box2D - i.e. shapes that are attached together in a big lump, so that you can break chunks off into their own body.
Currently, my system is very basic (just starting really) and modelled after the "Breakable" test in the Box2D testbed. It's a body with quite a few basic box fixtures (which will later become polygons). When you click a body, it deletes the fixture and creates a new body with the same fixture, rotation, etc in the same place as the old "chunk".
However, I can only get it to create the new body at the big body's origin
(->GetWorldCenter). What I want to do is find the global location of the fixture to be deleted and replaced, so I can make the new chunk there.
I've read some stuff about b2PolygonShape having a "centroid", but I'm not sure how to access and use that...
To put it simply, I want to find the global location (as x+y or a b2Vec2) of a FIXTURE, NOT a body (that's easy). The fixture will move with the body it's attached to, but I only currently need the position for one frame (having it update would be useful too though).
For Box2D position of the body not so important. Body position is only shift for fixture coordinates. It do not impact to simulation process. So, I don't understand, why you so care about this.
I made something like this, and can say, that using big body's origin works fine. You can see into Box2D testbed to Breakable test. There also used big body's origin. Only reason to calculate new coordinates that I see is strange behavior of SetAngle method.
If you still want centroid, look at ComputeCentroid, located at b2PolygonShape.cpp. Pay attention, method don't declared at b2PolygonShape.h. You can copy code from cpp and use it like this:
b2Fixture* chunk = ...;
b2Vec2 chunkCentroidLocal = ComputeCentorid(chunk->m_vertices,
chunk->m_vertexCount);
b2Vec2 chunkCentroidWorld = bigBody->GetWorldPoint(chunkCentroidLocal);
p.s. Don't forget to transform polygon points, when you will create new body. Simply find difference between big body and new body, and subtract it from every point of polygon.
b2Vec2 shift = chunkCentroidWorld - bigBody->GetWorldCenter();
b2Vec2 newVertices = new b2Vec2[chunk->m_vertexCount];
for(int i = 0; i< chunk->m_vertexCount; i++)
{
newVertices[i] = chunk->m_vertices[i] - shift;
}