• entries
33
69
• views
32024

# 3D Graphics Part 1 Introduction

2798 views

In this post I'm going to explain the basics of 3D graphics

# What Is A 3D Scene Consisted Of?

Consider a street with cars. This scene is consisted of several objects, several car lights, and if it's day we have sun as a light. This scene have some objects like cars, street, and maybe some buildings. The are also have some lights like sun, car lights and so on.

The scene objects are the geometry of the scene. The geometry is the approximation of the surfaces of the objects in the scene by triangles or other polygons (like you have a cube in the scene, a cube has 6 faces that are squares, each face can be a represented by a quad or a pair of triangles). These triangles/polygons are represented by their vertices, and each vertex is a location of a point in a 3D space (E.g. (0,0,0) , (1,0,0) , (1,1,0) these 3 points represent a triangle).These objects are designed by artists.

As I said there are lights in the scene too. Well without light the scene will be totally dark.

Figure 1-1 A scene represented only by the edges of triangles of its geometry.(This is called wireframe view)

Figure 1-2 A scene represented only by the vertices of triangles of its geometry.

Figure 1-3 The scene with filled triangles shaded.

# How To Draw A Scene

We draw the scene by defining a camera in the scene. The drawing process is also similar to the way the image takes shape in a camera (which is also similar to eye).(Figure 2-1)

Figure 2-1 The image projected to on to the red surface (which is the screen in our case and is mostly referred to as Near Plane) this projection is done using the yellow point (which in our case will always be (0,0,0), the view matrix causes this which is explained later).

Now a camera in the scene is defined by two matrices, a view matrix and a projection matrix. To understand these, first you need to know some basic math.

# Required Math Knowledge

For 3D graphics we use Homogeneous Coordinates, in this system a 3D point is represented as (x, y, z, w) where w ? 0, where the actual position of the point is (x, y, z) / w (which is (x / w, y / w, z / w)), and a vector is represented as (x, y, z, 0). This is like this so we can transform points easier using a 4x4 matrix. You can transform a point using a matrix by multiplying the matrix to that point.

Matrices: We mostly use matrices to transform points, there are several kind of transformation, these transformations are:
1-Rotation
2-Translation
3-Scaling
4-Projection

The code at the end of the post shows how these are done (don't want to bother with math here, you can search for 4x4 matrix for each of these transformations, they are also available on MSDN).

Vectors: Vectors have two component, a direction and a length. For a vector (x, y, z, 0) the length is calculated as sqrt(x*x + y*y + z*z) (sqrt denotes the square-root function) (The length of the vector V will be denoted as ||V||). The direction of a vector is the normalized (a vector with the length of 1) vector. So the direction of the (x, y, z, 0) will be:

For l as the length of the vector:

l = sqrt(x*x + y*y + z*z)

The direction will be:

D = (x, y, z, 0)/l = (x/l, y/l, z/l, 0)

Note: a direction is always a normalized vector.

Cross Product: The cross product of two vectors is a vector perpendicular to those vectors and its length is:

||cross(V,U)|| = ||V||*||U||*sin(theta)
theta is the angle between the two vectors

For V(x[sub]1[/sub],y[sub]1[/sub],z[sub]1[/sub]) and U(x[sub]2[/sub],y[sub]2[/sub],z[sub]2[/sub]) we have:

cross(V,U) = (y[sub]1[/sub]*z[sub]2[/sub] - y[sub]2[/sub]*z[sub]1[/sub], z[sub]1[/sub]*x[sub]2[/sub] - z[sub]2[/sub]*x[sub]1[/sub], x[sub]1[/sub]*y[sub]2[/sub] - x[sub]2[/sub]*y[sub]1[/sub])

Dot Product: The result of the dot product is:
For V(x[sub]1[/sub],y[sub]1[/sub],z[sub]1[/sub]) and U(x[sub]2[/sub],y[sub]2[/sub],z[sub]2[/sub]) we have:
dot(V,U) = ||V||*||U||*cos(theta) = x[sub]1[/sub]*x[sub]2[/sub] + y[sub]1[/sub]*y[sub]2[/sub] + z[sub]1[/sub]*z[sub]2[/sub]

# Camera

As I said a camera is defined by two matrices. Now each of these matrices is a 4x4 matrix. The view matrix transforms coordinate in a way that the origin of the new coordinate system is will be the camera and the axes will be aligned with the forward vector (the vector showing the direction at which the camera is looking) and up vector (the vector that shows the direction of the camera's top) (Figure 4-1)

Figure 4-1 The green arrow shows the up direction and the blue arrow shows the direction of the forward vector.

So what the view matrix does is to first translate the coordinates so that the camera will be the origin of the new coordinates, then it rotates the coordinates in a way that the axes become aligned with the up and forward vectors. So a view matrix is the multiplication of a translation matrix and a rotation matrix. Coordinates after being transformed by the view matrix are said to be in view space.

Now what projection matrix does, is to project all of the scene on the near plane (Figure 2-1 and Figure 4-1) and then it scales the projected scene in a way that the wanted portion of the scene will have a coordinate (x, y, z) of x, y, z at the range of [-1, 1]. This is because most common APIs (like OpenGL and D3D) use this kind of normalized coordinates to draw the scene. The z value will represent the depth used for the depth test (explained later), and the x, y represent the position on the screen where (-1,-1) is the bottom left corner of the screen and (1,1) is the top right corner of the screen.

As said the projection matrix scales the projected scene in according the selected portion of the scene, this portion is defined by left, right, bottom, top, near,and far (these values are in light view). The portion selected is a frustum, the near defines how far the near plane is from the camera and the far value defines the z scale, the range between near and far values will be scale to 1.

So what we do is to transform the vertices by the view and projection matrix and feed the data to the API (like OpenGL or D3D). This is done by:

ProjectedVertex = ProjectionMatrix * ViewMatrix * Vertex;

This transformation is done per vertex, and this is done by a vertex shader (a program ran on GPU for each vertex descried in the next post), after the projection transformation the surface of the projected scene/geometry is divided to several fragments/pixels and a fragment/pixel program is ran for each fragments/pixels (this program is called fragment/pixel shader descried in the next post) and then the fragment/pixel shader determines the color of each fragment, and this way a picture is drawn.

# Some Math Code

Some basic point and vector class: class point //point class { public: long double x, y, z; void __fastcall build(long double ix, long double iy, long double iz); //build point void __fastcall build(float ix, float iy, float iz); //build point with float (idiot nvidia) void __fastcall move(long double ax = long double(0.0), long double ay = long double(0.0), long double az = long double(0.0)); //move point void __fastcall rotate(point from, long double ax = long double(0.0), long double ay = long double(0.0), long double az = long double(0.0)); //rotate point void __fastcall move(float ax = 0.0f, float ay = 0.0f, float az = 0.0f); //move point float void __fastcall rotate(point from, float ax = 0.0f, float ay = 0.0f, float az = 0.0f); //rotate point float void __fastcall operator =(point intery); //operator = }; //end of point class class vector //3d vector class { public: long double x, y, z; void __fastcall build(point start, point end);//point to point vector void __fastcall build(long double ix, long double iy, long double iz);//simpile build void __fastcall build(float ix, float iy, float iz);//simpile build with float void __fastcall operator =(vector intery);//set value vector __fastcall operator +(vector entry);//vector vector sum vector __fastcall operator *(long double entry);//vector number multipliction vector __fastcall operator /(long double entry);//vector number division vector __fastcall operator *(float entry);//vector number multipliction vector __fastcall operator /(float entry);//vector number division long double __fastcall getsize();//get vector size long double __fastcall getsizeSq();//get vector size squared }; //end of 3d vector class long double __fastcall dot(vector v1, vector v2); //dot product vector __fastcall cross(vector v1, vector v2); //cross product vector __fastcall normalize(vector v1); //normalize void __fastcall point::build(long double ix, long double iy, long double iz) //build point { x = ix; //set x value y = iy; //set y value z = iz; //set z value } void __fastcall point::build(float ix, float iy, float iz) //build point { x = long double(ix); //set x value y = long double(iy); //set y value z = long double(iz); //set z value } void __fastcall point::move(long double ax, long double ay, long double az) //move the point { x = x + ax; //move along x axis y = y + ay; //move along y axis z = z + az; //move along z axis } void __fastcall point::rotate(point from, long double ax, long double ay, long double az) //rotate point { long double dx, dy, dz;//point coord in new space whit "from" as the origin dx = x - from.x; //transform x to new world dy = y - from.y; //transform y to new world dz = z - from.z; //transform z to new world x = from.x + (dx*(cos(ay)*cos(az)) + dy*(-1 * cos(ax)*sin(az) + sin(ax)*sin(ay)*cos(az)) + dz*(sin(ax)*sin(az) + cos(ax)*sin(ay)*cos(az))); //do the rotation on x y = from.y + (dx*(cos(ay)*sin(az)) + dy*(cos(ax)*cos(az) + sin(ax)*sin(ay)*sin(az)) + dz*(-1 * sin(ax)*cos(az) + cos(ax)*sin(ay)*sin(az))); //do the rotation on y z = from.z + (dx*-1 * sin(ay) + dy*sin(ax)*cos(ay) + dz*cos(ax)*cos(ay)); //do the rotation on z } void __fastcall point::move(float ax, float ay, float az) //just do a conversion { move(long double(ax), long double(ay), long double(az)); } void __fastcall point::rotate(point from, float ax, float ay, float az)//rotate point { rotate(from, long double(ax), long double(ay), long double(az));//just do a conversion } void __fastcall point::operator =(point intery) //operator = { build(intery.x, intery.y, intery.z);//build the point } void __fastcall vector::build(point start, point end)//point to point vector { x = end.x - start.x; y = end.y - start.y; z = end.z - start.z; } void __fastcall vector::build(long double ix, long double iy, long double iz)//simpil build { x = ix; y = iy; z = iz; } void __fastcall vector::build(float ix, float iy, float iz)//simpile build with float { x = long double(ix); //set x value y = long double(iy); //set y value z = long double(iz); //set z value } void __fastcall vector::operator =(vector intery)//set value { build(intery.x, intery.y, intery.z); } vector __fastcall vector::operator + (vector entry) //vector vector sum { vector ret; ret.build(entry.x + x, entry.y + y, entry.z + z); return ret; } vector __fastcall vector::operator *(long double entry)//vector number multipliction { vector ret; ret.build(entry*x, entry*y, entry*z); return ret; } vector __fastcall vector::operator /(long double entry)//division by long double { vector ret; ret.build(x / entry, y / entry, z / entry); return ret; } vector __fastcall vector::operator *(float entry)//vector float number multipliction { vector ret; ret.build(x * long double(entry), y* long double(entry), z * long double(entry)); return ret; } vector __fastcall vector::operator /(float entry)//division by float { vector ret; ret.build(x / long double(entry), y / long double(entry), z / long double(entry)); return ret; } long double __fastcall vector::getsize()//get vector size { return sqrt(x*x + y*y + z*z); } long double __fastcall vector::getsizeSq()//get vector size squared { return x*x + y*y + z*z; } long double __fastcall dot(vector v1, vector v2) //dot product { return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); } vector __fastcall cross(vector v1, vector v2) //cross product { vector temple; temple.build(v1.y*v2.z - v2.y*v1.z, v1.z*v2.x - v2.z*v1.x, v1.x*v2.y - v2.x*v1.y); return temple; } vector __fastcall normalize(vector v1)//normalize { return v1/v1.getsize(); }
Some basic functions for matrices (the LookAt function returns a view matrix and the Projection matrix returns a projection matrix): class _4x4matrix //4*4 matrix { public: union {#ifdef _M_X64 __declspec(align(16)) float x[16]; __declspec(align(16)) float xy[4][4]; __declspec(align(16)) __m128 data_row[4];#else float x[16]; float xy[4][4];#endif }; _4x4matrix __fastcall operator * (_4x4matrix input);//mat4 multiply vector __fastcall operator * (vector input);//mat4 multiply by vector point __fastcall operator * (point input);//mat4 multiply by point void __fastcall operator = (_4x4matrix input);//= void __fastcall LoadIdentity();//load matric with i void __fastcall LoadZero();//load matric with 0 void __fastcall LoadScaler(float sx, float sy, float sz);//load scaler matrix void __fastcall LoadTranslate(float sx, float sy, float sz);//load translate matrix void __fastcall LoadRotation(vector axis, point origin, float theta);//load rotation matrix }; //end of matrix class _4x4matrix LookAt(point cam_pos,vector forward,vector up);//get view mat _4x4matrix Projection(float left, float right, float buttom, float top, float nearz, float farz);//projection matrix _4x4matrix __fastcall Inverse(_4x4matrix input);//invers mat _4x4matrix __fastcall Transpose(_4x4matrix input);//invers mat void __fastcall _4x4matrix::operator = (_4x4matrix input)//mat4 multiply { for (register int i = 0; i < 16; i++) //go through array x = input.x; } _4x4matrix __fastcall _4x4matrix::operator * (_4x4matrix input)//mat4 multiply { _4x4matrix ret;#ifndef _M_X64 ret.LoadZero();//set it to zero for (register int i = 0; i < 16; i++) //go through array for (register int j = 0; j < 4; j++) //go through columns and rows ret.x += x[int(i / 4) * 4 +j] * input.x[j * 4 + i % 4]; //do the multipliction #else register __declspec(align(16)) __m128 temp[4]; _MM_TRANSPOSE4_PS(input.data_row[0], input.data_row[1], input.data_row[2], input.data_row[3]); for (register int i = 0; i < 4; i++) { temp[0] = _mm_mul_ps(data_row, input.data_row[0]); temp[1] = _mm_mul_ps(data_row, input.data_row[1]); temp[2] = _mm_mul_ps(data_row, input.data_row[2]); temp[3] = _mm_mul_ps(data_row, input.data_row[3]); _MM_TRANSPOSE4_PS(temp[0], temp[1], temp[2], temp[3]); ret.data_row = _mm_add_ps(temp[3], _mm_add_ps(temp[2], _mm_add_ps(temp[1], temp[0]))); }#endif return ret; } vector __fastcall _4x4matrix::operator * (vector input)//mat4 multiply { vector ret; ret.x = x[0] * input.x + x[1] * input.y + x[2] * input.z; ret.y = x[4] * input.x + x[5] * input.y + x[6] * input.z;//do the multiplication there is no w its vector ret.z = x[8] * input.x + x[9] * input.y + x[10] * input.z; return ret; } point __fastcall _4x4matrix::operator * (point input)//mat4 multiply { point ret; long double w; ret.x = x[0] * input.x + x[1] * input.y + x[2] * input.z + x[3]; ret.y = x[4] * input.x + x[5] * input.y + x[6] * input.z + x[7];//do the multiplication there is no w its vector ret.z = x[8] * input.x + x[9] * input.y + x[10] * input.z + x[11]; w = x[12] * input.x + x[13] * input.y + x[14] * input.z + x[15];//calculate w ret.x /= w;//divide by w ret.y /= w; ret.z /= w; return ret; } void __fastcall _4x4matrix::LoadIdentity()//load matric with i { for (register int i = 0; i < 16; i++) if (i % 5 == 0) x = 1.0; else x = 0.0; } void __fastcall _4x4matrix::LoadZero()//load matric with 0 { for (register int i = 0; i < 16; i++) x = 0.0; } void __fastcall _4x4matrix::LoadScaler(float sx,float sy,float sz)//load scaler matrix { LoadIdentity();//w is set to 1 all others are 0 x[0] = sx; x[5] = sy; //set the matrix x[10] = sz; } void __fastcall _4x4matrix::LoadTranslate(float sx, float sy, float sz)//load translate matrix { LoadIdentity();//load i x[3] = sx; x[7] = sy; //set the matrix x[11] = sz; } void __fastcall _4x4matrix::LoadRotation(vector axis, point origin, float theta)//load rotation matrix { axis = normalize(axis); float u = (float)axis.x, v = (float)axis.y, w = (float)axis.z; float u2 = float(axis.x*axis.x), v2 = float(axis.y*axis.y), w2 = float(axis.z*axis.z); float a = (float)origin.x, b = (float)origin.y, c = (float)origin.z; x[0] = (float)u2 + (v2 + w2)*cos(theta); x[1] = (float)u*v*(1 - cos(theta)) - w*sin(theta); x[2] = (float)w*u*(1 - cos(theta)) + v*sin(theta); x[3] = (float)(a*(v2 + w2) - u*(b*v + c*w))*(1 - cos(theta)) + (b*w - c*v)*sin(theta); x[4] = (float)u*v*(1 - cos(theta)) + w*sin(theta); x[5] = (float)v2 + (u2 + w2)*cos(theta); x[6] = (float)w*v*(1 - cos(theta)) - u*sin(theta); x[7] = (float)(b*(u2 + w2) - v*(a*u + c*w))*(1 - cos(theta)) + (c*u - a*w)*sin(theta); x[8] = (float)u*w*(1 - cos(theta)) - v*sin(theta); x[9] = (float)w*v*(1 - cos(theta)) + u*sin(theta); x[10] = (float)w2 + (v2 + u2)*cos(theta); x[11] = (float)(c*(u2 + v2) - w*(b*v + a*u))*(1 - cos(theta)) + (a*v - b*u)*sin(theta); x[12] = (float)0.0; x[13] = (float)0.0; x[14] = (float)0.0; x[15] = (float)1; } _4x4matrix LookAt(point cam_pos, vector forward, vector up) { vector xaxis, yaxis, zaxis;//define axises; vector eye;//campos in vetor shape eye.build(cam_pos.x, cam_pos.y, cam_pos.z);//set eye as campos zaxis = normalize(forward*-1.0f);//set z axis xaxis = normalize(cross(up, zaxis));//get x axis normalized yaxis = cross(zaxis, xaxis); //get y axis (already normalized) _4x4matrix return_mat; return_mat.x[0] = (float)xaxis.x; return_mat.x[4] = (float)yaxis.x; return_mat.x[8] = (float)zaxis.x; return_mat.x[12] = (float)0.0; return_mat.x[1] = (float)xaxis.y; return_mat.x[5] = (float)yaxis.y; return_mat.x[9] = (float)zaxis.y; return_mat.x[13] = (float)0.0; return_mat.x[2] = (float)xaxis.z; return_mat.x[6] = (float)yaxis.z; return_mat.x[10] = (float)zaxis.z; return_mat.x[14] = (float)0.0; return_mat.x[3] = (float)-dot(xaxis, eye); return_mat.x[7] = (float)-dot(yaxis, eye); return_mat.x[11] = (float)-dot(zaxis, eye); return_mat.x[15] = (float)1.0; /* xaxis.x yaxis.x zaxis.x 0 xaxis.y yaxis.y zaxis.y 0 xaxis.z yaxis.z zaxis.z 0 - dot(xaxis, eye) - dot(yaxis, eye) - dot(zaxis, eye) 1*/ return return_mat; } _4x4matrix Projection(float left, float right, float buttom, float top, float nearz, float farz) { _4x4matrix return_mat; float w = right - left;//width float h = top - buttom;//height float d = farz - nearz;//depth return_mat.x[0] = (float)2.0 * nearz / w; return_mat.x[4] = (float)0.0; return_mat.x[8] = (float)0.0; return_mat.x[12] = (float)0.0; return_mat.x[1] = (float)0.0; return_mat.x[5] = (float)2.0 * nearz / h; return_mat.x[9] = (float)0.0; return_mat.x[13] = (float)0.0; return_mat.x[2] = (float)(right + left) / w; return_mat.x[6] = (float)(top + buttom) / h; return_mat.x[10] = (float)-1.0*(farz + nearz) / d; return_mat.x[14] = (float)-1.0; return_mat.x[3] = (float)0.0; return_mat.x[7] = (float)0.0; return_mat.x[11] = (float)-1.0*nearz*farz / d; return_mat.x[15] = (float)0.0; return return_mat; } _4x4matrix __fastcall Inverse(_4x4matrix input)//invers mat { float det = 0; _4x4matrix return_mat; return_mat.x[0] = input.x[5] * (input.x[10] * input.x[15] - input.x[11] * input.x[14]) - input.x[9] * (input.x[6] * input.x[15] - input.x[7] * input.x[14]) + input.x[13] * (input.x[6] * input.x[11] - input.x[7] * input.x[10]); return_mat.x[4] = -input.x[4] * (input.x[10] * input.x[15] - input.x[11] * input.x[14]) + input.x[8] * (input.x[6] * input.x[15] - input.x[7] * input.x[14]) - input.x[12] * (input.x[6] * input.x[11] - input.x[7] * input.x[10]); return_mat.x[8] = input.x[4] * (input.x[9] * input.x[15] - input.x[11] * input.x[13]) - input.x[8] * (input.x[5] * input.x[15] - input.x[7] * input.x[13]) + input.x[12] * (input.x[5] * input.x[11] - input.x[7] * input.x[9]); return_mat.x[12] = -input.x[4] * (input.x[9] * input.x[14] - input.x[10] * input.x[13]) + input.x[8] * (input.x[5] * input.x[14] - input.x[6] * input.x[13]) - input.x[12] * (input.x[5] * input.x[10] - input.x[6] * input.x[9]); return_mat.x[1] = -input.x[1] * (input.x[10] * input.x[15] - input.x[11] * input.x[14]) + input.x[9] * (input.x[2] * input.x[15] - input.x[3] * input.x[14]) - input.x[13] * (input.x[2] * input.x[11] - input.x[3] * input.x[10]); return_mat.x[5] = input.x[0] * (input.x[10] * input.x[15] - input.x[11] * input.x[14]) - input.x[8] * (input.x[2] * input.x[15] - input.x[3] * input.x[14]) + input.x[12] * (input.x[2] * input.x[11] - input.x[3] * input.x[10]); return_mat.x[9] = -input.x[0] * (input.x[9] * input.x[15] - input.x[11] * input.x[13]) + input.x[8] * (input.x[1] * input.x[15] - input.x[3] * input.x[13]) - input.x[12] * (input.x[1] * input.x[11] - input.x[3] * input.x[9]); return_mat.x[13] = input.x[0] * (input.x[9] * input.x[14] - input.x[10] * input.x[13]) - input.x[8] * (input.x[1] * input.x[14] - input.x[2] * input.x[13]) + input.x[12] * (input.x[1] * input.x[10] - input.x[2] * input.x[9]); return_mat.x[2] = input.x[1] * (input.x[6] * input.x[15] - input.x[7] * input.x[14]) - input.x[5] * (input.x[2] * input.x[15] - input.x[3] * input.x[14]) + input.x[13] * (input.x[2] * input.x[7] - input.x[3] * input.x[6]); return_mat.x[6] = -input.x[0] * (input.x[6] * input.x[15] - input.x[7] * input.x[14]) + input.x[4] * (input.x[2] * input.x[15] - input.x[3] * input.x[14]) - input.x[12] * (input.x[2] * input.x[7] - input.x[3] * input.x[6]); return_mat.x[10] = input.x[0] * (input.x[5] * input.x[15] - input.x[7] * input.x[13]) - input.x[4] * (input.x[1] * input.x[15] - input.x[3] * input.x[13]) + input.x[12] * (input.x[1] * input.x[7] - input.x[3] * input.x[5]); return_mat.x[14] = -input.x[0] * (input.x[5] * input.x[14] - input.x[6] * input.x[13]) + input.x[4] * (input.x[1] * input.x[14] - input.x[2] * input.x[13]) - input.x[12] * (input.x[1] * input.x[6] - input.x[2] * input.x[5]); return_mat.x[3] = -input.x[1] * (input.x[6] * input.x[11] - input.x[7] * input.x[10]) + input.x[5] * (input.x[2] * input.x[11] - input.x[3] * input.x[10]) - input.x[9] * (input.x[2] * input.x[7] - input.x[3] * input.x[6]); return_mat.x[7] = input.x[0] * (input.x[6] * input.x[11] - input.x[7] * input.x[10]) - input.x[4] * (input.x[2] * input.x[11] - input.x[3] * input.x[10]) + input.x[8] * (input.x[2] * input.x[7] - input.x[3] * input.x[6]); return_mat.x[11] = -input.x[0] * (input.x[5] * input.x[11] - input.x[7] * input.x[9]) + input.x[4] * (input.x[1] * input.x[11] - input.x[3] * input.x[9]) - input.x[8] * (input.x[1] * input.x[7] - input.x[3] * input.x[5]); return_mat.x[15] = input.x[0] * (input.x[5] * input.x[10] - input.x[6] * input.x[9]) - input.x[4] * (input.x[1] * input.x[10] - input.x[2] * input.x[9]) + input.x[8] * (input.x[1] * input.x[6] - input.x[2] * input.x[5]); det = input.x[0] * return_mat.x[0] + input.x[1] * return_mat.x[4] + input.x[2] * return_mat.x[8] + input.x[3] * return_mat.x[12]; if (det == 0) { return_mat.LoadZero(); return return_mat;//det is zero it's not inversable } for (register int i = 0; i < 16; i++) return_mat.x = return_mat.x / det; return return_mat; } _4x4matrix __fastcall Transpose(_4x4matrix input)//transpose mat { _4x4matrix return_mat;#ifndef _M_X64 for (register int i = 0; i < 16; i++) return_mat.x = input.x[(i%4)*4+int(i/4)];#else return_mat.data_row[0] = input.data_row[0]; return_mat.data_row[1] = input.data_row[1]; return_mat.data_row[2] = input.data_row[2]; return_mat.data_row[3] = input.data_row[3]; _MM_TRANSPOSE4_PS(return_mat.data_row[0], return_mat.data_row[1], return_mat.data_row[2], return_mat.data_row[3]);#endif return return_mat; }

Thanks for reading I'm more than happy to help understanding any parts of my post so feel free to ask on comments. I will continue this at my next post.

## For cross product we have:

I liked this but the colour scheme for the code examples isn't very good i found it hard to read the comments the most

yes, sorry for the code, I tried to edit the theme but I couldn't, I should first reset the theme and then I may be able to edit it but I don't trust the GD net that much, anyways thanks for reading and your comment.

Unfortunately the software doesn't support editing your theme, but you can submit a fresh one -- just send me a private message or report your journal so we'll know to approve the changes -- unfortunately there are no notifications of a theme pending approval.

thank for the help, i'll change the theme and report it

Cross product(u,v) is ||u|| * ||v|| * Sin(theta) * normal

not just ||u|| * ||v|| * Sin(theta) (this is a scalar value if you do not multiply it by the normal).

Cross Product: The cross product of two vectors is a vector perpendicular to those vectors and its length is:

||cross(V,U)|| = ||V||*||U||*sin(theta)
theta is the angle between the two vectors

I was talking about the length of the cross product not the cross product itself. (the || || denotes the length of the vector)

but again thanks for reading :D

It'd be even better to show how this definition of dot product of u.v:
u_x * v_x + u_y * v_y + u_z * v_z
is derived from
||u|| * ||v|| * cos(theta)

Pretty easy to do using law of cosine.

check the post I added the proofs

That's pretty complicated code (for me). Good job with including images.

The code is simply an implementation of the math, as I said you should search on the math, MSDN provides pretty good and useful stuff, you can check it out. Btw thanks for your reply, and thanks for reading ,

## Create an account

Register a new account