tge/engine/game/collisionTest.cc
2025-02-17 23:17:30 -06:00

215 lines
6.9 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "dgl/dgl.h"
#include "game/game.h"
#include "math/mMath.h"
#include "console/simBase.h"
#include "console/consoleTypes.h"
#include "console/console.h"
#include "game/collisionTest.h"
static F32 BoxSize = 2;
bool CollisionTest::testPolytope = false;
bool CollisionTest::testClippedPolyList = false;
bool CollisionTest::testDepthSortList = false;
bool CollisionTest::testExtrudedPolyList = false;
bool CollisionTest::depthSort = false;
bool CollisionTest::depthRender = false;
bool CollisionTest::renderAlways = false;
//----------------------------------------------------------------------------
CollisionTest::CollisionTest()
{
}
CollisionTest::~CollisionTest()
{
}
void CollisionTest::consoleInit()
{
Con::addVariable("Collision::boxSize",TypeF32,&BoxSize);
Con::addVariable("Collision::testPolytope",TypeBool,&testPolytope);
Con::addVariable("Collision::testClippedPolyList",TypeBool,&testClippedPolyList);
Con::addVariable("Collision::testExtrudedPolyList",TypeBool,&testExtrudedPolyList);
Con::addVariable("Collision::testDepthSortList",TypeBool,&testDepthSortList);
Con::addVariable("Collision::depthSort",TypeBool,&depthSort);
Con::addVariable("Collision::depthRender",TypeBool,&depthRender);
Con::addVariable("Collision::renderAlways",TypeBool,&renderAlways);
}
void CollisionTest::collide(const MatrixF& transform)
{
//
Point3F pos;
transform.getColumn(3,&pos);
boundingBox.min = pos - Point3F(BoxSize,BoxSize,BoxSize);
boundingBox.max = pos + Point3F(BoxSize,BoxSize,BoxSize);
boundingSphere.center = pos;
boundingSphere.radius = BoxSize * 1.5;
if (testPolytope) {
MatrixF imat(true);
volume.buildBox(imat,boundingBox);
tree.clear();
}
if (testClippedPolyList) {
polyList.clear();
polyList.mPlaneList.clear();
polyList.mNormal.set(0,0,0);
// Planes bounding the square.
polyList.mPlaneList.setSize(6);
polyList.mPlaneList[0].set(boundingBox.min,VectorF(-1,0,0));
polyList.mPlaneList[1].set(boundingBox.max,VectorF(0,1,0));
polyList.mPlaneList[2].set(boundingBox.max,VectorF(1,0,0));
polyList.mPlaneList[3].set(boundingBox.min,VectorF(0,-1,0));
polyList.mPlaneList[4].set(boundingBox.min,VectorF(0,0,-1));
polyList.mPlaneList[5].set(boundingBox.max,VectorF(0,0,1));
}
if (testDepthSortList) {
depthSortList.clear();
mDepthSortExtent.set(5,20,5); // hard-code for now
MatrixF mat = transform;
mat.inverse(); // we want world to camera (or whatever transform represents)
depthSortList.set(mat,mDepthSortExtent);
// we use a different box and sphere...
// our box starts at the camera and goes forward mDepthSortExtent.y
// with width and height of mDepthSortExtent.x and mDepthSortExtent.z
Point3F x,y,z,p;
transform.getColumn(0,&x);
transform.getColumn(1,&y);
transform.getColumn(2,&z);
transform.getColumn(3,&p);
x *= 0.5f * mDepthSortExtent.x;
y *= mDepthSortExtent.y;
z *= 0.5f * mDepthSortExtent.z;
Point3F boxMin = p;
Point3F boxMax = p;
boxMin.setMin(p-x-z);
boxMin.setMin(p-x+z);
boxMin.setMin(p+x-z);
boxMin.setMin(p+x+z);
boxMin.setMin(p-x-z+y);
boxMin.setMin(p-x+z+y);
boxMin.setMin(p+x-z+y);
boxMin.setMin(p+x+z+y);
boxMax.setMax(p-x-z);
boxMax.setMax(p-x+z);
boxMax.setMax(p+x-z);
boxMax.setMax(p+x+z);
boxMax.setMax(p-x-z+y);
boxMax.setMax(p-x+z+y);
boxMax.setMax(p+x-z+y);
boxMax.setMax(p+x+z+y);
Point3F boxCenter = boxMin + boxMax;
boxCenter *= 0.5f;
F32 boxRadius = (boxMax-boxMin).len();
mDepthBox.min = boxMin;
mDepthBox.max = boxMax;
mDepthSphere.center = boxCenter;
mDepthSphere.radius = boxRadius;
}
if (testExtrudedPolyList) {
MatrixF imat(1);
polyhedron.buildBox(imat,boundingBox);
VectorF v1(0,3,0);
transform.mulV(v1,&extrudeVector);
extrudedList.extrude(polyhedron,extrudeVector);
extrudedList.setVelocity(extrudeVector);
extrudedList.setCollisionList(&collisionList);
Point3F p1 = pos + extrudeVector;
boundingBox.min = boundingBox.max = pos;
boundingBox.min.setMin(p1);
boundingBox.max.setMax(p1);
boundingBox.min -= Point3F(BoxSize,BoxSize,BoxSize);
boundingBox.max += Point3F(BoxSize,BoxSize,BoxSize);
boundingSphere.radius += extrudeVector.len();
}
if (testPolytope || testClippedPolyList || testExtrudedPolyList || testDepthSortList) {
testPos = boundingSphere.center;
gClientContainer.findObjects(0xFFFFFFFF,CollisionTest::callback,this);
}
if (testExtrudedPolyList) {
extrudedList.adjustCollisionTime();
}
}
void CollisionTest::callback(SceneObject* obj, void *thisPtr)
{
CollisionTest* ptr = reinterpret_cast<CollisionTest*>(thisPtr);
if (testPolytope) {
if (BSPNode* root = obj->buildCollisionBSP(&ptr->tree,ptr->boundingBox,ptr->boundingSphere))
ptr->volume.intersect(obj,root);
}
if (testClippedPolyList) {
obj->buildPolyList(&ptr->polyList,ptr->boundingBox,ptr->boundingSphere);
}
if (testExtrudedPolyList) {
obj->buildPolyList(&ptr->extrudedList,ptr->boundingBox,ptr->boundingSphere);
}
if (testDepthSortList) {
obj->buildPolyList(&ptr->depthSortList,ptr->mDepthBox,ptr->mDepthSphere);
}
}
extern void wireCube(F32 size,Point3F pos);
void CollisionTest::render()
{
bool collision = false;
if (testPolytope || renderAlways) {
if (volume.didIntersect())
volume.render();
}
if (testClippedPolyList || renderAlways) {
if (polyList.mPolyList.size())
collision = true;
polyList.render();
}
if (testExtrudedPolyList || renderAlways) {
if (collisionList.count)
collision = true;
extrudedList.render();
glPushAttrib(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
polyhedron.render(extrudeVector,collisionList.t);
glPopAttrib();
}
if (testDepthSortList || renderAlways) {
if (depthSort && testDepthSortList)
depthSortList.sort();
// should we write depth values of polys...
// if polys are correctly sorted then writing depth values
// should result in no overlap of polys when looking down
// from camera...otoh, if polys are out of order, we should
// see overlap
DepthSortList::renderWithDepth = depthRender;
depthSortList.render();
}
if (collision || renderAlways)
wireCube(BoxSize,testPos);
}