Jump to content
OGXbox.com

Meerjel01’s XTL Tutorials


Meerjel01
 Share

Recommended Posts

Know triangle collision? No? Here then!

static bool AABBTriangleSAT (D3DXVECTOR3 testAxis, Caabb box, D3DXVECTOR3 v0, D3DXVECTOR3 v1, D3DXVECTOR3 v2) {
	float p0, p1, p2;
	p0 = D3DXVec3Dot(&v0, &testAxis);
	p1 = D3DXVec3Dot(&v1, &testAxis);
	p2 = D3DXVec3Dot(&v2, &testAxis);


	float r = box.extents.x * abs(D3DXVec3Dot(&u0, &testAxis)) +
		box.extents.y * abs(D3DXVec3Dot(&u1, &testAxis)) +
		box.extents.z * abs(D3DXVec3Dot(&u2, &testAxis));

	return max(-largest(p0, p1, p2), smallest(p0, p1, p2)) > r;
}
static bool TriangleIntersectAABB(Caabb box, CTri triangle) {
	D3DXVECTOR3 v0 = triangle.p0;
	D3DXVECTOR3 v1 = triangle.p1;
	D3DXVECTOR3 v2 = triangle.p2;

	v0 -= box.center;
	v1 -= box.center;
	v2 -= box.center;

	D3DXVECTOR3 f0 = v1 - v0;
	D3DXVECTOR3 f1 = v2 - v1;
	D3DXVECTOR3 f2 = v0 - v2;

		

	D3DXVECTOR3 ax_u0_f0, ax_u0_f1, ax_u0_f2;
	D3DXVECTOR3 ax_u1_f0, ax_u1_f1, ax_u1_f2;
	D3DXVECTOR3 ax_u2_f0, ax_u2_f1, ax_u2_f2;

	D3DXVec3Cross(&ax_u0_f0, &u0, &f0);
	D3DXVec3Cross(&ax_u0_f1, &u0, &f1);
	D3DXVec3Cross(&ax_u0_f2, &u0, &f2);
	D3DXVec3Cross(&ax_u1_f0, &u1, &f0);
	D3DXVec3Cross(&ax_u1_f1, &u1, &f1);
	D3DXVec3Cross(&ax_u1_f2, &u1, &f2);
	D3DXVec3Cross(&ax_u2_f0, &u2, &f0);
	D3DXVec3Cross(&ax_u2_f1, &u2, &f1);
	D3DXVec3Cross(&ax_u2_f2, &u2, &f2);

	if(AABBTriangleSAT(ax_u0_f0, box, v0, v1, v2) || AABBTriangleSAT(ax_u0_f1, box, v0, v1, v2) || AABBTriangleSAT(ax_u0_f2, box, v0, v1, v2) ||
			AABBTriangleSAT(ax_u1_f0, box, v0, v1, v2) || AABBTriangleSAT(ax_u1_f1, box, v0, v1, v2) || AABBTriangleSAT(ax_u1_f2, box, v0, v1, v2) ||
			AABBTriangleSAT(ax_u2_f0, box, v0, v1, v2) || AABBTriangleSAT(ax_u2_f1, box, v0, v1, v2) || AABBTriangleSAT(ax_u2_f2, box, v0, v1, v2)) {
			return false;
		}

	D3DXVECTOR3 triNormal = D3DXVECTOR3(0,0,0);
	D3DXVec3Cross(&triNormal, &f0, &f1);

	if(AABBTriangleSAT(u0, box, v0, v1, v2) || AABBTriangleSAT(u1, box, v0, v1, v2) || AABBTriangleSAT(u2, box, v0, v1, v2)) {
		return false;
	}

	if(AABBTriangleSAT(triNormal, box, v0, v1, v2))
		return false;


	return true;
}

Collision response soon..

  • Like 1
Link to comment
Share on other sites

From my character collider code. Take a newDirection vector variable and use this for your triangles. (AABB character vs world triangle collision)

D3DXVECTOR3 TriangleCollision(CTri triangle, D3DXVECTOR3 dir, D3DXVECTOR3 lastPos, D3DXVECTOR3 currentPos) {
	D3DXVECTOR3 vNorm = GetNormal(triangle);
	colliding = false;

	triIsGround = false;
	triIsCeiling = false;
	triIsWall = false;

	if(CPyhsics::TriangleIntersectAABB(boundingBox, triangle)) {
	
		colliding = true;

		triIsGround = CPyhsics::GetGrounded(vNorm, D3DXVECTOR3(0, -1, 0), 0.5);
		triIsCeiling = CPyhsics::GetGrounded(vNorm, D3DXVECTOR3(0, 1, 0), 0.5);
		triIsWall = !triIsGround && !triIsCeiling;
		
		if(triIsGround)
			grounded = true;

		D3DXVECTOR3 tempV = NegateVector(vNorm);

		tempV *= D3DXVec3Length(&MultiplyVector(dir, vNorm));
		D3DXVECTOR3 wallDir = dir - tempV;

		D3DXVECTOR3 closestPtn = CPyhsics::GetClosestPointOnTriangle(currentPos, triangle);

		if(currentPos.y > closestPtn.y)
			return dir;

		D3DXVECTOR3 newPos = lastPos + wallDir;
		
		D3DXVECTOR3 newDir = newPos - lastPos;

		return newDir;
	}
	return dir;
}

Call it without using + or - btw.

  • Like 1
Link to comment
Share on other sites

  • 2 months later...
  • 2 months later...

Bump*

I haven't tested it yet on my engine but I believe it'll be more working using this method than a bunch of for-loops.

#include <iostream>

using namespace std;

class CObject
{
public:
	void ExecuteDeb(int num)
	{
		printf("Printing! %i ", num);
	}
};

class CObjectLinker
{
public:
	CObject* objs;
	int numObjs;
	
	CObjectLinker(int num)
	{
		numObjs = num;
		objs = new CObject[numObjs];
	}
	
	void StartExecute()
	{
		int number = numObjs;
		
		keepExecuting(number);
	}
	
	void keepExecuting(int& curNum)
	{
		objs[curNum].ExecuteDeb(curNum);
		curNum--;
		
		if(curNum < 0)
			return;
		keepExecuting(curNum);
	}
};

int main(int argc, char *argv[]) {
	CObjectLinker linker(4);
	
	linker.StartExecute();
}

This was a test to see if I can execute multiple objects with a countdown method instead of the usual. If And For/While takes some speed away when used a lot so I was experimenting and came up with this. Any thoughts?

  • Like 1
Link to comment
Share on other sites

On 5/2/2024 at 4:54 PM, Meerjel01 said:

Bump*

I haven't tested it yet on my engine but I believe it'll be more working using this method than a bunch of for-loops.

#include <iostream>

using namespace std;

class CObject
{
public:
	void ExecuteDeb(int num)
	{
		printf("Printing! %i ", num);
	}
};

class CObjectLinker
{
public:
	CObject* objs;
	int numObjs;
	
	CObjectLinker(int num)
	{
		numObjs = num;
		objs = new CObject[numObjs];
	}
	
	void StartExecute()
	{
		int number = numObjs;
		
		keepExecuting(number);
	}
	
	void keepExecuting(int& curNum)
	{
		objs[curNum].ExecuteDeb(curNum);
		curNum--;
		
		if(curNum < 0)
			return;
		keepExecuting(curNum);
	}
};

int main(int argc, char *argv[]) {
	CObjectLinker linker(4);
	
	linker.StartExecute();
}

This was a test to see if I can execute multiple objects with a countdown method instead of the usual. If And For/While takes some speed away when used a lot so I was experimenting and came up with this. Any thoughts?

This code ain't good apparently. It looks decent but apparently it's no good for the engine to have this in it. Guess for loops aren't too bad after all?

  • Like 1
Link to comment
Share on other sites

  • 1 month later...
  • 1 month later...

Point arrays (What I use) isn't as versatile as std vectors in that you can't dynamically add a slot to an array. But there's one thing that I use that everyone else might find use of too. A large point array and an integer to store the current amount of elements in said array.

Consider this.

char* arrayOfChars = new char[200];
int curNumChars = 0;

void AddCharToArray(char ch)
{
  arrayOfChars[curNumChars] = ch;
  curNumChars++;
}

And when to clear it.

void ClearArray()
{
  curNumChars = 0;
}

This can be useful for when going in and out of area volumes or AABBs. Call these every frame and check if inside the volume/AABB, add it to the point array and when finished with it clear the array. It's to decrease the amount of checks in for-loops to only check specific elements. Have a group of area triggers be part of a big area volume/AABB that the player must go inside to touch the group triggers. This is for performance. ClearArray() can have more count integers for multiple arrays as well.

Hope I gave some valuable insight today. Donate please

Link to comment
Share on other sites

  • 5 months later...

Another tutorial for devs.

cObject* objy;

pointers can help giving you an easy accessed variable which can have it's members changeable anywhere in your engine. Like a public variable in the Unity Engine.

Consider the following code.

cObject* objy;

objy = NULL;

objy->myVar = 20;

objy->AttackMe();

Whilst "->" is a replacement for "." to access the object itself and makes inherited members usable as well, but the variable must be initialized first with NULL or with

new cObject();

To make a pointer array is quite easy too.

cObject** objList = new cObject*[300];

objList[0]->AttackMe();

This is how it works. Using a variable without "*" will only make a copy each time you assign it which will not change the original. But to make it work correctly, use pointers on objects that are important and non pointers in mostly local parts of your code.

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...

A note about pointers. Don't make too many of them or your game will not work correctly.

 

An alternative is to use the "&" operator in parameters to direct an average class variable's access to somewhere else in the code. Pointers are useful but has limits. Especially in big pointer arrays.

image.png.b90f45d350fd96178f09ed7dd3e77e1f.png

Had debug mode working on my box now :)

  • Like 3
Link to comment
Share on other sites

  • 2 months later...

Info about ground collision. When colliding with a ground triangle, DON't USE THE WALL TECHNIQUE. The process as follows works best.

Get if the character is colliding with a triangle.

Get it's normal and determine if it's pointing up (Or is an up facing slope).

Get the closest position from the character's position (Otherwise it's feet pos) on the triangle.

If it's not to high up (Say not higher than your stepOffset used for stairs) then apply the character's position to the closest point on the triangle.

The method I used before was the common approach to push the character away from a wall and slide on it. It caused the character to go up and down every frame which I detected in my lower fps videos of my game. Using the wall slide algorithm on the ground would make the character aired and grounded every time which is not a good thing to do. So just use your closest point to triangle code and this

static bool GetSlopedNormal(D3DXVECTOR3 vNormal, D3DXVECTOR3 vDirection, float slope) {
	float result = D3DXVec3Dot(&vNormal, &vDirection);
		
	return result >= -1 && result <= -slope;
}

To do the grounding job done.

  • Like 1
Link to comment
Share on other sites

  • 3 months later...

Gonna add a capsule collider tutorial sometime. But now for something different.

When doing changing arrays in code I use average [] arrays with a nearby int variable to keep count on how many used elements are in the array. If the array has to change, take the index you want to remove from it, make a temporary int to store the used elements, loop through the array with the counting int, select all but the removed element, increase the temporary int each time and set the original counting int to the temp integer.

Consider the following.

void RemoveIndexFromArray(int index)
{
 int tmp = 0; 
  for(int i=0; i < numAllElements; i++)
  {
   if(i != index)
   {
	validElements[tmp] = allElements[i];
				
    tmp++;
   }
				
 }
 numValidElements = tmp;

}

Don't call this all the time as it would be performance costly if the array is large. Just call it when it needs to be changed.

(Also you might not need to use the temp int as you could just -- the original counting array)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

Board Life Status


Board startup date: April 23, 2017 12:45:48
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.