Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

HappyCoder

Member Since 28 Apr 2007
Offline Last Active Yesterday, 08:34 PM
-----

#4896660 Where can I start (3D math)

Posted by HappyCoder on 22 December 2011 - 04:23 PM

Here are a couple of things I use all the time and find very useful.

Dot Product
given two vectors a and b the dot product is defined as follows

length(a) * length(b) * cos(angleBetweenAandB)  = ax * bx + ay * by + az * bz = a dot b


The dot product is very useful. You can use it to find the angle between two vectors
angle = acos(a dot b) / (length(a) * length(b))

You can also use this to find what is called vector projection.
Posted Image

In the diagram above. A is projected onto B resulting in the part labeled |A|cos θ . To find the projection vector, I will call it c, we do the following
c = b * (a dot b) / (b dot b)
This has many uses. You can use this to find where a point is closest to a line. It is used frequently in overlap detection algorithms like you want to do between triangles and quads.


Cross Product
given two vectors a and b. The cross of them is the vector perpendicular to both a and b and is defined as
cx = ay * bz - az * by
cy = az * bx - ax * bz
cz = ax * by - ay * bx




Another very important thing you need to understand are transformations. Most commonly in the form of matrix transformations.
The basic idea is this. Say you want to transform a set of points meaning you want to rotate, move, or expand or contract them(scaling). To transform them you pass it through a transformation.

Trivial example.
Vector3 movePoint(Vector3 point, Vector3 offset)
{
	return Vector3(point.x + offset.x, point.y + offset.y, point.z + offset.z)
}


Obviously the above example is a very simple transformation. Most transformations do more than just move objects around. You also want to be able to rotate and scale them. You also want to be able to append multiple transformations meaning you start with point a, pass it through one transform called X resulting in point b then passing that trough another transformation, Y, resulting in point c. It would be much better to join transformations X and Y to only have to transform the point once going from point a directly to point c in one transform. Matrices can do that.

Here are three simple (but not all) transformations that can be done with matrices.
Translation (Move by x, y, z amount)
Rotation
Scaling Makes this bigger or smaller. Can flip objects if you specify a -1 for one of the axis.

To join any two transformations simply multiply them.

C = A * B

Any number of matrices can be multiplied together taking a large number of translations, rotations, and scales and turning them into a single matrix.

M = A * B * C * D

Then to transform a point simply multiply the point by the matrix treating the point as a 1x4 matrix with the last element in the 1x4 matrix being a 1

b = M * (a.x, a.y, a.z, 1)

Multiplying the above matrix M by a is the same as multiplying a by D then by C then by B then by A. As you can see, combining matrices is much more efficient. Remember, the right most transformations will be done first meaning with M, D is first, A is last. DirectX matrices are opposite of that, but I will go into more detail why in a second.

Using matrices as transformations is used at the heart of 3D graphics. 3D graphics data is made up of many 3D points connected in triangles. Both DirectX and OpenGL require a matrix to control where an object is drawn in the 3D scene.

DirectX, as I briefly mentioned, has a minor difference in matrix transformations. The matrices are all transposed, meaning they are flipped on the diagonal going from top left to bottom right. Because they are transposed the point needs to be on the left of the matrix when multiplying.

b = (a.x, a.y, a.z, 1) * M

And the leftmost matrix is the first transformation to be done when stacking multiple matrices.

M = D * C * B * A

I just threw a whole lot at you. Don't be frustrated if you don't grasp it all right away it is a lot to take in. All of this stuff is covered in a college level class on the subject of Linear Algebra. So I suggest you study Linear Algebra whether in school or on your own. If you want me to show how to solve any of the problems you listed above or need any further clarifcation let me know.


#4890575 is it possible to check if 2 vectors are criss crossing?

Posted by HappyCoder on 04 December 2011 - 09:50 PM

To do the transform you need to create the matrix

transform = cameraProjection * cameraTransform

to transform a 3d point multiply a 4d vector by the transform where the 4th component is a 1

transformedVec = transform  * (x, y, z, 1)

then multiply the transformedVec  by the inverse of the 4th component of transformedVec

wInv = 1.0 / transformedVec.w (w is the 4th component of the the 4d vector)

transformedVec  *= wInv

then you take the x,y of the final transformedVec and use that for a 2d line segment collision.

So in code


// classes needed
class Matrix;
class Vector3; // x, y, z
class Vector4; // x, y, z, w
class Ray; // Vector3 origin, Vector3 direction
class Segment; // Vector3 a, Vector3 b

// method for matrix
Vector3 Matrix::tranformPointWithPerspective(const Vector3& in)
{
	Vector4 vec4 = Vector4(in.x, in.y, in.z, 1.0);

	Vector4 transVec = (*this) * vec4; 

	double wInv = 1.0 / transVec.w;

	return Vector3(transVec.x * wInv, transVec.y * wInv, transVec.z * wInv);
}

// then to do a segment collision
// this method could go in camera class
bool doesCollideInView(const Ray& rayA, const Ray& rayB)
{
	Matrix resultTranform = perspectiveMatrix * cameraTransform; // perspectiveMatrix * cameraTransform; // this could be done once and saved somewhere if you need to do many collision checks

	Segment segA(resultTranform.tranformPointWithPerspective(rayA.origin), resultTransform.tranformPointWithPerspective(rayA.origin + rayA.direction));	Segment segB(resultTranform.tranformPointWithPerspective(rayB.origin), resultTransform.tranformPointWithPerspective(rayB.origin + rayB.direction));

	// then you ignore the z component on each segment and do a 2d segment collision to see if they overlap
	// I wont provide the code for that, you should be able to find something like that

}


Hope that is clear



#4888054 Worth a buck

Posted by HappyCoder on 26 November 2011 - 11:50 PM

I think I would likely say a game would be worth a buck, but not want to actually pay a buck for it.


#4886754 The Structure of a Video Game

Posted by HappyCoder on 22 November 2011 - 09:28 PM

I know exactly what you mean. I have felt the exact thing many times. You run into what is sometimes called the God Object meaning you have too much functionality into a single class. You should avoid this.

What should be done about it? Try to move logic out of your main loop, or scene classes and move them into the entities they control.

For example
void update(dt)
{
	for (int i =0; i < entityList.count(); ++i)
	{
		Entity& entity = entityList[i];

		entity.pos += entity.velocity * dt;
		
		if (entity.type == HumanPlayer)
		{
			// logic for human player
		}
		else if (entity.type == LaserTower)
		{
			// logic for laser tower
		}
		else if (entity.type == Tank)
		{
			// logic for tank
		}
	}
}

void mainLoop()
{
	while (running)
	{
		update(timeFromLastFrame);
		draw();
		
		sleep(timeTillNextFrame);
	}
}


The code I have posted above is bad coding practice and should not be done because the logic for each entity is done in the update function. What should be done is the logic should be moved into the entity class. Another thing done poorly in the above code is using a switch statement to determine what action should be done for each entity based on the type. If you ever find yourself checking the type of a class to determine what logic to do on it you should try to find a way to use inheritance and polymorphism instead.

The following is the previous code revised with those improvements

// Entity.h
class Entity
{
protected:
	Vector position;
	Vector velocity;
public:
	virtual void update(double dt);
};

// Entity.cpp
void Entity::update(double dt);

{
	position += velocity * dt;
}


// Human.h
class Human : public Entity
{
public:
	virtual void update(double dt);
};

// Human.cpp
void Human::update(double dt)

{
	Entity::update(dt);
	// logic for human player
}
// LaserTower.h
class LaserTower: public Entity
{
public:
	virtual void update(double dt);
};

// LaserTower.cpp
void LaserTower::update(double dt)

{
	Entity::update(dt);
	// logic for laser tower
}

Then put your main loop into an application class
// Application.h

class Application
{
private:
	Scene scene;
public:
	void mainLoop();
	Application();
};

// Application.cpp

Application::Application()
{
	
}

void Application::mainLoop()
{
	while (running)
	{
		scene.update(timeSinceLastFrame);
		scene.draw();

		// maintain framerate	
	}
}


// Scene.h
class Scene
{
private:
	list<Entity> entityList;
public:
	void update(double dt);
	void draw();
}

// Scene.cpp
void Scene::update(double dt)
{
	for (int i = 0; i < entityList.size(); ++i)
	{
		entityList[i].update();
	}
}

void Scene::draw()
{
	// draw the scene
}

So. Just to discuss what is happening. Game Logic moved from the God Object and to the class it corresponds to.
As seen above I delegated the game loop to an application class. You would only create one of these in you main method and call its mainLoop from there. A scene would be the current part of the game the user is playing. A few examples of scenes would be a map in the game, a house, the main menu. These can be interchanged at any point. You can put any number of entities in the scene.  Each entity represents and object in the scene. The player, enemies, and other objects in the scene.

You may notice that the amount classes has increased. This is a good thing. A good rule of thumb is to have the functionality of a class describable in one sentence. If you find you have a class that does x thing AND y thing you should consider separating it into more than one class. One class that does x thing and another class that does y thing. By organizing things well it will take a bit more work and planning initially but later on it makes it sooooo much easier to add functionality to your game. Adding a new enemy is as easy as adding a new class. When you have a good design many times the expected functionality will emerge without having to specifically putting it in.

Just as a note. The code I provided is not complete and you will need to adapt it to whatever your game requires but it communicates some basic ideas. The code I gave is kinda a pseudo  c++ so you would have to changes some things before actually using it.

My post just got really long. I hope it helped out in some way. If something needs clarification or I didn't answer your question completely let me know.


#4883277 How to separate my game engine and my game?

Posted by HappyCoder on 12 November 2011 - 02:56 PM


If you want a complete separation from your game and engine at the project level, why not put the engine into a static library? You could put both of them into the same solution file. Then when you are working on just the game part, you wouldn't have to rebuild the engine part (which can save some time depending on how large your project is). True, there really is no need to separate the game from the engine, but doing so gives you experience with making things more modular.



Thanks, that sounds like what I was aiming to achieve.  Could you expand on what you mean by "put the engine into a static library"?  I'm not really sure how to do this.


The way you build a static library depends on your compiler. Do a Google search for buildings static libraries in c++ and you should be able to find what you need.


But to add to the original topic. If you want to make your "engine" easily separable from the rest of your code that needs to come down to the way you design your code. Make good use of encapsulation. That means that one class shouldn't have to know about the internal workings of another class to use it. Stay away from global variables.

In the end you will probably have to make adjustments to the engine every time you use it to create another game. You may need to add a feature that the engine doesn't support. That is okay. Make the point of your work to make a game, the reusable code that comes from making a game should just be a result of good program design.


#4881638 Compositing

Posted by HappyCoder on 07 November 2011 - 11:25 PM

You need to first render to an off screen buffer. To do that look up OpenGL FBO (Frame Buffer Object). You will bind a texture to the frame buffer.

Once you render the scene, you change the FBO, you take the resulting texture rendered to previously and apply that on a quad that covers the entire screen to render post rendering effects.

In a nutshell that is what you need to do. I hope this helps point you in the right direction.


#4880285 mouse to ray - sphere collision detection help

Posted by HappyCoder on 03 November 2011 - 03:19 PM

It looks like the algorithms you have assume that the line direction is a normal vector. Are you normalizing the vector before you pass it in?


#4866681 Files can always be recovered no matter what you do...

Posted by HappyCoder on 27 September 2011 - 10:31 PM

I would agree that you can erase a file beyond recovery. I would simply have a program write over the data a few times with actual data of the same file type randomly found on the internet. Then set all of the bits to 0. There would be no way of knowing if the recovered data came from the random data pulled from the internet or the original file. Those are my two bits.


#4849053 If you must choose only one of the two choices, progress and technique, which...

Posted by HappyCoder on 14 August 2011 - 12:22 PM

I think the priority of getting things done over learning new ways to do it depends on the situation. If I am trying to meet a deadline I will focus on progress, or just get something done with the knowledge I already have. I think in most situations I would focus on improving my technique. I always am wanting to learn more and learn to do things better.

So my answer depends on the circumstances.


#4834085 What do you think about the Revelation?

Posted by HappyCoder on 11 July 2011 - 07:31 PM

I'm interested to hear what other people think about this book and its consequences. Personally, although I consider myself to be a Christian, or at least try to, am not interested the least in the Revelation. From where I stand, it's even harmful: It talks about wars, armies, revenge, wrath, enemies and other stuff that seem very distanced from what Jesus tought. And it has been used by the Christian Church in numerous times to justify acts of extreme violence, which are shameful, to say the least, to be associated with Christianity. Overall, although as a young kid I used to read it for its vivid, fantasy imagery, I don't see how this book contributes positively to anything at all.

Your thoughts? (Please no flamewars!)



Revelation speaks of the end of the battle between wickedness and righteousness. Gods mercy will accept any repentant soul who wants to change and live a righteous life, but will not force any man to be righteous. God has given many warnings to all of us of the consequences of sin. We are free to choose to follow God or to follow Satan, but we are not free to choose the consequences that follow our actions.

So why would God allow these consequences to fall upon us if he loves us? He does it because he loves us. (Hebrews 12). I like to imagine it like a child who does not want to do any work in school. If no correction is made the child will grow up and probably not graduate for college or even high school. It wouldn't be likely have a good job and would have a lower quality life because the child never learned to work hard. While the child may find it cruel that they may loose their video games for a time or not be able to play with friends, this is done because the parents love their child and want to correct them.

The destruction in revelation will be a direct consequence of our own wickedness. There will be righteous people, but there will be a lot of wickedness on the earth. Before Christ can come and personally reign on the earth it must be purged of that wickedness. Keep in mind that this life is a brief moment in eternity. All that is lost will be returned to those who are faithful. Those who want to live in a world with no evil must work to cleanse themselves of wickedness, and through Christ we can all be clean of that. To have a world free of evil God must cleanse the earth of those who don't want to be clean through Christ and continue in sin. Like anything spiritual, you should pray for understanding on this. I don't have a perfect knowledge of this but this is how I understand it. I hope I was able to communicative my ideas clearly.


#4827768 Minimum bounding sphere of a Frustum

Posted by HappyCoder on 25 June 2011 - 09:39 PM

I think I have it figured out.

First of all A and B need to be in the camera space, meaning that the line that goes out the center of the camera (the line formed by S + N * t) will fall directly on the z axis. This means that the X and Y of this line will always be 0 or.

Px = 0
Py = 0

This leaves us with only one variable to solve for or Pz.

We know that the distance between P and A is the same as P and B so

Ax^2 + Ay^2 + (Az - Pz)^2 = Bx^2 + By^2 + (Bz - Pz)^2

at this point we just solve for Pz.

Pz = ((Bx^2 + By^2 + Bz^2) - (Ax^2 + Ay^2 + Az^2)) / (2(Bz - Az))

The only thing left to do is the transform P into world space and calculate the radius of the circle by finding the distance between P and A or P and B.

If I didn't explain clearly enough let me know and I can give some detail.


#4818365 Debate me about the bible

Posted by HappyCoder on 01 June 2011 - 11:52 AM

I would first like to say that I don't athests are bad people. I am a member of the Church of Jesus Christ of Latter Day Saints more commonly known as Mormons. I have known many good people from other faiths such as the Jehovah's Witness, Catholic, as well as Athiests. I also know that my ubringing has given me a moral foundation that will help me througout my life.

I enjoy science. I like to study it and learn from it. As I study it I don't see the need to have to pick either God or science. I don't see why I have to choose only one. I make my religion my main foundation and any knowledge that science has to offer. My knowledge of God did not come from reading a science textbook. It came through reading the scriptures and asking if it is true. (Moroni 10:3-5)

The belief of athiesm is nothing new. Not believing in Christ has been part of societies long before his coming. (Alma 30:12-16) To the Greeks the preaching was foolishness. "For the Jews require a sign, and the Greeks seek after wisdom:But we preach Christ crucified, unto the Jews a stumblingblock, and unto the Greeks foolishness;" 1 Cor:22-23. A knowledge of the truth comes to a sincere seeker with a humble heart. You my ridicule me for my beliefs. Science will contitue to progress and there will be those who will try to tell me that our knowledge disproves God. I believe that "even the earth, and all things that are upon the face of it, yea, and its motion, yea, and also all the planets which move in their regular form do witness that there is a Supreme Creator." (Alma 30:44) I look around and see that there is too much order for it to be by chance. The order in the galaxies. The order in the solar system. The order in life. The order in life's basic building blocks such as protiens and DNA. The order in atoms and molecules. This is not proof to me that God lives. What is the foundation of my testimony is a witness through the Holy Ghost. (Moroni 10:3-5)  Anybody who wants to know the truth needs to read the scriptures, ponder of them, then ask with a sincere heart if it is true. If done with faith the Holy Ghost will releal the truth of this directly to our minds. That is why I beleive.




PARTNERS