Jump to content
  • Advertisement
lucky6969b

How to avoid the object floating around with the camera?

Recommended Posts

I want it to stay at one place, say where the position with transformations by the world matrix only. But I don't think if I drop the view and projection matrices, it will work anyway.
But now the thing is moving with the camera.

outVS.position = mul(mul(float4(position.xyz, 1.0), modelViewMatrix), projectionMatrix);



Thanks
Jack

Share this post


Link to post
Share on other sites
Advertisement

Try this to get an understanding of the view matrix.

The link above is openGL based but the information is adaptable to what I assume from your shader snippet is hlsl. Below is a code dump of a camera from one of my directX projects for reference.

//
// file : transform.h
//

#ifndef _nub_device_transform_h_
#define _nub_device_transform_h_

#include <DirectXMath.h>

typedef DirectX::XMFLOAT3 vec3;
typedef DirectX::XMVECTOR vec;
typedef DirectX::XMFLOAT4X4 mat4;

namespace Component
{
	class cTransform
	{
	public:
		cTransform()
		{
			_position  = vec3(0.0f, 0.0f, 0.0f);
			_rotations = vec3(0.0f, 0.0f, 0.0f);
			_scale     = vec3(1.0f, 1.0f, 1.0f);

			_forward   = vec3(0.0f, 0.0f, 1.0f);
			_right     = vec3(1.0f, 0.0f, 0.0f);
			_up        = vec3(0.0f, 1.0f, 0.0f);

			DirectX::XMStoreFloat4x4(&_matrix, DirectX::XMMatrixIdentity());
			_isDirty   = false;
		}

		vec3 getPosition()      { return _position;  }
		vec3 getAxisRotations() { return _rotations; }
		vec3 getForward()       { return _forward;   } //
		vec3 getRight()         { return _right;     } // if these are dirty they won't be current this frame
		vec3 getUp()            { return _up;        } // todo: add assertions 
		mat4 getMatrix()        { return _matrix;    } //

		void setPosition(vec3 p)      { _position = p;                      }
		void setScale   (vec3 s)      { _scale = s;        _isDirty = true; }
		void setRotation(vec3 r)      { _rotations = r;    _isDirty = true; }

		void move(vec3 v)             { _position.x += v.x;            _position.y += v.y;            _position.z += v.z;            }
		void moveForward(float t)     { _position.x += t * _forward.x; _position.y += t * _forward.y; _position.z += t * _forward.z; }
		void moveRight(float t)       { _position.x += t * _right.x;   _position.y += t * _right.y;   _position.z += t * _right.z;   }
		void moveUp(float t)          { _position.x += t * _up.x;      _position.y += t * _up.y;      _position.z += t * _up.z;      }

		void addDeltaPosition(vec3 p) { _position.x += p.x; _position.y += p.y; _position.z += p.z; }
		void addDeltaYaw(float t)     { _rotations.y += t; _isDirty = true; }
		void addDeltaPitch(float t)   { _rotations.x += t; _isDirty = true; }
		void addDeltaRoll (float t)   { _rotations.z += t; _isDirty = true; }

		void update()
		{
			if (_isDirty)
			{
				// if all rotations being tracked are zero, forward points 'into' the screen
				//
				// Notes:
				// cos(0) = 1    cos(pi/2) = 0    cos(pi) = -1    cos(pi+pi/2) =  0    cos(2pi) = 1
				// sin(0) = 0    sin(pi/2) = 1    sin(pi) =  0    sin(pi+pi/2) = -1    sin(2pi) = 0
				//
				//

				_forward = vec3(cosf(_rotations.x) * sinf(_rotations.y),
					            sinf(_rotations.x),
					            cosf(_rotations.x) * cosf(_rotations.y));
						
				_right = vec3(cosf(_rotations.z) * sinf(_rotations.y + DirectX::XM_PIDIV2),
					          sinf(_rotations.z),
					          cosf(_rotations.z) * cosf(_rotations.y + DirectX::XM_PIDIV2));
				DirectX::XMStoreFloat3(&_right, DirectX::XMVector3Normalize(DirectX::XMLoadFloat3(&_right)));
				
				vec vecForward = DirectX::XMLoadFloat3(&_forward);
				vec vecRight   = DirectX::XMLoadFloat3(&_right);
				vec vecUp      = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(vecForward, vecRight));
				
				//DirectX::XMStoreFloat3(&_right, DirectX::XMVector3Normalize(DirectX::XMVector3Cross(vecUp, vecForward)));
				DirectX::XMStoreFloat3(&_up, vecUp);
				

				_matrix.m[0][0] = _right.x * _scale.x;
				_matrix.m[0][1] = _right.y;
				_matrix.m[0][2] = _right.z;
				_matrix.m[0][3] = 0.0f;

				_matrix.m[1][0] = _up.x;
				_matrix.m[1][1] = _up.y * _scale.y;
				_matrix.m[1][2] = _up.z;
				_matrix.m[1][3] = 0.0f;

				_matrix.m[2][0] = _forward.x;
				_matrix.m[2][1] = _forward.y;
				_matrix.m[2][2] = _forward.z * _scale.z;
				_matrix.m[2][3] = 0.0f;
				_isDirty = false;
			}
			_matrix.m[3][0] = _position.x;
			_matrix.m[3][1] = _position.y;
			_matrix.m[3][2] = _position.z;
			_matrix.m[3][3] = 1.0f;
		}

	private:
		vec3 _position;
		vec3 _rotations; // per axis rotation amounts in radians
		vec3 _scale;

		vec3 _forward;
		vec3 _right;
		vec3 _up;

		mat4 _matrix;
		
		bool _isDirty;
	};
	
} // end namespace Component
#endif //_nub_device_transform_h_
//
// file : camera.h
//

#ifndef _nub_device_camera_h_
#define _nub_device_camera_h_

#include "transform.h"

class cCamera
{
public:
	cCamera();
	cCamera(const cCamera&) { /*empty copy constructor*/ }
    ~cCamera()              { /*empty destructor*/       }

	DirectX::XMFLOAT4X4   getViewMatrix();
	DirectX::XMFLOAT4X4   getReflectionViewMatrix();

	void update();
	void updateReflection( float );
	
//	void addPosition( float, float, float );
//	void addRotation( float, float, float );

	Component::cTransform transform;

private:
	DirectX::XMFLOAT4X4   _reflectionMatrix;
	DirectX::XMFLOAT4X4   _viewMatrix;
};

#endif //_nub_device_camera_h_
//
// file : camera.cpp
//

#include "stdafx.h"
#include "camera.h"

using namespace DirectX;

cCamera::cCamera() {}

DirectX::XMFLOAT4X4 cCamera::getViewMatrix()
{
	return _viewMatrix;
}

DirectX::XMFLOAT4X4 cCamera::getReflectionViewMatrix()
{
	return _reflectionMatrix;
}

void cCamera::update()
{
	transform.update();

	// build inverse transpose for the view matrix
	vec3 viewX   = transform.getRight();
	vec3 viewY   = transform.getUp();
	vec3 viewZ   = transform.getForward();
	XMVECTOR vp  = XMLoadFloat3(&transform.getPosition());
	
	_viewMatrix.m[0][0] = viewX.x;
	_viewMatrix.m[0][1] = viewY.x;
	_viewMatrix.m[0][2] = viewZ.x;
	_viewMatrix.m[0][3] = 0.0f;

	_viewMatrix.m[1][0] = viewX.y;
	_viewMatrix.m[1][1] = viewY.y;
	_viewMatrix.m[1][2] = viewZ.y;
	_viewMatrix.m[1][3] = 0.0f;
	
	_viewMatrix.m[2][0] = viewX.z;
	_viewMatrix.m[2][1] = viewY.z;
	_viewMatrix.m[2][2] = viewZ.z;
	_viewMatrix.m[2][3] = 0.0f;
	
	_viewMatrix.m[3][0] = XMVectorGetX(XMVector3Dot(-vp, XMLoadFloat3(&viewX)));
	_viewMatrix.m[3][1] = XMVectorGetY(XMVector3Dot(-vp, XMLoadFloat3(&viewY)));
	_viewMatrix.m[3][2] = XMVectorGetZ(XMVector3Dot(-vp, XMLoadFloat3(&viewZ)));
	_viewMatrix.m[3][3] = 1.0f;

	/*
	// kept this here for future attempt towards a 'look at' routine

	XMMATRIX rotationMatrix;
	XMVECTOR up, position, lookat;
	float yaw, pitch, roll;
	
	position = XMLoadFloat4(&_position);
	up       = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
	lookat   = XMVectorSet( 0.0f, 0.0f, 1.0f, 0.0f );

	yaw      = _rotation.y;
	pitch    = _rotation.x;
	roll     = _rotation.z;
	rotationMatrix = XMMatrixRotationRollPitchYaw( -pitch, yaw, roll );

	// move to camera space
	lookat = XMVector3TransformCoord( lookat, rotationMatrix );
	up     = XMVector3TransformCoord( up, rotationMatrix );
	lookat = position + lookat;
	XMStoreFloat4x4(&_viewMatrix, XMMatrixLookAtLH( position, lookat, up ));
	*/
}


void cCamera::updateReflection( float height )
{
	XMVECTOR up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
	
	XMFLOAT3 pos = transform.getPosition();
	pos.y = -pos.y + (height*2.0f);

	float yaw = transform.getAxisRotations().y;
	XMVECTOR lookat = XMVectorSet( sinf(yaw) + pos.x, pos.y, cosf(yaw) + pos.z, 0.0f );
	XMStoreFloat4x4(&_reflectionMatrix, XMMatrixLookAtLH( XMLoadFloat3(&pos), lookat, up )); 
}

 

Edited by GoliathForge
dropped example code for assumed modern directX 3d camera

Share this post


Link to post
Share on other sites

In my camera class i extract up right front vectors same like you and then to apply camera position i multiple rotation camera matrix with translation matrix so you should define constant position and apply that to transslation mat tthen multiple rot * trans

template <class T> void
glLookAt(Matrix44<T> &matrix, t3dpoint<T> eyePosition3D, t3dpoint<T> center3D, t3dpoint<T> upVector3D )
{
   t3dpoint<T>  forward, side, up;
   forward = Normalize( vectorAB(eyePosition3D, center3D) );
   side = Normalize( forward * upVector3D );
   up = side * forward;
  matrix.LoadIdentity();

	matrix.m[0] = side.x;
	matrix.m[1] = side.y;
	matrix.m[2] = side.z;

	matrix.m[4] = up.x;
	matrix.m[5] = up.y;
	matrix.m[6] = up.z;

	matrix.m[8] 	= -forward.x;
	matrix.m[9] 	= -forward.y;
	matrix.m[10] 	= -forward.z;



Matrix44<T> transgender;
transgender.Translate(-eyePosition3D.x, -eyePosition3D.y, -eyePosition3D.z);


matrix = transgender * matrix;
} We

 

Share this post


Link to post
Share on other sites

@WiredCat That looks great. I'm a huge openGL fan boy...

The difference is 4x4 matrix multiplication involves 64 multiplies and 48 additions, while the dot requires 3 and 2 respectively 3 times for the translation assignment which is 9 multiplications and 6 additions. Perhaps not a big deal for a camera, but apply that logic to a ton of objects begins to get wasteful. 

Here is a visual to compare the two operations to show that matrix multiplication is similar to dot. (pulled from an old openGL project)

inline cMatrix4 &cMatrix4::operator*=(const cMatrix4 &rhs)
{
    cMatrix4 tmp;

    // Row 1.
    tmp.e[0][0] = (e[0][0] * rhs.e[0][0]) + (e[0][1] * rhs.e[1][0]) + (e[0][2] * rhs.e[2][0]) + (e[0][3] * rhs.e[3][0]);
    tmp.e[0][1] = (e[0][0] * rhs.e[0][1]) + (e[0][1] * rhs.e[1][1]) + (e[0][2] * rhs.e[2][1]) + (e[0][3] * rhs.e[3][1]);
    tmp.e[0][2] = (e[0][0] * rhs.e[0][2]) + (e[0][1] * rhs.e[1][2]) + (e[0][2] * rhs.e[2][2]) + (e[0][3] * rhs.e[3][2]);
    tmp.e[0][3] = (e[0][0] * rhs.e[0][3]) + (e[0][1] * rhs.e[1][3]) + (e[0][2] * rhs.e[2][3]) + (e[0][3] * rhs.e[3][3]);

    // Row 2.
    tmp.e[1][0] = (e[1][0] * rhs.e[0][0]) + (e[1][1] * rhs.e[1][0]) + (e[1][2] * rhs.e[2][0]) + (e[1][3] * rhs.e[3][0]);
    tmp.e[1][1] = (e[1][0] * rhs.e[0][1]) + (e[1][1] * rhs.e[1][1]) + (e[1][2] * rhs.e[2][1]) + (e[1][3] * rhs.e[3][1]);
    tmp.e[1][2] = (e[1][0] * rhs.e[0][2]) + (e[1][1] * rhs.e[1][2]) + (e[1][2] * rhs.e[2][2]) + (e[1][3] * rhs.e[3][2]);
    tmp.e[1][3] = (e[1][0] * rhs.e[0][3]) + (e[1][1] * rhs.e[1][3]) + (e[1][2] * rhs.e[2][3]) + (e[1][3] * rhs.e[3][3]);

    // Row 3.
    tmp.e[2][0] = (e[2][0] * rhs.e[0][0]) + (e[2][1] * rhs.e[1][0]) + (e[2][2] * rhs.e[2][0]) + (e[2][3] * rhs.e[3][0]);
    tmp.e[2][1] = (e[2][0] * rhs.e[0][1]) + (e[2][1] * rhs.e[1][1]) + (e[2][2] * rhs.e[2][1]) + (e[2][3] * rhs.e[3][1]);
    tmp.e[2][2] = (e[2][0] * rhs.e[0][2]) + (e[2][1] * rhs.e[1][2]) + (e[2][2] * rhs.e[2][2]) + (e[2][3] * rhs.e[3][2]);
    tmp.e[2][3] = (e[2][0] * rhs.e[0][3]) + (e[2][1] * rhs.e[1][3]) + (e[2][2] * rhs.e[2][3]) + (e[2][3] * rhs.e[3][3]);

    // Row 4.
    tmp.e[3][0] = (e[3][0] * rhs.e[0][0]) + (e[3][1] * rhs.e[1][0]) + (e[3][2] * rhs.e[2][0]) + (e[3][3] * rhs.e[3][0]);
    tmp.e[3][1] = (e[3][0] * rhs.e[0][1]) + (e[3][1] * rhs.e[1][1]) + (e[3][2] * rhs.e[2][1]) + (e[3][3] * rhs.e[3][1]);
    tmp.e[3][2] = (e[3][0] * rhs.e[0][2]) + (e[3][1] * rhs.e[1][2]) + (e[3][2] * rhs.e[2][2]) + (e[3][3] * rhs.e[3][2]);
    tmp.e[3][3] = (e[3][0] * rhs.e[0][3]) + (e[3][1] * rhs.e[1][3]) + (e[3][2] * rhs.e[2][3]) + (e[3][3] * rhs.e[3][3]);

    *this = tmp;
    return *this;
}


inline float cVector3::dot(const cVector3 &p, const cVector3 &q)
{
    return (p.x * q.x) + (p.y * q.y) + (p.z * q.z);
}

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!