• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
MichaelDeCicco

Matrix problems

2 posts in this topic

I am putting together a little math library for a larger project, and I'm having trouble with my matrix math. This isn't the first time I've had this problem. The last time I had this problem I just used the GLM library instead of writing it all myself though, but now I think it's important for me to understand it well enough to do it myself.

I've made some regular old Vector2,3, and 4 classes to use as rows in my Matrix2,3, and 4 classes. My matrix classes are row major. My main concern right now is the Matrix4 class. Since all the Vector classes are pretty standard, I don't think it's necessary to put them here. Here's my Matrix4 class:

[CODE]
template <typename ValueType>
class Matrix4
{
public:
Matrix4()
{
Identity(1.0f);
}
Matrix4(const Matrix4 <ValueType>&Mat)
{
*this = Mat;
}
~Matrix4()
{
}

void DebugPrint() const
{
for(int i = 0;i < 4;i++)System::USystem::GetSystem()->Log(Ungine::System::LOG_MESSAGE,"%f\t%f\t%f\t%f\n",Rows[i][0],Rows[i][1],Rows[i][2],Rows[i][3]);
}

Matrix4 <ValueType>Transpose() const
{
Matrix4 <ValueType>Ret;

Ret[0][0] = Rows[0][0]; Ret[0][1] = Rows[1][0]; Ret[0][2] = Rows[2][0]; Ret[0][3] = Rows[3][0];
Ret[1][0] = Rows[0][1]; Ret[1][1] = Rows[1][1]; Ret[1][2] = Rows[2][1]; Ret[1][3] = Rows[3][1];
Ret[2][0] = Rows[0][2]; Ret[2][1] = Rows[1][2]; Ret[2][2] = Rows[2][2]; Ret[2][3] = Rows[3][2];
Ret[3][0] = Rows[0][3]; Ret[3][1] = Rows[1][3]; Ret[3][2] = Rows[2][3]; Ret[3][3] = Rows[3][3];

return Ret;
}
void operator =(const Matrix4 <ValueType>&Mat)
{
for(int i = 0;i < 4;i++) for(int j = 0;j < 4;j++) Rows[i][j] = Mat[i][j];
}
Matrix4 <ValueType>operator *(const Matrix4 <ValueType>&Mat) const
{
Matrix4 Ret;

Ret[0][0] = Rows[0].DotProduct(Mat.GetColumn(0));
Ret[0][1] = Rows[0].DotProduct(Mat.GetColumn(1));
Ret[0][2] = Rows[0].DotProduct(Mat.GetColumn(2));
Ret[0][3] = Rows[0].DotProduct(Mat.GetColumn(3));

Ret[1][0] = Rows[1].DotProduct(Mat.GetColumn(0));
Ret[1][1] = Rows[1].DotProduct(Mat.GetColumn(1));
Ret[1][2] = Rows[1].DotProduct(Mat.GetColumn(2));
Ret[1][3] = Rows[1].DotProduct(Mat.GetColumn(3));

Ret[2][0] = Rows[2].DotProduct(Mat.GetColumn(0));
Ret[2][1] = Rows[2].DotProduct(Mat.GetColumn(1));
Ret[2][2] = Rows[2].DotProduct(Mat.GetColumn(2));
Ret[2][3] = Rows[2].DotProduct(Mat.GetColumn(3));

Ret[3][0] = Rows[3].DotProduct(Mat.GetColumn(0));
Ret[3][1] = Rows[3].DotProduct(Mat.GetColumn(1));
Ret[3][2] = Rows[3].DotProduct(Mat.GetColumn(2));
Ret[3][3] = Rows[3].DotProduct(Mat.GetColumn(3));

return Ret;
}
Matrix4 <ValueType>operator *=(const Matrix4 <ValueType>&Mat)
{
*this = *this * Mat;
return *this;
}
Vector4 <ValueType>operator *(const Vector4<ValueType>&Vec) const
{
Vector4 <ValueType>Ret;

Ret.x = Rows[0].DotProduct(Vec);
Ret.y = Rows[1].DotProduct(Vec);
Ret.z = Rows[2].DotProduct(Vec);
Ret.w = Rows[3].DotProduct(Vec);

return Ret;
}
Vector3 <ValueType>operator *(const Vector3<ValueType>&Vec) const
{
Vector3 <ValueType>Ret;

Ret.x = Rows[0].DotProduct(Vec);
Ret.y = Rows[1].DotProduct(Vec);
Ret.z = Rows[2].DotProduct(Vec);

return Ret;
}

void Identity(ValueType id = 1.0f)
{
Rows[0] = Vector4 <ValueType>(id,0.0f,0.0f,0.0f);
Rows[1] = Vector4 <ValueType>(0.0f,id,0.0f,0.0f);
Rows[2] = Vector4 <ValueType>(0.0f,0.0f,id,0.0f);
Rows[3] = Vector4 <ValueType>(0.0f,0.0f,0.0f,id);
}
void Translate(const Vector3 <ValueType>&Trans)
{
Matrix4 <ValueType> Mat;

Mat[0] = Vector4 <ValueType>(1.0f,0.0f,0.0f,Trans.x);
Mat[1] = Vector4 <ValueType>(0.0f,1.0f,0.0f,Trans.y);
Mat[2] = Vector4 <ValueType>(0.0f,0.0f,1.0f,Trans.z);
Mat[3] = Vector4 <ValueType>(0.0f,0.0f,0.0f,1.0f );

*this = *this * Mat;
}
void Rotate(const Vector3 <ValueType>&Axis,ValueType Angle)
{
Matrix4 Mat;

ValueType hAngle = Angle * 0.5f;

ValueType SinAngle = Sin(hAngle);
ValueType CosAngle = Cos(hAngle);

ValueType w = CosAngle;
ValueType x = Axis.x * SinAngle;
ValueType y = Axis.y * SinAngle;
ValueType z = Axis.z * SinAngle;

ValueType xSq = x * x;
ValueType ySq = y * y;
ValueType zSq = z * z;
ValueType xy = x * y;
ValueType xz = x * z;
ValueType xw = x * w;
ValueType yw = y * w;
ValueType zw = z * w;
ValueType zy = z * y;

Mat[0][0] = 1.0f - 2.0f * (ySq + zSq);
Mat[0][1] = 2.0f * (xy + zw);
Mat[0][2] = 2.0f * (xz - yw);
Mat[0][3] = 0.0f;
Mat[1][0] = 2.0f * (xy - zw);
Mat[1][1] = 1.0f - 2.0f * (xSq + zSq);
Mat[1][2] = 2.0f * (zy + xw);
Mat[1][3] = 0.0f;
Mat[2][0] = 2.0f * (xz + yw);
Mat[2][1] = 2.0f * (zy - xw);
Mat[2][2] = 1.0f - 2.0f * (xSq + ySq);
Mat[2][3] = 0.0f;

Mat[3][0] = 0.0f;
Mat[3][1] = 0.0f;
Mat[3][2] = 0.0f;
Mat[3][3] = 1.0f;

*this = *this * Mat;
}
void Scale(ValueType Scale)
{
Matrix4 <ValueType> Mat;

Mat[0] = Vector4 <ValueType>(Scale,0.0f,0.0f,0.0f);
Mat[1] = Vector4 <ValueType>(0.0f,Scale,0.0f,0.0f);
Mat[2] = Vector4 <ValueType>(0.0f,0.0f,Scale,0.0f);
Mat[3] = Vector4 <ValueType>(0.0f,0.0f,0.0f,Scale);

*this = *this * Mat;
}
void Scale(const Vector4 <ValueType> &Scale)
{
Matrix4 <ValueType> Mat;

Mat[0] = Vector4 <ValueType>(Scale.x,0.0f,0.0f,0.0f);
Mat[1] = Vector4 <ValueType>(0.0f,Scale.y,0.0f,0.0f);
Mat[2] = Vector4 <ValueType>(0.0f,0.0f,Scale.z,0.0f);
Mat[3] = Vector4 <ValueType>(0.0f,0.0f,0.0f,Scale.w);

*this = *this * Mat;
}
ValueType Determinant() const
{
abort();
}
bool Inverse(Matrix4 <ValueType>*Mat)
{
abort();
return false;
}

ValueType *Ptr()
{
return &Rows[0].x;
}
Vector4 <ValueType>GetColumn(Index Idx) const
{
return Vector4 <ValueType>(Rows[0][Idx],Rows[1][Idx],Rows[2][Idx],Rows[3][Idx]);
}
Vector4 <ValueType>&operator[](Index Idx)
{
return Rows[Idx];
}
Vector4 <ValueType>operator[](Index Idx) const
{
return Rows[Idx];
}
protected:
Vector4 <ValueType>Rows[4];
};
[/CODE]

I realized I had a problems when I was trying to use this class to build a MVP matrix for a camera. No matter how I do it, what order I multiply in, whether or not the end MVP matrix or the individual matrices are transposed, what I see on the screen is just a very stretched out polygon. I am attempting to render a simple square at 0,0,0,0 with a perspective and orthographic projection.

Here's part of the render function where I am testing the matrix class:
[CODE]
System::USystem::GetSystem()->SetAngleType(Ungine::System::AT_DEGREE);

Matrix4f Model, View, Projection, MVP;
static f32 Val = 0.0f;
Val += 0.01f;
//Model.Translate(Vector3f(768 / 2,1024 / 2,0));
//Model.Rotate(Vector3f(0,1,1).Normalize(),Val / 2.0f);
//Model.Scale(Vector4f((2 + Math::Sin(Val)) * 0.5f,(2 + Math::Sin(Val)) * 0.5f,(2 + Math::Sin(Val)) * 0.5f,1.0f));//;Rotate(Vector3f(0,0,1),Val);
View = LookAt(Vector3f(0,0,-20.0f),Vector3f(0,0,0),Vector3f(0,1,0));

Projection = Perspectivef(50.0f,768.0f / 1024.0f,0.1f,1000.0f);
//Projection = Orthographicf(0.0f,768.0f,0.0f,1024.0f,0.0f,1000.0f);

MVP = Projection * View * Model;

glUniformMatrix4fv(MVP_Loc,1,false,MVP.Ptr());

[/CODE]

And here are the projection and LookAt functions:
[CODE]
Matrix4f Perspectivef(f32 FieldOfView,f32 AspectRatio,f32 Near,f32 Far)
{
Matrix4f Mat;

f32 TanFov = Tan(FieldOfView * 0.5f);

f32 a = 1.0f / (AspectRatio * TanFov);
f32 b = 1.0f / TanFov;
f32 c = Far / (Far - Near);
f32 d = -(2.0f * Near * Far) / (Far - Near);

Mat[0] = Vector4f(a , 0.0f , 0.0f , 0.0f);
Mat[1] = Vector4f(0.0f , b , 0.0f , 0.0f);
Mat[2] = Vector4f(0.0f , 0.0f , c , d );
Mat[3] = Vector4f(0.0f , 0.0f , 1.0f , 0.0f);

return Mat;
}
Matrix4f Orthographicf(f32 Left,f32 Right,f32 Top,f32 Bottom,f32 Near,f32 Far)
{
Matrix4f Mat;

f32 dW = Left - Right;
f32 dH = Top - Bottom;
f32 dL = Far - Near;

f32 Tx = (Right + Left) / (Right - Left);
f32 Ty = (Far + Near) / (Far - Near);
f32 Tz = (Top + Bottom) / (Top - Bottom);

Mat[0] = Vector4f(2.0f / (dW),0.0f ,0.0f ,Tx );
Mat[1] = Vector4f(0.0f ,2.0f / (dH),0.0f ,Ty );
Mat[2] = Vector4f(0.0f ,0.0f ,-(2.0f / dL),Tz );
Mat[3] = Vector4f(0.0f ,0.0f ,0.0f ,1.0f);

return Mat;
}
Matrix4f LookAt(const Vector3f &Eye,const Vector3f &Target,const Vector3f &Up)
{
Matrix4f Mat;

Vector3f Forward, Side, _Up;
Forward = (Target - Eye).Normalize();
Side = Forward.CrossProduct(Up).Normalize();
_Up = Side.CrossProduct(Forward).Normalize();
Mat[0] = Vector4f(Side ,0.0f );
Mat[1] = Vector4f(_Up ,0.0f );
Mat[2] = Vector4f(Forward * -1.0f,0.0f );
Mat[3] = Vector4f(0.0f ,0.0f,0.0f,1.0f);
Mat.Translate(Eye * -1.0f);

return Mat;
}
[/CODE]

It's a bunch of code to look through, but if anyone has the patience, could you tell me if you see anything that looks wrong?
Matrix4f is just Matrix4 <f32>. Also, sorry about the large amount of whitespace before each line, that's just from the indentation from two namespaces that I didn't include in the code, for some reason they got larger when I submitted this thread.

Thank you for your time!
0

Share this post


Link to post
Share on other sites
The fact that the results on the screen don't look right is a very high-level description of the problem. In order to debug your code it is much more useful to create an example with numbers that are simple enough that you can follow the computation by hand, and then step in with a debugger and see where the computations depart from what you expected.
0

Share this post


Link to post
Share on other sites
Thank you, I learned that I should be a little more patient and more analytical before asking questions. As it turns out, my math was right but I forgot to divide gl_Position by gl_Position.w in the vertex shader!

How annoying.
0

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
Sign in to follow this  
Followers 0