DirectX Camera Jitter - matrix

Source Code.
I'm making a small DirectX Demo Scene but my camera seems to "snap" to odd positions when I attempt to rotate it. It only happens when rotating and I can't seem to find out what is causing it.
// Get the cursor pos and calculate change in movement
POINT cursorPos;
GetCursorPos(&cursorPos);
LONG deltaX = oldCursorPos.x - cursorPos.x;
LONG deltaY = oldCursorPos.y - cursorPos.y;
// Hold right click to rotate
if (GetAsyncKeyState(VK_RBUTTON))
{
XMMATRIX xRotation = XMMatrixRotationY(((float)-deltaX * (float)timer.Delta()));
XMMATRIX yRotation = XMMatrixRotationX(((float)-deltaY * (float)timer.Delta()));
XMMATRIX view = XMLoadFloat4x4(&cameraMatrix);
XMFLOAT4 viewVector = XMFLOAT4(cameraMatrix.m[3][0], cameraMatrix.m[3][1], cameraMatrix.m[3][2], 1.0f);
for (size_t i = 0; i < 3; i++) { cameraMatrix.m[3][i] = 0.0f; }
view = view * xRotation;
view = yRotation * view;
XMStoreFloat4x4(&cameraMatrix, view);
cameraMatrix.m[3][0] = viewVector.x;
cameraMatrix.m[3][1] = viewVector.y;
cameraMatrix.m[3][2] = viewVector.z;
}
oldCursorPos = cursorPos;
Above is the code that performs the rotations to the camera matrix, below is the code I use to set the view matrix equal to the inverse of the camera matrix. Both of these operations are done every frame.
XMMATRIX camera = XMLoadFloat4x4(&cameraMatrix);
XMMATRIX view = XMMatrixInverse(NULL, camera);
XMStoreFloat4x4(&sceneMatrix.viewMatrix, view);
Both of these snippets don't seem to be the problem though, as I have triple checked my notes and this is exactly how my instructor expects it to be done. This bug happens in debug and release mode.
I put the source code in the link above if an attractive person such as yourself dare look at the rest of the code. Beware: It is a small demo application so try not to cringe at the hard-coded objects and such.

I'm not certain it's causing your problem, as a simple demo might have a consistent frame-rate, but you shouldn't be scaling mouse movement by a time delta.
These lines:
XMMATRIX xRotation = XMMatrixRotationY(((float)-deltaX * (float)timer.Delta()));
XMMATRIX yRotation = XMMatrixRotationX(((float)-deltaY * (float)timer.Delta()));
Should be
float fRotationSpeed = 0.01f; // Tweak this.
XMMATRIX xRotation = XMMatrixRotationY(((float)-deltaX * fRotationSpeed));
XMMATRIX yRotation = XMMatrixRotationX(((float)-deltaY * fRotationSpeed));

Related

Standalone Player Looks Different than Game View

Okay so I've built this little dodger game and everything is perfect except the standalone player doesn't match the game view visually. Pics for reference. Please let me know anything to stop this issue.
I want the standalone player to be the same as the game view.
Changing the resolution in the player settings doesn't work so far.
Unity GameView
Standalone Player
Looks to me like its your scale settings in the Game window. It's set at 0.33 in the picture you've posted.
Try changing your view to Free Aspect, then adjust your camera GameObject to tighten in on your gameplay area. Or just refresh your layout, sometimes changing the aspect ratio while the Game view is smaller makes it difficult to restore the aspect you are looking for.
Reset your layout here:
Window\Layouts\Default (or whatever you prefer)
I used this code, with two different cameras rendering.
void Update ()
{
float targetaspect = 4f / 3f; // set the desired aspect ratio
float windowaspect = (float)Screen.width / (float)Screen.height; // determine the current aspect ratio
float scaleheight = windowaspect / targetaspect; // current viewport height should be scaled by this amount
// obtain camera component so we can modify its viewport
Camera camera = GetComponent<Camera>();
// if scaled height is less than current height, add letterbox
if (scaleheight < 1.0f)
{
Rect rect = camera.rect;
rect.width = 1.0f;
rect.height = scaleheight;
rect.x = 0;
rect.y = (1.0f - scaleheight) / 2.0f;
camera.rect = rect;
}
else // add pillarbox
{
float scalewidth = 1.0f / scaleheight;
Rect rect = camera.rect;
rect.width = scalewidth;
rect.height = 1.0f;
rect.x = (1.0f - scalewidth) / 2.0f;
rect.y = 0;
camera.rect = rect;
}
}

Why is this basic "rotate around the origin" failing to work?

I've done this a hundred times, but this is my first time with a manually constructed cube made of "sticks", which are 3D lines. It's constructed around the origin, out 5 from the origin in each of the X, Y, and Z directions.
When I rotate it, I'm still "inside it" and it rotates around me (the camera). I'm applying a translation and rotation, so I'm stymied as to what I'm doing wrong.
Here's the basic code to rotate the box, by which I mean generate it's world matrix:
float rotateX = 0.0f, rotateY = 0.0f, rotateZ = 0.0f;
XMFLOAT4 positionBox = XMFLOAT4(0, 0, -50, 1); // Camera at origin looking at this
XMMATRIX matrixCubeWorld;
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
auto pCamera = g_GameServices.GetService<CWorldCamera>();
XMMATRIX translation = XMMatrixTranslationFromVector(XMLoadFloat4(&positionBox));
XMMATRIX rotation = XMMatrixRotationRollPitchYaw(rotateX, rotateY, rotateZ);
matrixCubeWorld = rotation * translation;
if (GetKeyState('X') < 0)
rotateX = RotateAround(rotateX, fElapsedTime);
if (GetKeyState('Y') < 0)
rotateY = RotateAround(rotateY, fElapsedTime);
}
And when I set up to draw, I use that matrix:
D3D11_MAPPED_SUBRESOURCE MappedResource;
V(pd3dImmediateContext->Map(_pVertexShaderVariables, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource));
auto pCB = reinterpret_cast<VSCB3DLineChangesEveryFrame *>(MappedResource.pData);
pCB->_gWorldViewProj = matrixCubeWorld * pCamera->GetViewMatrix() * pCamera->GetProjMatrix();
pd3dImmediateContext->Unmap(_pVertexShaderVariables, 0);
return hr;
...and the shader is as simple as can be:
VertexShaderOutput Line3DVertexShaderFunction(float3 position : POSITION, float4 color : COLOR, float2 tex : TEXCOORD0)
{
VertexShaderOutput output;
output.position = mul(float4(position, 1), _gWorldViewProj);
output.color = color;
output.tex = tex;
return output;
}
So do I have a bug or a misunderstanding? I've tried with the inverse of the translation, thinking that would 'bring it back to the origin before rotating' but didn't improve it.
Transformations look good imho.
Maybe it's due to the fact that 'XMMatrixTranslationFromVector'
takes only 3d-vector as the documentation (msdn) says.
Also make sure that RotateAround function and camera view/proj matrices give correct results.
Best regards.

Rotate a Sprite around another Sprite -libGDX-

video game link
I'm trying to make a game (see link above) , and I need to have the stick rotate around himself to maintain the orientation face to center of the circle.
this is how I declare the Sprite, and how I move it around the circle:
declaration:
line = new Sprite(new Texture(Gdx.files.internal("drawable/blockLine.png")));
line.setSize(140, 20);
lineX = Gdx.graphics.getWidth()/2 - line.getWidth()/2;
lineY = (Gdx.graphics.getHeight()/2 - line.getHeight()/2) + circle.getHeight()/2;
movement:
Point point = rotatePoint(new Point(lineX, lineY), new Point(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2), angle+= Gdx.graphics.getDeltaTime() * lineSpeed);
line.setPosition(point.x, point.y);
rotatePoint function:
Point rotatePoint(Point point, Point center, double angle){
angle = (angle ) * (Math.PI/180); // Convert to radians
float rotatedX = (int) (Math.cos(angle) * (point.x - center.x) - Math.sin(angle) * (point.y-center.y) + center.x);
float rotatedY = (int) (Math.sin(angle) * (point.x - center.x) + Math.cos(angle) * (point.y - center.y) + center.y);
return new Point(rotatedX,rotatedY);
}
Any sugestions ?
I can't test right now but I think the rotation of the line should simply be:
Math.atan2(rotatedPoint.getOriginX() - middlePoint.getOriginX(), rotatedPoint.getOriginY() - middlePoint.getOriginY()));
Then you'll have to adjust rad to degrees or whatever you'll use. Tell me if it doesn't work!
I would take a different approach, I just created a method that places n Buttons around a click on the screen. I am using something that looks like this:
float rotation; // in degree's
float distance; //Distance from origin (radius of circle).
vector2 originOfRotation; //Center of circle
vector2 originOfSprite; //Origin of rotation sprite we are calculating
Vector2 direction = new vector2(0, 1); //pointing up
//rotate the direction
direction.rotate(rotation);
// add distance based of the direction. Warning: originOfRotation will change because of chaining method.
// use originOfRotation.cpy() if you do not want to init each frame
originOfSprite = originOfRotation.add(direction.scl(distance));
Now you have the position of your sprite. You need to increment rotation by x each frame to have it rotate. If you want the orientation of the sprite to change you can use the direction vector, probably rotated by 180 again. Efficiency wise I'm not sure what the difference would be.

Processing, Rotate rectangle using matrix?

I am trying to rotate a rectangle without using the rotate function, but instead using a matrix..I know how to rotate a line using a matrix but all my attempts to rotate a rectangle have failed.
I dont think this is use full but heres is my code that rotates the line.
float[][] rotation;
float[] position;
float theta = 180;
float pointX;
float pointY;
void setup() {
frameRate(60);
size(600, 600);
pointX = 0;
pointY = 0;
rotation = new float[2][2];
position = new float[8];
}
void draw() {
background(200);
theta = mouseX;
position[0] = mouseY;
position[1] = mouseY;
position[2] = -mouseY;
position[3] = mouseY;
rotation[0][0] = cos(radians(theta));
rotation[0][1] = -sin(radians(theta));
rotation[1][0] = sin(radians(theta));
rotation[1][1] = cos(radians(theta));
float newpos[] = new float[8];
newpos[0] += position[0] * rotation[0][0];
newpos[1] += position[1] * rotation[0][1];
translate(width/2, height/2);
line(0, 0, pointX+newpos[0], pointY+newpos[1]);
line(0, 0, pointX+newpos[0] * -1, pointY+newpos[1] * -1);
}
Although the lines behaves properly it is by chance... You have a crucial part of the calculation of the new x and y of the point not as it should have been. As you can find in wikipedia, you need to calculate the sin and cos in the matrix as you properly did, but when creating the new point you don't exactly do this:
Start by having a look at pushMatrix()/popMatrix() and coordinate spaces.
Have a look at Daniel Shiffman's tutorial as well, it's pretty well explained.
If you need to get lower level than this, have a look at the PMatrix2D class.
Notice there is a rotate() function. After you rotate, you can either simply apply
the matrix(using applyMatrix()) but you might as well be using push/pop matrix calls.
Another option is multiply vectors(rectangle corners) to the rotation matrix and draw the result/transformed points.

Transform mouse coordinates to 3d coordinates

I have the following problem:
I have my mouse coordinates and I have a Model (Data Points) and I want the 3d Coordinates of my mouse coordinates and my lookAt Vector of this coordinates, so that I can make a raycast with the object, so that I can see the 3d values of the data points. So I want to click with the mouse and then I want to see the coordinates of the datapoint I clicked at.
I have the following from a tutorial, but it doesn't work. The ray origin and ray direction are not correct (I draw I line from ray origin in the ray direction and the ray origin isn't right:
Can anyone help me? Here is the code:
// Move the mouse cursor coordinates into the -1 to +1 range.
pointX = ((2.0f * (float)mouseX) / (float) screen_width) - 1.0f;
pointY = (((2.0f * (float)mouseY) / (float) screen_height) - 1.0f) * -1.0f;
m_D3D->GetProjectionMatrix(projectionMatrix);
pointX = pointX / projectionMatrix._11;
pointY = pointY / projectionMatrix._22;
// Get the inverse of the view matrix.
m_Camera->GetViewMatrix(viewMatrix);
D3DXMatrixInverse(&inverseViewMatrix, NULL, &viewMatrix);
// Calculate the direction of the picking ray in view space.
direction.x = (pointX * inverseViewMatrix._11) + (pointY * inverseViewMatrix._21)+
inverseViewMatrix._31;
direction.y = (pointX * inverseViewMatrix._12) + (pointY * inverseViewMatrix._22)
+ inverseViewMatrix._32;
direction.z = (pointX * inverseViewMatrix._13) + (pointY * inverseViewMatrix._23)
+ inverseViewMatrix._33;
// Get the origin of the picking ray which is the position of the camera.
origin = m_Camera->GetPosition();
// Get the world matrix and translate to the location of the sphere.
m_Impact->GetWorldMatrix(worldMatrix);
//D3DXMatrixTranslation(&translateMatrix, -5.0f, 1.0f, 5.0f);
//D3DXMatrixMultiply(&worldMatrix, &worldMatrix, &translateMatrix);
// Now get the inverse of the translated world matrix.
D3DXMatrixInverse(&inverseWorldMatrix, NULL, &worldMatrix);
D3DXVec3TransformCoord(&rayOrigin, &origin, &inverseWorldMatrix);
D3DXVec3TransformNormal(&rayDirection, &direction, &inverseWorldMatrix);
// Normalize the ray direction.
D3DXVec3Normalize(&rayDirection, &rayDirection);
//collision_object->setTransform(col_matrix);
collision_model->setTransform(col_matrix);
float collision_point[3];
//bool collision_result = collision_object ->rayCollision(rayOrigin,
rayDirection, true);
bool collision_result = collision_model ->rayCollision(rayOrigin,
rayDirection, true);
if(collision_result == true)
{
intersect = true;
//collision_object->getCollisionPoint(collision_point, true);
collision_model->getCollisionPoint(collision_point, false);
*coordX = collision_point[0];
*coordY = collision_point[1];
*coordZ = collision_point[2];
}
One simple way to build a ray from mouse is as follow (pseudo code)
Get mouse coords to -1 -> 1 range (as you already do)
Create view projection matrix (view*projection)
Invert it.
Create 2 mouse vectors:
near = Vector3(mousex,mousey,0);
far = Vector3(mousex,mousey,1);
rayorigin = transformcoord(near, inverseviewprojection);
rayend = transformcoord(far, inverseviewprojection);
raydir = normalize(rayend-rayorigin);

Resources