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...
Related
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 have a spatial structure where I keep a few objects. All the positions of the objects are global.
I'm now trying to create a parent/child system but I'm having trouble with the math. What I tried at first was, everytime I move an object, I also move all of its children by the same amount. That works but I also need rotation, so I tried using matrixes. I built a model matrix for the child. It was built using the relative position/rotation/scale to the parent:
glm::mat4 child_model;
//"this" is the parent
child_model = glm::translate(child_model, child_spatial.position - this->m_position);
child_model = child_model * glm::toMat4(glm::inverse(this->m_rotation) * child_spatial.rotation);
child_model = glm::scale(child_model, child_spatial.scale - this->m_scale);
I would then rotate/translate/scale the child matrix by the amount the parent was rotated/moved/scaled and then I would decompose the resulting matrix back to the global child:
child_model = child_model * glm::toMat4(this->m_rotation * rotation);
child_model = glm::translate(child_model, this->m_position + position);
child_model = glm::scale(child_model, this->m_scale * scale);
where position/rotation/scale are defined as:
//How much the parent changed
position = this->position - m_position;
rotation = glm::inverse(m_rotation) * this->rotation;
scale = this->scale - m_scale;
and:
glm::decompose(child_model, d_scale, d_rotation, d_translation, d_skew, d_perspective);
child_spatial.position = d_translation;
child_spatial.rotation = d_rotation;
child_spatial.scale = d_scale;
But it doesn't work and I'm not sure what is wrong. Everything just spins/moves out of control. What am I missing here?
This problem is similar to joint animation used for computer animations. First you have to use or construct transformation matrices for each object. However, the transformation matrix of each child object should be with respect to their parent's coordinate system (i.e., child coordinate should be in parent's coordinate space). We'll call this matrix a ToParentMatrix. In addition, each object needs to have another matrix which transforms it all the way to the root (which is in world space). We'll call this matrix aToRootMatrix. When we multiply these two matrices we get a 'ToWorldMatrix' which contains the position and orientation in world space. So the transformation of each object to world space is as follows in a 2-joint hierarchie (root, child1 (of root) and child2 (of child1)):
RootTransform = ToWorldMatrix; // The root object is allready in world space;
Child1.ToRootMatrix = RootTransform;
Child1.ToWorldMatrix = Child1.ToRootMatrix*Child1.ToParentMatrix;
Child2.ToRootMatrix = Child1.ToWorldMatrix;
Child2.ToWorldMatrix = Child2.ToRootMatrix*Child2.ToParentMatrix;
For more information, search for joint (or skeletal) animation and forward kinematics. Also Frank Luna's book has two nice chapters about skeletal animation.
You are way overthinking things because you are missing some math fundamentals. There are tons of linear algebra for 3d graphics tutorials and courses just a google away!
You need to read through some of them. Your mistake is that you think of a matrix as "how to apply scale/translate/rotate". You need to change that point of view. Matrices describe local spaces. It does not matter how you set them up. So stop thinking about "how things move". Think of every matrix as a space (base). Multiplying a vector by a matrix moves it into that space. And then you move it to the next space. Think of a space as a relative coordinate system.
This is probably not very helpful, but what I am trying to say is: Spend some time to study how linear algebra works! You will need it and it is quite easy in the end. I have a hard time finding a good tutorial but maybe https://www.khanacademy.org/math/linear-algebra looks good.
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.
I looked at a bunch of similar questions, and I cannot seem to find one that particularly answers my question. I am coding a simple 3d game, and I am trying to allow the player to pick up and move entities around my map. I essentially want to get a velocity vector that will "push" the physics object a distance from the player's eyes, wherever they are looking. Here's an example of this being done in another game (the player is holding a chair entity in front of his eyes).
To do this, I find out the player's eye angles, then get the forward vector from the angles, then calculate the velocity of the object. Here is my working code:
void Player::PickupOtherEntity( Entity& HoldingEntity )
{
QAngle eyeAngles = this->GetPlayerEyeAngles();
Vector3 vecPos = this->GetEyePosition();
Vector3 vecDir = eyeAngles.Forward();
Vector3 holdingEntPos = HoldingEntity.GetLocation();
// update object by holding it a distance away
vecPos.x += vecDir.x * DISTANCE_TO_HOLD;
vecPos.y += vecDir.y * DISTANCE_TO_HOLD;
vecPos.z += vecDir.z * DISTANCE_TO_HOLD;
Vector3 vecVel = vecPos - holdingEntPos;
vecVel = vecVel.Scale(OBJECT_SPEED_TO_MOVE);
// set the entity's velocity as to "push" it to be in front of the player's eyes
// at a distance of DISTANCE_TO_HOLD away
HoldingEntity.SetVelocity(vecVel);
}
All that is great, but I want to convert my math so that I can apply an impulse. Instead of setting a completely new velocity to the object, I want to "add" some velocity to its existing velocity. So supposing I have its current velocity, what kind of math do I need to "add" velocity? This is essentially a game physics question. Thank you!
A very simple implementation could be like this:
velocity(t+delta) = velocity(t) + delta * acceleration(t)
acceleration(t) = force(t) / mass of the object
velocity, acceleration and force are vectors. t, delta and mass scalars.
This only works reasonably well for small and equally spaced deltas. What you are essentially trying to achieve with this is a simulation of bodies using classical mechanics.
An Impulse is technically F∆t for a constant F. Here we might want to assume a∆t instead because mass is irrelevant. If you want to animate an impulse you have to decide what the change in velocity should be and how long it needs to take. It gets complicated real fast.
To be honest an impulse isn't the correct thing to do. Instead it would be preferable to set a constant pick_up_velocity (people don't tend to pick things up using an impulse), and refresh the position each time the object rises up velocity.y, until it reaches the correct level:
while(entPos.y < holdingEntPos.y)
{
entPos.y += pickupVel.y;
//some sort of short delay
}
And as for floating in front of the player's eyes, set an EyeMovementEvent of some sort that also sends the correct change in position to any entity the player is holding.
And if I missed something and that's what you are already doing, remember that when humans apply an impulse, it is generally really high acceleration for a really short time, much less than a frame. You wouldn't see it in-game anyways.
basic Newtonian/D'Alembert physics dictate:
derivate(position)=velocity
derivate(velocity)=acceleration
and also backwards:
integrate(acceleration)=velocity
integrate(velocity)=position
so for your engine you can use:
rectangle summation instead of integration (numerical solution of integral). Define time constant dt [seconds] which is the interval between updates (timer or 1/fps). So the update code (must be periodically called every dt:
vx+=ax*dt;
vy+=ay*dt;
vz+=az*dt;
x+=vx*dt;
y+=vy*dt;
z+=vz*dt;
where:
a{x,y,z} [m/s^2] is actual acceleration (in your case direction vector scaled to a=Force/mass)
v{x,y,z} [m/s] is actual velocity
x,y,z [m] is actual position
These values have to be initialized a,v to zero and x,y,z to init position
all objects/players... have their own variables
full stop is done by v=0; a=0;
driving of objects is done only by change of a
in case of collision mirror v vector by collision normal
and maybe multiply by some k<1.0 (0.95 for example) to account energy loss on impact
You can add gravity or any other force field by adding g vector:
vx+=ax*dt+gx*dt;
vy+=ay*dt+gy*dt;
vz+=az*dt+gz*dt;
also You can add friction and anything else you need
PS. the same goes for angles just use angle/omega/epsilon/I instead of x/a/v/m
to be clear by angles I mean rotation (pitch,yaw,roll) around mass center
Consider this: you create a new project on Cocos2D 2.0. You have the traditional Helloworld layer. You add a layer to it with the following structure:
Helloworld (cclayer)
│
┕━ baseLayer (cclayer)
│
┕━ myReducedNode [CCSprite node]
│
┕━ myFullSprite (ccsprite)
│
┕━ smallSprite (ccsprite)
myReducedNode is a node inside baseLayer, created using [CCSprite node] and has a scale applied to it, so, when I apply that scale I reduce myFullSprite and all smallSprites at the same time.
myFullSprite is a 1024x768 points sprite inside myReducedNode.
smallSprites are 230x348 points sprite inside myFullSprite.
Consider this craziness:
first I apply a scale of 1 to myReducedNode. When I drag smallSprite and check its coordinates, everything is fine. If I position smallSprite on the top left corner of myFullSprite, I read the center coordinate of smallSprite as being (115,594) which is the correct value.
I apply a 0.8 scale to myReducedNode. Dragging smallSprite to the same top left corner of myFullSprite, cocos is now reporting the center of smallSprite to be (17,641) ?????????!!!!!!
I am talking about local coordinates, I mean, the position smallSprite is inside myFullSprite.
What is causing this? There's no apparent logic on this number... This number has no relation with the scale applied to the top node.
What am I missing here? I am banging my head on the wall for days, trying to figure this puzzle!!! thanks.
More information. I hope this helps figure out why the coordinates have those values...
baseLayer position is (612, 389) on Helloworld.
myReducedNode position is (0,0) on baseLayer.
myFullSprite position is (0,0) on myReducedNode
I think you should take a look at convertToWorldSpace:, since you are scaling and nesting things, transformations most likely apply to those coordinates.
Here you have a question that might be useful and this post on cocos2d too
Try this:
CGPoint smallSpriteLocalPosition;
smallSpriteLocalPosition =
[smallSprite.parent convertToNodeSpace:smallSprite.position];
Then print out those coordinates and see if they register properly. That should give you the node (local) coordinates of the smallSprite relative to its parent, the fullSprite. You should also be able to convertToWorldSpace for coordinates within the window bounds.
This is what has worked for me in the past when working with child sprites; it can be a bit tricky. Make sure you use the proper variables in the convert call, otherwise you won't get the right data. Let me know if that works as I haven't tried it with layers that are three deep.
after a few changes in code and a several days of research and tries, I conclude this is a bug of Cocos2D or a lack of consistency between how Layers, Sprites and Nodes work (as suggested by LearnCocos2d) , as there's no way to explain the obtained values. I will try to fill a bug report on that.