void RenderCube() { AABB3 box; box.min.x = box.min.y = box.min.z = -5.0f; box.max = -box.min; RenderVertex vl[8]; for (int i = 0 ; i < 8 ; ++i) { vl[i].p = box.corner(i); //vl[i].argb = MAKE_ARGB(255, (i & 1) ? 255 : 0, (i & 2) ? 255 : 0, (i & 4) ? 255 : 0); vl[i].n = vl[i].p; vl[i].n.normalize(); vl[i].u = (i & 1) ? 1.0f : 0.0f; vl[i].v = (i & 2) ? 1.0f : 0.0f; } RenderTri pl[6*2] = { { 0,4,6 }, { 0,6,2 }, { 1,3,7 }, { 1,7,5 }, { 0,1,5 }, { 0,5,4 }, { 2,6,7 }, { 2,7,3 }, { 0,2,3 }, { 0,3,1 }, { 4,5,7 }, { 4,7,6 }, }; gRenderer.renderTriMesh(vl, 8, pl, 12); }
/** * updates position, velocity, and animation time of particles * - rParticleSet.aabb is also updated * */ inline void CBE_ParticleSet::UpdateParticles( ParticleSetExtraData& rParticleSet, float dt, AABB3& aabb ) { // Vector3 vGravityAccel = m_pStage->GetGravityAccel(); // float fGravityInfluenceFactor = m_fGravityInfluenceFactor; Vector3 vGravityAccel = m_pStage->GetGravityAccel() * m_fGravityInfluenceFactor; // AABB3 aabb; aabb.Nullify(); int i, num_particles = rParticleSet.iNumParticles; for(i=0; i<num_particles; i++) { // update velocity // rParticleSet.pavVelocity[i] += (vGravityAccel * fGravityInfluenceFactor) * dt; rParticleSet.pavVelocity[i] += vGravityAccel * dt; // update position rParticleSet.pavPosition[i] += rParticleSet.pavVelocity[i] * dt; // update animation time rParticleSet.pafAnimationTime[i] += dt; aabb.AddPoint( rParticleSet.pavPosition[i] ); } const float r = m_fParticleRadius; aabb.vMin -= Vector3(r,r,r); aabb.vMax += Vector3(r,r,r); rParticleSet.aabb = aabb; }
TerrainChunk::TerrainChunk( int xChunkIndex, int yChunkIndex, int zChunkIndex, Terrain *terrain ): Entity("TerrainChunk"), _xChunkIndex(xChunkIndex), _yChunkIndex(yChunkIndex), _zChunkIndex(zChunkIndex), _terrain(terrain) { std::ostringstream stringStream; stringStream << "TerrainChunk [" << _xChunkIndex << ", " << _yChunkIndex << ", " << _zChunkIndex << "]"; _name = stringStream.str(); _paletteRenderables.reserve(DefaultCapacity); _grid = new MatrixVoxelGrid(ChunkSize, ChunkSize, ChunkSize); // Setup for a correct model matrix. setPosition( _xChunkIndex * ChunkSize, _yChunkIndex * ChunkSize, _zChunkIndex * ChunkSize); // Setup for correct frustum culling. AABB3 localAABB; localAABB.setMinMax(Vector3(0, 0, 0), Vector3(ChunkSize, ChunkSize, ChunkSize)); expandLocalAABB(localAABB); }
Matrix44 MatrixUtils::orthographic_off_center( AABB3& bounds ) { return orthographic_off_center( bounds.vmin().x, bounds.vmax().x, bounds.vmin().y, bounds.vmax().y, bounds.vmin().z, bounds.vmax().z); }
/// \param m Specifies the transformation matrix to be applied. /// \return The bounding box for the mesh under m. AABB3 TriMesh::getBoundingBox(const Matrix4x3 &m) const { AABB3 bb; bb.empty(); for (int i = 0; i < vertexCount; ++i) bb.add(vertexList[i].p * m); return bb; }
/// \param m Specifies the transformation matrix applied to the model. /// \return The bounding box of the model in transformed space. AABB3 Model::getBoundingBox(const Matrix4x3 &m) const { AABB3 bb; bb.empty(); for(int i = 0; i < m_partCount; ++i) bb.add(m_partMeshList[i].getBoundingBox(m)); return bb; }
/// \param submodel Specifies the submodel whose bounding box is to be fetched. /// \param m Specifies the transformation matrix representing the submodel in world space. AABB3 ArticulatedModel::getSubmodelBoundingBox(int submodel, const Matrix4x3 &m) const { assert(submodel < m_nSubmodelCount); AABB3 bb; bb.empty(); for(int i = 0; i < m_nNextSubmodelPart[submodel]; ++i) bb.add(m_partMeshList[m_nSubmodelPart[submodel][i]].getBoundingBox(m)); return bb; }
inline void IndexedPolygon::UpdateAABB() { m_AABB.Nullify(); const size_t num_vertices = m_index.size(); for( size_t i=0; i<num_vertices; i++ ) { m_AABB.AddPoint( GetVertex(i).m_vPosition ); } }
/** Adopted from Real Time Collision Detection 5.2.3 */ bool gh::Plane3::IntersectsWithAABB3( const AABB3& box ) const { Vector3 center = box.calcCenter(); Vector3 extents = box.getMax() - center; float r = extents.x * fabs( normal.x ) + extents.y * fabs( normal.y ) + extents.z * fabs( normal.z ); float s = normal.dotProduct( center ) - distanceFromOrigin; return fabs( s ) <= r; }
void PrimitiveBatch::draw_aabb( const AABB3& box, const ColourRGBA8& colour/*=ColourARGB8::White()*/ ) { Vector3 v[8]; v[0] = box.center() + box.dimensions() * Vector3(-0.5f,-0.5f,-0.5f); v[1] = box.center() + box.dimensions() * Vector3(+0.5f,-0.5f,-0.5f); v[2] = box.center() + box.dimensions() * Vector3(-0.5f,+0.5f,-0.5f); v[3] = box.center() + box.dimensions() * Vector3(+0.5f,+0.5f,-0.5f); v[4] = box.center() + box.dimensions() * Vector3(-0.5f,-0.5f,+0.5f); v[5] = box.center() + box.dimensions() * Vector3(+0.5f,-0.5f,+0.5f); v[6] = box.center() + box.dimensions() * Vector3(-0.5f,+0.5f,+0.5f); v[7] = box.center() + box.dimensions() * Vector3(+0.5f,+0.5f,+0.5f); draw_line(Line3(v[0],v[1]), colour); draw_line(Line3(v[2],v[3]), colour); draw_line(Line3(v[4],v[5]), colour); draw_line(Line3(v[6],v[7]), colour); draw_line(Line3(v[0],v[4]), colour); draw_line(Line3(v[1],v[5]), colour); draw_line(Line3(v[2],v[6]), colour); draw_line(Line3(v[3],v[7]), colour); draw_line(Line3(v[0],v[2]), colour); draw_line(Line3(v[1],v[3]), colour); draw_line(Line3(v[4],v[6]), colour); draw_line(Line3(v[5],v[7]), colour); }
// clip trace at the point of contact void CTriangleMesh::ClipLineSegment( CJL_LineSegment& segment ) { Vector3 vStart = segment.vStart; Vector3 vEnd; if( segment.fFraction == 1.0f ) vEnd = segment.vGoal; else vEnd = segment.vEnd; // the line segment has been already clipped - set the current end point static vector<int> s_veciTriList; s_veciTriList.resize( 0 ); AABB3 aabb; aabb.Nullify(); aabb.AddPoint( vStart ); aabb.AddPoint( vEnd ); GetIntersectingTriangles( s_veciTriList, aabb ); size_t i, iNumTris = s_veciTriList.size(); if( iNumTris == 0 ) return; // no intersection Vector3 vOrigLineSegment = vEnd - vStart; for( i=0; i<iNumTris; i++ ) { IndexedTriangle& tri = GetTriangle( s_veciTriList[i] ); Triangle triangle( GetVertex( tri.GetIndex(0) ), GetVertex( tri.GetIndex(1) ), GetVertex( tri.GetIndex(2) ), tri.m_vNormal ); // check intersection between ray and triangle if( triangle.RayIntersect( vStart, vEnd ) ) { // found intersection // 'vEnd' now represents the intersection point // save contact surface segment.plane = triangle.GetPlane(); // record surface material to 'tr' segment.iMaterialIndex = tri.m_iMaterialID; } } segment.fFraction *= Vec3Dot( vEnd - vStart, vOrigLineSegment ) / Vec3LengthSq( vOrigLineSegment ); segment.vEnd = vEnd; }
void CBSPMapData::SetLightsFromLightSourceFaces() { vector<CMapFace> vecTempLightSourceFace; // temporary buffer to hold light source faces size_t i,j; size_t iNumInteriorFaces = m_aInteriorFace.size(); for(i=0; i<iNumInteriorFaces; i++) { // set all the flags of light source faces to false m_aInteriorFace[i].m_bFlag = false; } // cluster light source faces for(i=0; i<iNumInteriorFaces; i++) { vecTempLightSourceFace.clear(); CMapFace& rFace1 = m_aInteriorFace[i]; if( !rFace1.ReadTypeFlag(CMapFace::TYPE_LIGHTSOURCE) ) continue; // doesn't emit light by itself if( rFace1.m_bFlag == true ) continue; // already registered as a light source face rFace1.m_bFlag = true; vecTempLightSourceFace.push_back( rFace1 ); // adjacent light source faces are converted into one point light SearchAdjacentLightSourceFaces_r( &vecTempLightSourceFace, rFace1, &m_aInteriorFace ); // convert each cluster of light source faces into a point light AABB3 aabb; aabb.Nullify(); for(j=0; j<vecTempLightSourceFace.size(); j++) vecTempLightSourceFace[j].AddToAABB( aabb ); SPointLightDesc light = FindPointLightDesc( rFace1.m_acSurfaceName ); CPointLight* pPointLight = new CPointLight; pPointLight->vPosition = aabb.GetCenterPosition(); pPointLight->Color.fRed = light.fRed; pPointLight->Color.fGreen = light.fGreen; pPointLight->Color.fBlue = light.fBlue; pPointLight->fIntensity = light.fIntensity; pPointLight->fAttenuation0 = light.fAttenuation[0]; pPointLight->fAttenuation1 = light.fAttenuation[1]; pPointLight->fAttenuation2 = light.fAttenuation[2]; m_vecpLight.push_back( pPointLight ); } }
void UniformGrid<T,CellType>::InitGrid(const AABB3<T> &boundingBox, const AABB3<T> &element) { m_dCellSize = 2.0 * element.getBoundingSphereRadius(); m_bxBox = boundingBox; int x = (2.0*m_bxBox.extents_[0]+m_dCellSize)/m_dCellSize; int y = (2.0*m_bxBox.extents_[1]+m_dCellSize)/m_dCellSize; int z = (2.0*m_bxBox.extents_[2]+m_dCellSize)/m_dCellSize; // int nGhostLayerCells = (2 * xy + 2 * xz + 2 * yz) + (4 * x + 4 * y + 4 * z) + 8; // pass a bounding box that is m_dCellSize bigger in each dimension m_pCells = new CellType[x*y*z]; // printf("cell size: %f\n",m_dCellSize); // printf("domain extends : %f %f %f\n",boundingBox.extents_[0],boundingBox.extents_[1],boundingBox.extents_[2]); // printf("element extends : %f %f %f\n",element.extents_[0],element.extents_[1],element.extents_[2]); // printf("Dimensions : %d %d %d\n",x,y,z); // printf("Number of cells in uniform grid : %d\n",x*y*z); m_iDimension[0] = x; m_iDimension[1] = y; m_iDimension[2] = z; m_iTotalEntries=0; }
bool Ned3DObjectManager::enforcePositions(GameObject &obj1, GameObject &obj2) { const AABB3 &box1 = obj1.getBoundingBox(), &box2 = obj2.getBoundingBox(); AABB3 intersectBox; if(AABB3::intersect(box1, box2, &intersectBox)) { // Collision: Knock back both objects // - Kludge method: Push back on smallest dimension Vector3 delta = intersectBox.size(); Vector3 obj1Pos = obj1.getPosition(), obj2Pos = obj2.getPosition(); if(delta.x <= delta.y) if(delta.x <= delta.z) { // Push back on x float dx = (box1.min.x < box2.min.x) ? -delta.x : delta.x; obj1Pos.x += dx; obj2Pos.x -= dx; } else { // Push back on z float dz = (box1.min.z < box2.min.z) ? -delta.z : delta.z; obj1Pos.z += dz; obj2Pos.z -= dz; } else if(delta.y <= delta.z) { // Push back on y float dy = (box1.min.y < box2.min.y) ? -delta.y : delta.y; obj1Pos.y += dy; obj2Pos.y -= dy; } else { // Push back on z float dz = (box1.min.z < box2.min.z) ? -delta.z : delta.z; obj1Pos.z += dz; obj2Pos.z -= dz; } obj1.setPosition(obj1Pos); obj2.setPosition(obj2Pos); return true; } return false; }
void CBE_NozzleExhaust::UpdateNozzleExhaust( CCopyEntity* pCopyEnt, SBE_ParticleSetExtraData& rParticleSet, float dt ) { int i, num_particles = m_MaxNumParticlesPerSet; // float dt = fFrameTime; AABB3 aabb; aabb.Nullify(); // UpdateParticles( rParticleSet, fFrameTime, aabb ); float radius = m_fParticleRadius; for(i=0; i<num_particles; i++) { // update animation time rParticleSet.pafAnimationTime[i] += dt; if( rParticleSet.pafAnimationTime[i] < 0 ) continue; // update velocity // rParticleSet.pavVelocity[i] += vGravityAccel * dt; // update position rParticleSet.pavPosition[i] += rParticleSet.pavVelocity[i] * dt; aabb.AddSphere( Sphere(rParticleSet.pavPosition[i],radius) ); } pCopyEnt->world_aabb.MergeAABB( aabb ); Vector3 vBasePos = Vector3(0,0,0);//pCopyEnt->Position();// + pCopyEnt->GetDirection() * pCopyEnt->f1; Vector3 vDir = Vector3(0,0,1);//pCopyEnt->GetDirection(); Vector3 vRight = Vector3(1,0,0);//pCopyEnt->GetRightDirection(); Vector3 vUp = Vector3(0,1,0);//pCopyEnt->GetUpDirection(); float cycle_time = m_fDuration; for( i=0; i<num_particles; i++ ) { if( cycle_time <= rParticleSet.pafAnimationTime[i] ) { // set new position & velocity CreateNewParticle( pCopyEnt, rParticleSet, i ); // rParticleSet.pafAnimationTime[i] = 0; } } }
void AABB3::TransformBy(Matrix& matrix) { AABB3 bb; Vector3f v(minVec); Vector3f w(maxVec); bb.Encapsulate(matrix.Transform(Vector3f(v.x(),v.y(),v.z()))); bb.Encapsulate(matrix.Transform(Vector3f(w.x(),v.y(),v.z()))); bb.Encapsulate(matrix.Transform(Vector3f(v.x(),w.y(),v.z()))); bb.Encapsulate(matrix.Transform(Vector3f(w.x(),w.y(),v.z()))); bb.Encapsulate(matrix.Transform(Vector3f(v.x(),v.y(),w.z()))); bb.Encapsulate(matrix.Transform(Vector3f(w.x(),v.y(),w.z()))); bb.Encapsulate(matrix.Transform(Vector3f(v.x(),w.y(),w.z()))); bb.Encapsulate(matrix.Transform(Vector3f(w.x(),w.y(),w.z()))); minVec.Set(bb.minVec); maxVec.Set(bb.maxVec); }
inline bool Camera::ViewFrustumIntersectsWith( const AABB3& raabb ) const { int i; float d; Vector3 vCenter, vExtents; vCenter = raabb.GetCenterPosition(); vExtents = raabb.GetExtents(); for( i=0; i<6; i++ ) { const SPlane& rPlane = m_WorldBSPTree[i].plane; d = Vec3Dot( rPlane.normal, vCenter ) - rPlane.dist - raabb.GetRadiusForPlane(rPlane); if(0 < d) return false; } return true; }
inline AABB3 GetAABB( const std::vector<IndexedPolygon>& polygon_buffer ) { AABB3 aabb; aabb.Nullify(); size_t i, num_pols = polygon_buffer.size(); size_t j, num_verts; for( i=0; i<num_pols; i++ ) { // polygon_buffer[i].Update(); // aabb.MergeAABB( polygon_buffer[i].GetAABB() ); num_verts = polygon_buffer[i].m_index.size(); for( j=0; j<num_verts; j++ ) { aabb.AddPoint( polygon_buffer[i].GetVertex((int)j).m_vPosition ); } } return aabb; }
ParticleSetExtraData() : iNumParticles(0), pavPosition(nullptr), pavVelocity(nullptr), pavOrigDirection(nullptr), pafAnimationTime(nullptr), pafAnimDuration(nullptr), pasPattern(nullptr), pafFadeVel(nullptr) { aabb.Nullify(); }
/** * updates position, velocity, and animation time of particles * - rParticleSet.aabb is also updated * */ inline void CBE_ParticleSet::UpdateParticlePositions( ParticleSetExtraData& rParticleSet, float dt, AABB3& aabb ) { // AABB3 aabb; aabb.Nullify(); int i, num_particles = rParticleSet.iNumParticles; for(i=0; i<num_particles; i++) { // update position rParticleSet.pavPosition[i] += rParticleSet.pavVelocity[i] * dt; // update animation time rParticleSet.pafAnimationTime[i] += dt; aabb.AddPoint( rParticleSet.pavPosition[i] ); } const float r = m_fParticleRadius; aabb.vMin -= Vector3(r,r,r); aabb.vMax += Vector3(r,r,r); rParticleSet.aabb = aabb; }
bool FrustumCuller::isCullable(const Chunk& chunk, const RenderData& data) { // Calculate the MVP matrix dmat4 modelTransform = chunk.owner()->modelTransform(); dmat4 viewTransform = dmat4(data.camera.combinedViewMatrix()); dmat4 modelViewProjectionTransform = dmat4(data.camera.projectionMatrix()) * viewTransform * modelTransform; const std::vector<glm::dvec4>& corners = chunk.getBoundingPolyhedronCorners(); // Create a bounding box that fits the patch corners AABB3 bounds; // in screen space std::vector<vec4> clippingSpaceCorners(8); for (size_t i = 0; i < 8; i++) { dvec4 cornerClippingSpace = modelViewProjectionTransform * corners[i]; clippingSpaceCorners[i] = cornerClippingSpace; dvec3 cornerScreenSpace = (1.0f / glm::abs(cornerClippingSpace.w)) * cornerClippingSpace; bounds.expand(cornerScreenSpace); } return !_viewFrustum.intersects(bounds); }
AABB3 SoccerBase::GetAgentBoundingBox(const Leaf& base) { AABB3 boundingBox; boost::shared_ptr<Space> parent = base.FindParentSupportingClass<Space>().lock(); if (!parent) { base.GetLog()->Error() << "(GetAgentBoundingBox) ERROR: can't get parent node.\n"; return boundingBox; } /* We can't simply use the GetWorldBoundingBox of the space node, becuase * (at least currently) it'll return a wrong answer. Currently, the space * object is always at (0,0,0) which is encapsulated in the result of it's * GetWorldBoundingBox method call. */ Leaf::TLeafList baseNodes; parent->ListChildrenSupportingClass<BaseNode>(baseNodes); if (baseNodes.empty()) { base.GetLog()->Error() << "(GetAgentBoundingBox) ERROR: space object doesn't have any" << " children of type BaseNode.\n"; } for (Leaf::TLeafList::iterator i = baseNodes.begin(); i!= baseNodes.end(); ++i) { boost::shared_ptr<BaseNode> node = shared_static_cast<BaseNode>(*i); boundingBox.Encapsulate(node->GetWorldBoundingBox()); } return boundingBox; }
bool Ned3DObjectManager::enforcePosition(GameObject &moving, GameObject &stationary) { const AABB3 &box1 = moving.getBoundingBox(), &box2 = stationary.getBoundingBox(); AABB3 intersectBox; if(AABB3::intersect(box1, box2, &intersectBox)) { // Collision: Knock back obj1 // - Kludge method: Push back on smallest dimension Vector3 delta = intersectBox.size(); Vector3 obj1Pos = moving.getPosition(), obj2Pos = stationary.getPosition(); if(delta.x <= delta.y) if(delta.x <= delta.z) { // Push back on x obj1Pos.x += (box1.min.x < box2.min.x) ? -delta.x : delta.x; } else { // Push back on z obj1Pos.z += (box1.min.z < box2.min.z) ? -delta.z : delta.z; } else if(delta.y <= delta.z) { // Push back on y obj1Pos.y += (box1.min.y < box2.min.y) ? -delta.y : delta.y; } else { // Push back on z obj1Pos.z += (box1.min.z < box2.min.z) ? -delta.z : delta.z; } moving.setPosition(obj1Pos); return true; } return false; }
void Init( int flag, int num_particles ) { Release(); iNumParticles = 0; aabb.Nullify(); if( flag & ParticleSetFlag::POSITION ) pavPosition = new Vector3 [num_particles]; if( flag & ParticleSetFlag::VELOCITY ) pavVelocity = new Vector3 [num_particles]; if( flag & ParticleSetFlag::ORIG_DIR ) pavOrigDirection = new Vector3 [num_particles]; if( flag & ParticleSetFlag::ANIM_TIME ) pafAnimationTime = new float [num_particles]; if( flag & ParticleSetFlag::ANIM_DURATION ) pafAnimDuration = new float [num_particles]; if( flag & ParticleSetFlag::PATTERN ) pasPattern = new short [num_particles]; if( flag & ParticleSetFlag::FADE_VEL ) pafFadeVel = new float [num_particles]; // if( flag & ParticleSetFlag::LOCAL_POSITION )pavLocalPosition = new Vector3 [num_particles]; }
UniformGrid<T,CellType>::UniformGrid(const AABB3<T> &boundingBox, const AABB3<T> &element) { m_dCellSize = 2.0 * element.getBoundingSphereRadius(); int x = (m_bxBox.extents_[0]+m_dCellSize)/m_dCellSize; int y = (m_bxBox.extents_[1]+m_dCellSize)/m_dCellSize; int z = (m_bxBox.extents_[2]+m_dCellSize)/m_dCellSize; int xy = x*y; int xz = x*z; int yz = y*z; // pass a bounding box that is m_dCellSize bigger in each dimension m_pCells = new CellType[x*y*z]; m_iTotalEntries=0; }
bool Ned3DObjectManager::enforcePositions(GameObject &obj1, GameObject &obj2) { // TODO: replace with http://code.google.com/p/bullet/source/browse/trunk/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp HullAgainstHull for OOBBs /* // Bullet stuff: btVector3 v(0.0f,0.0f,0.0f); const btConvexPolyhedron* cP = NULL; const btConvexPolyhedron* cP2 = NULL; if ( obj1.colOb->getCollisionShape()->isPolyhedral() ) { btPolyhedralConvexShape* pCS = ((btPolyhedralConvexShape*) obj1.colOb->getCollisionShape()); //pCS->initializePolyhedralFeatures(); cP = pCS->getConvexPolyhedron(); } if (obj2.colOb->getCollisionShape()->isPolyhedral() ) { btPolyhedralConvexShape* pCS = ((btPolyhedralConvexShape*) obj2.colOb->getCollisionShape()); //pCS->initializePolyhedralFeatures(); cP2 = pCS->getConvexPolyhedron(); } bool collision = false; if (cP && cP2) { collision = btPolyhedralContactClipping::findSeparatingAxis(*cP,*cP2, obj1.colOb->getWorldTransform(),obj2.colOb->getWorldTransform(), v,renderCallback); } btVector3 v1 = obj1.colOb->getWorldTransform().getOrigin(); btVector3 v2 = obj2.colOb->getWorldTransform().getOrigin(); bool invert = false; if (obj1.getType() == ObjectTypes::BOX || obj2.getType() == ObjectTypes::BOX) { invert = true; } if (collision) { if (!invert) { //normal collision stuff } else { } } return collision;*/ bool invert = false; if (obj1.getType() == ObjectTypes::BOX || obj2.getType() == ObjectTypes::BOX) { invert = true; } const AABB3 &box1 = obj1.getBoundingBox(), &box2 = obj2.getBoundingBox(); AABB3 intersectBox; if(! invert && AABB3::intersect(box1, box2, &intersectBox)) { // Collision: Knock back both objects // - Kludge method: Push back on smallest dimension Vector3 delta = intersectBox.size(); Vector3 obj1Pos = obj1.getPosition(), obj2Pos = obj2.getPosition(); if(delta.x <= delta.y) if(delta.x <= delta.z) { // Push back on x float dx = (box1.min.x < box2.min.x) ? -delta.x : delta.x; obj1Pos.x += dx; obj2Pos.x -= dx; } else { // Push back on z float dz = (box1.min.z < box2.min.z) ? -delta.z : delta.z; obj1Pos.z += dz; obj2Pos.z -= dz; } else if(delta.y <= delta.z) { // Push back on y float dy = (box1.min.y < box2.min.y) ? -delta.y : delta.y; obj1Pos.y += dy; obj2Pos.y -= dy; } else { // Push back on z float dz = (box1.min.z < box2.min.z) ? -delta.z : delta.z; obj1Pos.z += dz; obj2Pos.z -= dz; } obj1.setPPosition(obj1Pos); obj2.setPPosition(obj2Pos); return true; } else if (AABB3::intersect(box1, box2, &intersectBox) ) { // inverted bounding box collision) char* tp = (char*)malloc(sizeof(char*)*500); // allocate char sprintf_s(tp,500,"hello world %f\n\0",box1.min.x); Vector3 delta = intersectBox.size(); Vector3 obj1Pos = obj1.getPosition(), obj2Pos = obj2.getPosition(); float dx,dy,dz=0.0f; dx=dy=dz=0.0f; // check if plane should leave the box GameObject* p = &obj2; BoxObject* b = (BoxObject*)p; p = &obj1; PlaneObject* plane = (PlaneObject*)p; bool posChanged = false; // since one is much bigger than the other, we can use maxes to determine relative position: if (box1.min.x < box2.min.x + 1.0f) { // move obj2 to the left and move obj1 to the right dx = box2.min.x - box1.min.x; //obj1Pos.x += dx; posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_LEFT; //OutputDebugString(tp); if (b->l == BoxObject::LEFT) { setNextBox(b,b->left); return true; } } if (box1.min.x < box2.min.x) { // move obj2 to the left and move obj1 to the right dx = box2.min.x - box1.min.x; obj1Pos.x += dx; posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_LEFT; //OutputDebugString(tp); if (b->l == BoxObject::LEFT) { setNextBox(b,b->left); return true; } } if (box1.max.x + 1.0f > box2.max.x) { dx = box2.max.x - box1.max.x; //obj1Pos.x += dx; //OutputDebugString(tp); posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_RIGHT; if (b->l == BoxObject::RIGHT) { setNextBox(b,b->right); return true; } } if (box1.max.x > box2.max.x) { dx = box2.max.x - box1.max.x; obj1Pos.x += dx; //OutputDebugString(tp); posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_RIGHT; if (b->l == BoxObject::RIGHT) { setNextBox(b,b->right); return true; } } if (box1.min.y < box2.min.y + 1.0f) { // move obj2 to the left and move obj1 to the right dy = box2.min.y - box1.min.y; //obj1Pos.y += dy; //OutputDebugString(tp); posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_DOWN; if (b->l == BoxObject::BOTTOM) { setNextBox(b,b->bottom); return true; } } if (box1.min.y < box2.min.y) { // TODO: Make plane not able to go slightly over // move obj2 to the left and move obj1 to the right dy = box2.min.y - box1.min.y; obj1Pos.y += dy; //OutputDebugString(tp); posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_DOWN; if (b->l == BoxObject::BOTTOM) { setNextBox(b,b->bottom); return true; } } if (box1.max.y + 1.0f > box2.max.y) { dy = box2.max.y - box1.max.y; //obj1Pos.y += dy; //OutputDebugString(tp); posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_UP; if (b->l == BoxObject::TOP) { setNextBox(b,b->top); return true; } } if (box1.max.y > box2.max.y) { dy = box2.max.y - box1.max.y; obj1Pos.y += dy; //OutputDebugString(tp); posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_UP; if (b->l == BoxObject::TOP) { setNextBox(b,b->top); return true; } } if (box1.min.z < box2.min.z + 1.0f) { // move obj2 to the left and move obj1 to the right dz = box2.min.z - box1.min.z; //obj1Pos.z += dz; posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_NEAR; if (b->l == BoxObject::FRONT) { setNextBox(b,b->back); return true; } } if (box1.min.z < box2.min.z) { // move obj2 to the left and move obj1 to the right dz = box2.min.z - box1.min.z; obj1Pos.z += dz; posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_NEAR; if (b->l == BoxObject::FRONT) { setNextBox(b,b->back); return true; } } if (box1.max.z + 1.0f > box2.max.z) { dz = box2.max.z - box1.max.z; //obj1Pos.z += dz; //char* tp = (char*)malloc(sizeof(char*)*500); // allocate char //sprintf_s(tp,500,"In with the new?????\n\0"); //OutputDebugString(tp); posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_FAR; if (b->l == BoxObject::BACK) { setNextBox(b,b->front); return true; } } if (box1.max.z > box2.max.z) { dz = box2.max.z - box1.max.z; obj1Pos.z += dz; posChanged = true; plane->m_stopState = plane->m_stopState | PlaneObject::STOP_FAR; if (b->l == BoxObject::BACK) { setNextBox(b,b->front); return true; } } if (!posChanged) { // No walls hit, so plane can move normally plane->m_stopState = PlaneObject::NO_STOP; } obj1.setPPosition(obj1Pos); return true; } return false; }
bool Ned3DObjectManager::enforcePosition(GameObject &moving, GameObject &stationary) { // Bullet stuff: //collisionWorld->contactPairTest(moving.colOb,stationary.colOb, *renderCallback); /* btVector3 v(0.0f,0.0f,0.0f); const btConvexPolyhedron* cP = NULL; const btConvexPolyhedron* cP2 = NULL; if ( moving.colOb->getCollisionShape()->isPolyhedral() ) { btPolyhedralConvexShape* pCS = ((btPolyhedralConvexShape*) moving.colOb->getCollisionShape()); //pCS->initializePolyhedralFeatures(); // TODO wasn't doing this on startup, now I am cP = pCS->getConvexPolyhedron(); } if (stationary.colOb->getCollisionShape()->isPolyhedral() ) { btPolyhedralConvexShape* pCS = ((btPolyhedralConvexShape*) stationary.colOb->getCollisionShape()); //pCS->initializePolyhedralFeatures(); // TODO wasn't doing this on startup, now I am cP2 = pCS->getConvexPolyhedron(); } bool collision = false; if (cP && cP2) { collision = btPolyhedralContactClipping::findSeparatingAxis(*cP,*cP2, moving.colOb->getWorldTransform(),stationary.colOb->getWorldTransform(), v,renderCallback); } btVector3 v2 = moving.colOb->getWorldTransform().getOrigin(); if (collision) { char* tp = (char*)malloc(sizeof(char*)*500); // allocate char sprintf_s(tp,500,"hello world %f %f %f\n\0",v2.getX(),v2.getY(),v2.getZ()); OutputDebugString(tp); delete tp; } return collision;*/ const AABB3 &box1 = moving.getBoundingBox(), &box2 = stationary.getBoundingBox(); AABB3 intersectBox; if(AABB3::intersect(box1, box2, &intersectBox)) { // Collision: Knock back obj1 // - Kludge method: Push back on smallest dimension Vector3 delta = intersectBox.size(); Vector3 obj1Pos = moving.getPosition(), obj2Pos = stationary.getPosition(); if(delta.x <= delta.y) if(delta.x <= delta.z) { // Push back on x obj1Pos.x += (box1.min.x < box2.min.x) ? -delta.x : delta.x; } else { // Push back on z obj1Pos.z += (box1.min.z < box2.min.z) ? -delta.z : delta.z; } else if(delta.y <= delta.z) { // Push back on y obj1Pos.y += (box1.min.y < box2.min.y) ? -delta.y : delta.y; } else { // Push back on z obj1Pos.z += (box1.min.z < box2.min.z) ? -delta.z : delta.z; } moving.setPPosition(obj1Pos); return true; } return false; }
static void AddContactPoint( TCFixedVector< CJL_CollPointInfo, MAX_CONTACTS_PER_BOX_PAIR >& vecCollPointInfo, Vector3& rvNormal, Scalar fPenetrationDepth, CJL_Shape_Box& rBox0, CJL_Shape_Box& rBox1, CJL_CollisionFunctor& rColFunctor ) /* static void AddContactPoint( Vector3& rvNormal, Scalar fPenetrationDepth, CJL_Shape_Box& rBox0, CJL_Shape_Box& rBox1, CJL_CollisionFunctor& rColFunctor )*/ { CJL_ContactInfo contact; contact.pBody0 = &rBox0; contact.pBody1 = &rBox1; // same normal and penetration depths are applied to contact points contact.vNormal = rvNormal; contact.fPenetrationDepth = fPenetrationDepth; ///// check box edges against box float fFraction = 1.0f; Vector3 vEnd = Vector3(0,0,0); BSPTreeForBox bsp_tree; // transform edges to the local space of the box bool b0, b1; Vector3 vWorldStart, vWorldGoal, vLocalStart, vLocalGoal; Vector3 vHalfLength; Matrix34 actor_world_pose; Matrix34 box_local_pose; AABB3 aabb; int i, j; CJL_Shape_Box *pBox[2]; pBox[0] = &rBox0; pBox[1] = &rBox1; TCFixedVector< Vector3, MAX_CONTACTS_PER_BOX_PAIR > vecPts; for( i=0; i<2; i++ ) { // check the edges of box[(i+1)%2] against box[i] (swap boxes and do this for each other) vHalfLength = pBox[i]->GetSideLength() * 0.5f; /// bsptree.SetAABB( vHalfLength ); aabb.vMin = -vHalfLength; aabb.vMax = vHalfLength; Vector3 vSideLength = pBox[i]->GetSideLength(); bsp_tree.SetSize( vSideLength.x, vSideLength.y, vSideLength.z ); for( j=0; j<12; j+=2 ) { pBox[(i+1)%2]->GetWorldEdge( j, vWorldStart, vWorldGoal ); // transform from world space to 'pBox[i]' space pBox[i]->GetWorldPose().InvTransform( vLocalStart, vWorldStart ); pBox[i]->GetWorldPose().InvTransform( vLocalGoal, vWorldGoal ); b0 = aabb.IsPointInside( vLocalStart ); b1 = aabb.IsPointInside( vLocalGoal ); if( b0 && b1 ) continue; // the entire line segment is inside the box[i] if( !b0 ) { fFraction = 1.0f; bsp_tree.ClipTrace( vEnd, fFraction, vLocalStart, vLocalGoal, 0 ); if( fFraction < 1.0f ) { // found collision if( fFraction < SCALAR_TINY ) { fFraction = 0; vEnd = vLocalStart; } else if( 1 - SCALAR_TINY < fFraction ) { fFraction = 1.0f; vEnd = vLocalGoal; } // transform contact point from the local space of pBox[i] to the world space pBox[i]->GetWorldPose().Transform( contact.vContactPoint, vEnd ); // transform contact normal (orientation only) // contact.vNormal = pBox[i]->GetWorldOrient() * tr.plane.normal; // contact.fPenetrationDepth = fPenetrationDepth; if( vecPts.size() < MAX_CONTACTS_PER_BOX_PAIR ) vecPts.push_back( contact.vContactPoint ); } } if( !b1 ) { fFraction = 1.0f; bsp_tree.ClipTrace( vEnd, fFraction, vLocalGoal, vLocalStart, 0 ); if( fFraction < 1.0f ) { // found collision if( fFraction < SCALAR_TINY ) { fFraction = 0; vEnd = vLocalStart; } else if( 1 - SCALAR_TINY < fFraction ) { fFraction = 1.0f; vEnd = vLocalGoal; } // transform contact point from the local space of pBox[i] to the world space pBox[i]->GetWorldPose().Transform( contact.vContactPoint, vEnd ); if( vecPts.size() < MAX_CONTACTS_PER_BOX_PAIR ) vecPts.push_back( contact.vContactPoint ); } } } } CJL_PhysicsActor *pActor0 = rBox0.GetPhysicsActor(); CJL_PhysicsActor *pActor1 = rBox1.GetPhysicsActor(); // const Vector3& vOldPos0 = pActor0 ? pActor0->GetOldPosition() : Vector3(0,0,0); // const Vector3& vOldPos1 = pActor1 ? pActor1->GetOldPosition() : Vector3(0,0,0); const Vector3& vNewActorPos0 = pActor0 ? pActor0->GetPosition() : Vector3(0,0,0); const Vector3& vNewActorPos1 = pActor1 ? pActor1->GetPosition() : Vector3(0,0,0); const Vector3& vOldPos0 = pActor0 ? rBox0.GetOldWorldPose().vPosition : Vector3(0,0,0); const Vector3& vOldPos1 = pActor1 ? rBox1.GetOldWorldPose().vPosition : Vector3(0,0,0); const Vector3& vNewPos0 = pActor0 ? rBox0.GetWorldPose().vPosition : Vector3(0,0,0); const Vector3& vNewPos1 = pActor1 ? rBox1.GetWorldPose().vPosition : Vector3(0,0,0); const Vector3 vBodyDelta = (vNewPos0 - vOldPos0) - (vNewPos1 - vOldPos1); const Scalar fBodyDeltaLen = Vec3Dot( vBodyDelta, rvNormal ); Scalar fOldDepth = fPenetrationDepth + fBodyDeltaLen; // if oldDepth > 0 then reduce it so that the penetration code will // result in a torque??? if( 0 < fOldDepth ) fOldDepth *= 0.8f; #ifndef USE_COMBINED_COLLISION_POINTS_INFO contact.InitialPenetration = fOldDepth; contact.pBody0 = (CJL_ShapeBase *)&rBox0; contact.pBody1 = (CJL_ShapeBase *)&rBox1; int num_pnts = vecPts.size(); for( i=0; i<num_pnts; i++ ) { contact.vContactPoint = vecPts[i]; // contact.vR0 = vecPts[i] - vNewPos0; // contact.vR1 = vecPts[i] - vNewPos1; contact.vR0 = vecPts[i] - vNewActorPos0; contact.vR1 = vecPts[i] - vNewActorPos1; rColFunctor.AddTemporaryContact( contact ); } #else // TCFixedVector< CJL_CollPointInfo, MAX_CONTACTS_PER_BOX_PAIR > vecCollPointInfo; int num_pnts = vecPts.size(); for( i=0; i<num_pnts; i++ ) { vecCollPointInfo.push_back( CJL_CollPointInfo( vecPts[i] - vNewActorPos0, vecPts[i] - vNewActorPos1, fOldDepth ) ); // store contact position vecCollPointInfo.back().vContactPosition = vecPts[i]; } /// rColFunctor.AddTemporaryContacts( &rBox0, /// &rBox1, /// rvNormal, /// &vecCollPointInfo[0], /// vecCollPointInfo.size() ); #endif /* rColFunctor.AddTemporaryContacts( (CJL_ShapeBase *)&rBox0, (CJL_ShapeBase *)&rBox1, rvNormal, &vecPts[0], vecPts.size(), fOldDepth );*/ }
/// Transforms the box and computes a new AABB. This always results in an /// AABB that is at least as large as the original. /// \param box Specifies the box to be transformed. /// \param m Specifies the transformation to be performed. void AABB3::setToTransformedBox(const AABB3 &box, const Matrix4x3 &m) { // If we're empty, then bail if (box.isEmpty()) { empty(); return; } // Start with the translation portion min = max = m.getTranslation(); // Examine each of the 9 matrix elements // and compute the new AABB if (m.m11 > 0.0f) { min.x += m.m11 * box.min.x; max.x += m.m11 * box.max.x; } else { min.x += m.m11 * box.max.x; max.x += m.m11 * box.min.x; } if (m.m12 > 0.0f) { min.y += m.m12 * box.min.x; max.y += m.m12 * box.max.x; } else { min.y += m.m12 * box.max.x; max.y += m.m12 * box.min.x; } if (m.m13 > 0.0f) { min.z += m.m13 * box.min.x; max.z += m.m13 * box.max.x; } else { min.z += m.m13 * box.max.x; max.z += m.m13 * box.min.x; } if (m.m21 > 0.0f) { min.x += m.m21 * box.min.y; max.x += m.m21 * box.max.y; } else { min.x += m.m21 * box.max.y; max.x += m.m21 * box.min.y; } if (m.m22 > 0.0f) { min.y += m.m22 * box.min.y; max.y += m.m22 * box.max.y; } else { min.y += m.m22 * box.max.y; max.y += m.m22 * box.min.y; } if (m.m23 > 0.0f) { min.z += m.m23 * box.min.y; max.z += m.m23 * box.max.y; } else { min.z += m.m23 * box.max.y; max.z += m.m23 * box.min.y; } if (m.m31 > 0.0f) { min.x += m.m31 * box.min.z; max.x += m.m31 * box.max.z; } else { min.x += m.m31 * box.max.z; max.x += m.m31 * box.min.z; } if (m.m32 > 0.0f) { min.y += m.m32 * box.min.z; max.y += m.m32 * box.max.z; } else { min.y += m.m32 * box.max.z; max.y += m.m32 * box.min.z; } if (m.m33 > 0.0f) { min.z += m.m33 * box.min.z; max.z += m.m33 * box.max.z; } else { min.z += m.m33 * box.max.z; max.z += m.m33 * box.min.z; } }