Am I converting local space to world space coordinates properly? - c++

I'm trying to create a bone and IK system. Below is the method that is recursive and that calculates the absolute positions and absolute angles of each bone. I call it with the root bone and zero'd parameters. It works fine, but when I try to use CCD IK I get discrepancies between the resulting end point and the calculated one. Therefore maybe I'm doing this wrong even though it works.
Thanks
void Skeleton::_updateBones( Bone* root,float realStartX, float realStartY, float realStartAngle )
{
if(!root->isRelative())
{
realStartX = 0.0f;
realStartY = 0.0f;
realStartAngle = 0.0f;
}
realStartX += root->getX();
realStartY += root->getY();
realStartAngle += root->getAngle();
float vecX = sin(realStartAngle);
float vecY = cos(realStartAngle);
realStartX += (vecX * root->getLength());
realStartY += (vecY * root->getLength());
root->setFrame(realStartX,realStartY,realStartAngle);
float angle = fmod(realStartAngle,2.0f * 3.141592f);
if( angle < -3.141592f )
angle += (2.0f * 3.141592);
else if( angle > 3.141592f )
angle -= (2.0f * 3.141592f);
for(std::list<Bone>::iterator it = root->begin(); it != root->end(); ++it)
{
_updateBones(&(*it),realStartX,realStartY,angle);
}
}

This looks wrong.
float vecX = sin(realStartAngle);
float vecY = cos(realStartAngle);
Swap sin() and cos().
float vecX = cos(realStartAngle);
float vecY = sin(realStartAngle);

Related

How to linearly interpolate to destination that is not constant

If I want to linearly interpolate from point A (source) to point B (destination) on a 2d plane I could do it like this. Vector2 here is a struct consisting of x and y floats.
Vector2 Interpolate(Vector2 source, Vector2 destination, float delta) {
return source+(destination-source)*delta;
}
void OnEachUpdate() {
delta += 0.05f;
delta = max(delta, 1.0f);
currentVector = Interpolate(source, destination, delta);
}
This way I can interpolate from source to destination with a given delta. However what if I have destination vector that is not constant? Say the user can change the destination by pointing a mouse cursor on a 2d plane. An object should linearly interpolate to the destination vector.
I could do something like this but it's not a linear interpolation, but more like sigmoidal, which is not what I want.
delta = 0.05f;
currentVector += Interpolate(currentVector, destination, delta);
Since you said you want to keep the speed constant, I assume you want this:
float speed = whatever;
float delta_x = target_x - current_x;
float delta_y = target_y - current_y;
float dist_sqr = delta_x*delta_x + delta_y*delta_y;
if (dist_sqr <= speed*speed)
{
// The destination is reached.
current_x = target_x;
current_y = target_y;
}
else
{
float dist = std::sqrt(dist_sqr);
current_x += delta_x / dist * speed;
current_y += delta_y / dist * speed;
}

How to scale the rotation of a quaternion

I am trying to do the equivalent of multiplying the velocity by the time between frames. I would imagine that doing this for quaternions would be done by raising them to a power. I have code to rotate an object based on my mouse movements. It has a main loop running at one frame rate and a physics loop running at a fixed frame rate. Here is the relevant part of the main loop:
glfwPollEvents();
Input::update();
window.clear(0,0,0,1);
rigidBody.angularVelocity *= glm::angleAxis(0.001f * Input::deltaMouse().x, glm::vec3(0,1,0));
rigidBody.angularVelocity *= glm::angleAxis(0.001f * Input::deltaMouse().y, glm::vec3(1,0,0));
if(Input::getKey(Input::KEY_A))
{
rigidBody.velocity -= float(Time::getDelta()) * glm::vec3(1,0,0);
}
if(Input::getKey(Input::KEY_D))
{
rigidBody.velocity += float(Time::getDelta()) * glm::vec3(1,0,0);
}
if(Input::getKey(Input::KEY_W))
{
rigidBody.velocity -= float(Time::getDelta()) * glm::vec3(0,0,1);
}
if(Input::getKey(Input::KEY_S))
{
rigidBody.velocity += float(Time::getDelta()) * glm::vec3(0,0,1);
}
if(Input::getKey(Input::KEY_LCONTROL))
{
rigidBody.velocity -= float(Time::getDelta()) * glm::vec3(0,1,0);
}
if(Input::getKey(Input::KEY_LSHIFT))
{
rigidBody.velocity += float(Time::getDelta()) * glm::vec3(0,1,0);
}
Here is the relevant part of the physics loop:
for(int i = 0; i < *numRigidBodies; i++)
{
rigidBodies[i].transform->getPos() += rigidBodies[i].velocity;
rigidBodies[i].transform->getRot() *= rigidBodies[i].angularVelocity;
}
rigidBodies[0].angularVelocity = glm::quat();
rigidBodies[0].velocity = glm::vec3();
This works fine, but when I try raising angular velocity to a power with glm::pow, the object rotates randomly and does not follow my mouse. I realize I could do this with a line of code like
rigidBodies[i].transform->getRot() *= glm::angleAxis((float)Time::getFixedDelta() * glm::angle(rigidBodies[i].angularVelocity), glm::axis(rigidBodies[i].angularVelocity));
but this seems needlessly complicated for the task. What is causing this issue, and how can I fix it?
Not sure exactly how to do it with the API you're using, but basically, you would use Quaternion::Slerp(). Slerp means "spherical linear interpolation".
Something like this(pseudocode) should work:
auto& rot = rigidBodies[i].transform->getRot();
auto goal = rigidBodies[i].angularVelocity * rot;
rot = rot.slerp(rot, goal, Time::deltaTime);
Edit:
I should note that this is not how I would approach this problem. I would just store the rotation around the X and Y axis as scalars and construct a new quaternion from them each frame.
Please excuse the sloppy pseudo code:
// previous x and y positions, could probably be set in MouseDown event
float lastX = ...;
float lastY = ...;
float xRotation = 0;
float yRotation = 0;
float rotationSpeed = 1.0;
void OnMouseMove(float x, float y) {
float dx = x - lastX;
float dy = y - lastY;
lastX = x;
lastY = y;
xRotation += dy * rotationSpeed * Time::deltaTime;
yRotation += dx * rotationSpeed * Time::deltaTime;
rigidBodies[i].transform->getRot() = eulerQuat(xRotation, yRotation, 0);
}
Turns out angular velocity is usually represented as a 3d vector where the direction is the axis and the magnitude is the angular speed. Replace this line of code:
rigidBodies[i].transform->getRot() *= rigidBodies[i].angularVelocity;
with this:
if(rigidBodies[i].angularVelocity != glm::vec3())
rigidBodies[i].transform->getRot() *= glm::quat(rigidBodies[i].angularVelocity * float(Time::getFixedDelta()));
and the physics system works as expected. The if check makes sure that angular speed is not 0.

Solar System Simulator Physics Integration Issues (Unreal Engine 4, C++)

So I'm making this solar system simulator in Unreal Engine 4 using C++ for a College project, however, I'm new to C++ and UE4 AND I suck at maths so I was in need of a bit of assistance, I wanted to use the Euler integrator for now just to get some basic physics in and have the Moon orbit around the Earth and then move on to probably use the Velocity Verlet method and build the whole Solar System that way. However, as of right now, even the Euler integration doesn't work. Here's the code in Moon.cpp
//Declare the masses
float MMass = 109.456;
float EMass = 1845.833;
//New velocities
float NewMVelX = 0.0;
float NewMVelY = 0.0;
float NewMVelZ = 0.0;
//Distance
float DistanceX = 0.0;
float DistanceY = 0.0;
float DistanceZ = 0.0;
//Earth's velocity
float EVelocityX = 0.0;
float EVelocityY = 0.0;
float EVelocityZ = 0.0;
//Moon's base velocity
float MVelocityX = 0.1;
float MVelocityY = 0.0;
float MVelocityZ = 0.0;
//Moon's acceleration
float MForceX = 0.0;
float MForceY = 0.0;
float MForceZ = 0.0;
//New position
float MPositionX = 0.0;
float MPositionY = 0.0;
float MPositionZ = 0.0;
// Called every frame
void AMoon::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//Get Earth Location
FVector EPosition = FVector(0.0, 0.0, 0.0);
//Get Moon Location
FVector MPosition = GetActorLocation();
//Get the distance between the 2 bodies
DistanceX = (MPosition.X - EPosition.X) / 100;
DistanceY = (MPosition.Y - EPosition.Y) / 100;
//DistanceZ = MPosition.Z - EPosition.Z / 100;
//Get the acceleration/force for every axis
MForceX = G * MMass * EMass / (DistanceX * DistanceX);
MForceY = G * MMass * EMass / (DistanceY * DistanceY);
//MForceZ = G * MMass * EMass / (DistanceZ * DistanceZ);
//Get the new velocity
NewMVelX = MVelocityX + MForceX;
NewMVelY = MVelocityY + MForceY;
//NewMVelZ = MVelocityZ + MForceZ * DeltaTime;
//Get the new location
MPositionX = (MPosition.X) + NewMVelX;
MPositionY = (MPosition.Y) + NewMVelY;
//MPositionZ = MPosition.Z * (MVelocityZ + NewMVelZ) * 0.5 * DeltaTime;
//Set the new velocity on the old one
MVelocityX = NewMVelX;
MVelocityY = NewMVelY;
//MVelocityZ = NewMVelZ;
//Assign the new location
FVector NewMPosition = FVector(MPositionX, MPositionY, MPositionZ);
//Set the new location
SetActorLocation(NewMPosition);
}
The values might not be right, I was just making tests at this point. I based this code on the different pieces of information I got on Google and multiple websites but at this point I'm quite confused. What is happening is that the Moon just starts going in 1 direction and never stops. I know my issue is with the force/acceleration/actual gravity of the Earth, it should pull the Moon not push it away. But anyway, if anyone has an idea what I'm doing wrong, I'd be very grateful to hear what you have to say! Thanks
The force depends on the euclidean, rotation-invariant distance. Thus use
distance = sqrt(distanceX²+distanceY²+distanceZ²)
force = - G*Emass*Mmass/distance²
forceX = force * X/distance
forceY = force * Y/distance
forceZ = force * Z/distance
The time stepping of the velocity is also wrong, it should be
velocityX += forceX/Mmass * deltaTime
velocityY += forceY/Mmass * deltaTime
velocityZ += forceZ/Mmass * deltaTime
and of course also the position update contains the time step
positionX += velocityX * deltaTime
....

Camera matrix invalid when aligned with up vector

I'm currently implementing cameras on my engine and I'm having an issue when the camera is looking from top to the floor (example, eye position 0.,0.,50. and target is 0.,0.,0.) my up vector is 0.,0.,1..
Then when I do the maths, the crossproduct of position and up gives 0.,0.,0. and then the view is screwed and nothing is rendered. If I move the camera, everything works as expected.
How can I solve this?
if (node==NULL || target==NULL) return;
node->Update();
eye=node->GetWorldMatrix()*GRPVECTOR(0.0,0.0,0.0); //converts from matrix to vector my vector transformation
target->Update();
obj=target->GetWorldMatrix()*GRPVECTOR(0.0,0.0,0.0);
GRPVECTOR ev;
GRPVECTOR z;
GRPVECTOR x_tmp;
GRPVECTOR x;
GRPVECTOR y;
ev = eye - obj;
ev.Normalize();
z=ev;
x_tmp.CrossProduct(&up,&z);
if (x_tmp.GetLengthf()==0.0f)
return; //my view is screwed, I return
x_tmp.Normalize();
x=x_tmp;
y.CrossProduct(&z,&x);
this->viewmatrix.matrix[0][0] = x.vector[0];
this->viewmatrix.matrix[0][1] = y.vector[0];
this->viewmatrix.matrix[0][2] = z.vector[0];
this->viewmatrix.matrix[0][3] = 0.0f;
this->viewmatrix.matrix[1][0] = x.vector[1];
this->viewmatrix.matrix[1][1] = y.vector[1];
this->viewmatrix.matrix[1][2] = z.vector[1];
this->viewmatrix.matrix[1][3] = 0.0f;
this->viewmatrix.matrix[2][0] = x.vector[2];
this->viewmatrix.matrix[2][1] = y.vector[2];
this->viewmatrix.matrix[2][2] = z.vector[2];
this->viewmatrix.matrix[2][3] = 0.0f;
this->viewmatrix.matrix[3][0] = -x.vector[0] * eye.vector[0] + -x.vector[1] * eye.vector[1] + -x.vector[2] * eye.vector[2];
this->viewmatrix.matrix[3][1] = -y.vector[0] * eye.vector[0] + -y.vector[1] * eye.vector[1] + -y.vector[2] * eye.vector[2];
this->viewmatrix.matrix[3][2] = -z.vector[0] * eye.vector[0] + -z.vector[1] * eye.vector[1] + -z.vector[2] * eye.vector[2];
this->viewmatrix.matrix[3][3] = 1.0f;
GRPMATRIX Translate;
Translate.BuildTranslationMatrix(-obj.vector[0],-obj.vector[1],-obj.vector[2]);
this->viewmatrix.GetMulplicationMatrix(&this->viewmatrix,&Translate);

Second iteration crash - order irrelevant

To save on global memory transfers, and because all of the steps of the code work individually, I have tried to combine all of the kernals into a single kernal, with the first 2 (of 3) steps being done as device calls rather than global calls.
This is failing in the second half of the first step.
There is a function that I need to call twice, to calculate the 2 halves of an image. Regardless of the order the image is calculated in, it crashes on the second iteration.
After examining the code as well as I could, and running it multiple times with different return points, I have found what makes it crash.
__device__
void IntersectCone( float* ModDistance,
float* ModIntensity,
float3 ray,
int threadID,
modParam param )
{
bool ignore = false;
float3 normal = make_float3(0.0f,0.0f,0.0f);
float3 result = make_float3(0.0f,0.0f,0.0f);
float normDist = 0.0f;
float intensity = 0.0f;
float check = abs( Dot(param.position, Cross(param.direction,ray) ) );
if(check > param.r1 && check > param.r2)
ignore = true;
float tran = param.length / (param.r2/param.r1 - 1);
float length = tran + param.length;
float Lsq = length * length;
float cosSqr = Lsq / (Lsq + param.r2 * param.r2);
//Changes the centre position?
float3 position = param.position - tran * param.direction;
float aDd = Dot(param.direction, ray);
float3 e = position * -1.0f;
float aDe = Dot(param.direction, e);
float dDe = Dot(ray, e);
float eDe = Dot(e, e);
float c2 = aDd * aDd - cosSqr;
float c1 = aDd * aDe - cosSqr * dDe;
float c0 = aDe * aDe - cosSqr * eDe;
float discr = c1 * c1 - c0 * c2;
if(discr <= 0.0f)
ignore = true;
if(!ignore)
{
float root = sqrt(discr);
float sign;
if(c1 > 0.0f)
sign = 1.0f;
else
sign = -1.0f;
//Try opposite sign....?
float3 result = (-c1 + sign * root) * ray / c2;
e = result - position;
float dot = Dot(e, param.direction);
float3 s1 = Cross(e, param.direction);
float3 normal = Cross(e, s1);
if( (dot > tran) || (dot < length) )
{
if(Dot(normal,ray) <= 0)
{
normal = Norm(normal); //This stuff (1)
normDist = Magnitude(result);
intensity = -IntensAt1m * Dot(ray, normal) / (normDist * normDist);
}
}
}
ModDistance[threadID] = normDist; and this stuff (2)
ModIntensity[threadID] = intensity;
}
There are two things I can do to to make this not crash, both off which negate the point of the function: If I do not try to write to ModDistance[] and ModIntensity[], or if I do not write to normDist and intensity.
First chance exceptions are thrown by the code above, but not if either of the blocks commented out.
Also, The program only crashes the second time this routine is called.
Have been trying to figure this out all day, any help would be fantastic.
The code that calls it is:
int subrow = threadIdx.y + Mod_Height/2;
int threadID = subrow * (Mod_Width+1) + threadIdx.x;
int obsY = windowY + subrow;
float3 ray = CalculateRay(obsX,obsY);
if( !IntersectSphere(ModDistance, ModIntensity, ray, threadID, param) )
{
IntersectCone(ModDistance, ModIntensity, ray, threadID, param);
}
subrow = threadIdx.y;
threadID = subrow * (Mod_Width+1) + threadIdx.x;
obsY = windowY + subrow;
ray = CalculateRay(obsX,obsY);
if( !IntersectSphere(ModDistance, ModIntensity, ray, threadID, param) )
{
IntersectCone(ModDistance, ModIntensity, ray, threadID, param);
}
The kernel is running out of resources. As posted in the comments, it was giving the error CudaErrorLaunchOutOfResources.
To avoid this, you should use a __launch_bounds__ specifier to specify the block dimensions you want for your kernel. This will force the compiler to ensure there are enough resources. See the CUDA programming guide for details on __launch_bounds__.