bool CPersistantDebug::GetEntityParams(EntityId entityId, Vec3& baseCenterPos, float& height) { IEntity *ent = gEnv->pEntitySystem->GetEntity(entityId); if (ent) { AABB bounds; ent->GetWorldBounds(bounds); baseCenterPos = bounds.GetCenter(); baseCenterPos.z = bounds.min.z; height = bounds.GetSize().z; return true; } return false; }
virtual void GetDimension(BaseObject* op, Vector* mp, Vector* rad) override { // Find the Minimum/Maximum of the object's bounding // box by all hidden child-objects in its hierarchy. AABB bbox; for (NodeIterator<BaseObject> it(op->GetDown(), op); it; ++it) { // We skip objects that are being controlled by // a generator object. if (it->GetInfo() & OBJECT_GENERATOR && !IsControlledByGenerator(*it)) bbox.Expand(*it, it->GetMg(), false); } *mp = bbox.GetMidpoint(); *rad = bbox.GetSize(); }
// Calculates the desired position for the physics box, so that its center will be superimposed with AABB center of provided entity. // Also adjusts upwards to avoid any obvious floor clipping. Returns desired Position for entity. Vec3 CIntersectionAssistanceUnit::CalculateTargetAdjustPoint(const IEntity* pEntity, const Matrix34 &wMat, const Vec3& vStartingPos) const { // (if present + desired) adjust physbox center to that of owner Ent - to make sure centers of PhysBox + focal ent superimposed // at the desired position const IEntity* pFocalEnt = gEnv->pEntitySystem->GetEntity(m_focalEntityId); if(pFocalEnt) { OBB focalOBB; AABB focalAABB; // Compensate for actor/non actor entities that require different paths :( if(CPlayer* pPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_focalEntityId))) { EStance playerStance = pPlayer->GetStance(); focalAABB = pPlayer->GetStanceInfo(playerStance)->GetStanceBounds(); } else { pFocalEnt->GetLocalBounds(focalAABB); } focalOBB.SetOBBfromAABB(Quat(IDENTITY), focalAABB); // shift to match focus ent Center (taking into account crouch etc if player). float fVerticalAdjust = focalOBB.h.z; // Additionally.. if the new test pos *would* immediately penetrate the floor (assumption based on any part of the volume being < player AABB z min value) // shift it up. float fFloorPenetrationAdjust = 0.0f; AABB wEntABB; pEntity->GetLocalBounds(wEntABB); wEntABB.SetTransformedAABB(wMat,wEntABB); float fFloorClearance = focalOBB.h.z - (wEntABB.GetSize().z * 0.5f); fFloorPenetrationAdjust += (0.0f - min(fFloorClearance, 0.0f)); // Apply floor clearance + Vertical adjust Vec3 desiredPos = wMat.GetTranslation() + Vec3(0.0f,0.0f,(fFloorPenetrationAdjust) * kFloorAdjustConstant); desiredPos += (fVerticalAdjust * pFocalEnt->GetWorldTM().GetColumn2() * kFloorAdjustConstant); return desiredPos; } return wMat.GetTranslation(); }
//------------------------------------------------------------------------ void CGameRules::CullEntitiesInExplosion(const ExplosionInfo &explosionInfo) { if (!g_pGameCVars->g_ec_enable || explosionInfo.damage <= 0.1f) return; IPhysicalEntity **pents; float radiusScale = g_pGameCVars->g_ec_radiusScale; float minVolume = g_pGameCVars->g_ec_volume; float minExtent = g_pGameCVars->g_ec_extent; int removeThreshold = max(1, g_pGameCVars->g_ec_removeThreshold); IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); Vec3 radiusVec(radiusScale * explosionInfo.physRadius); int i = gEnv->pPhysicalWorld->GetEntitiesInBox(explosionInfo.pos-radiusVec,explosionInfo.pos+radiusVec,pents, ent_rigid|ent_sleeping_rigid); int removedCount = 0; static IEntityClass* s_pInteractiveEntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("InteractiveEntity"); static IEntityClass* s_pDeadBodyClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DeadBody"); if (i > removeThreshold) { int entitiesToRemove = i - removeThreshold; for(--i;i>=0;i--) { if(removedCount>=entitiesToRemove) break; IEntity * pEntity = (IEntity*) pents[i]->GetForeignData(PHYS_FOREIGN_ID_ENTITY); if (pEntity) { // don't remove if entity is held by the player if (pClientActor && pEntity->GetId()==pClientActor->GetGrabbedEntityId()) continue; // don't remove items/pickups if (IItem* pItem = g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(pEntity->GetId())) { continue; } // don't remove enemies/ragdolls if (IActor* pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId())) { continue; } // if there is a flowgraph attached, never remove! if (pEntity->GetProxy(ENTITY_PROXY_FLOWGRAPH) != 0) continue; IEntityClass* pClass = pEntity->GetClass(); if (pClass == s_pInteractiveEntityClass || pClass == s_pDeadBodyClass) continue; // get bounding box if (IEntityPhysicalProxy* pPhysProxy = (IEntityPhysicalProxy*)pEntity->GetProxy(ENTITY_PROXY_PHYSICS)) { AABB aabb; pPhysProxy->GetWorldBounds(aabb); // don't remove objects which are larger than a predefined minimum volume if (aabb.GetVolume() > minVolume) continue; // don't remove objects which are larger than a predefined minimum volume Vec3 size(aabb.GetSize().abs()); if (size.x > minExtent || size.y > minExtent || size.z > minExtent) continue; } // marcok: somehow editor doesn't handle deleting non-dynamic entities very well // but craig says, hiding is not synchronized for DX11 breakable MP, so we remove entities only when playing pure game // alexl: in SinglePlayer, we also currently only hide the object because it could be part of flowgraph logic // which would break if Entity was removed and could not propagate events anymore if (gEnv->bMultiplayer == false || gEnv->IsEditor()) { pEntity->Hide(true); } else { gEnv->pEntitySystem->RemoveEntity(pEntity->GetId()); } removedCount++; } } } }
//---------------------------------------------------------------------------------------------------------------------------------- /// Init dynamics //---------------------------------------------------------------------------------------------------------------------------------- void CARDYNAMICS::Init( class SETTINGS* pSet1, class Scene* pScene1, class FluidsXml* pFluids1, COLLISION_WORLD & world, const MODEL & chassisModel, const MODEL & wheelModelFront, const MODEL & wheelModelRear, const MATHVECTOR<Dbl,3> & position, const QUATERNION<Dbl> & orientation) { pSet = pSet1; pScene = pScene1; pFluids = pFluids1; this->world = &world; MATHVECTOR<Dbl,3> zero(0, 0, 0); body.SetPosition(position); body.SetOrientation(orientation); body.SetInitialForce(zero); body.SetInitialTorque(zero); // init engine engine.SetInitialConditions(); // init chassis btTransform tr; tr.setIdentity(); AABB <float> box = chassisModel.GetAABB(); for (int i = 0; i < 4; i++) { MATHVECTOR<float,3> wheelpos = GetLocalWheelPosition(WHEEL_POSITION(i), 0); const MODEL * wheelmodel = &wheelModelFront; if (i > 1) wheelmodel = &wheelModelRear; AABB <float> wheelaabb; float sidefactor = 1.0; if (i == 1 || i == 3) sidefactor = -1.0; wheelaabb.SetFromCorners( wheelpos - wheelmodel->GetAABB().GetSize() * 0.5 * sidefactor, wheelpos + wheelmodel->GetAABB().GetSize() * 0.5 * sidefactor); box.CombineWith(wheelaabb); } /// chassis shape --------------------------------------------------------- const MATHVECTOR<Dbl,3> verticalMargin(0, 0, 0.3); btVector3 origin = ToBulletVector(box.GetCenter() + verticalMargin - center_of_mass); btVector3 size = ToBulletVector(box.GetSize() - verticalMargin); //btCompoundShape * chassisShape = new btCompoundShape(false); #if 0 //btBoxShape * hull = new btBoxShape( btVector3(1.8,0.8,0.5) ); btBoxShape * hull = new btBoxShape( btVector3(1.7,0.7,0.3) ); tr.setOrigin(origin + btVector3(0,0,0.2)); chassisShape->addChildShape(tr, hull); #else /// todo: all params in .car // y| length x- width z^ height btScalar w = size.getX()*0.2, r = size.getZ()*0.3, h = 0.45; /// spheres btScalar l0 = 0.f, w0 = 0.f, h0 = 0.f; if (coll_R > 0.f) r = coll_R; l0 = coll_Lofs; if (coll_W > 0.f) w = coll_W; w0 = coll_Wofs; if (coll_H > 0.f) h = coll_H; h0 = coll_Hofs; origin = btVector3(l0, w0, h0); btScalar r2 = r*0.6; btScalar l1 = coll_posLfront, l2 = coll_posLback, l1m = l1*0.5, l2m = l2*0.5; //LogO("Car shape dims: r="+toStr(r)+" w="+toStr(w)+" h="+toStr(h)+" h0="+toStr(h0)); //LogO("Car offset: x="+toStr(origin.x())+" y="+toStr(origin.y())+" z="+toStr(origin.z())); const int numSph = 14; int i = 0; btScalar rad[numSph]; btVector3 pos[numSph]; pos[i] = btVector3( l1 , -w, -h); rad[i] = r2; ++i; // front pos[i] = btVector3( l1 , w, -h); rad[i] = r2; ++i; pos[i] = btVector3( l1m, -w, -h); rad[i] = r; ++i; // front near pos[i] = btVector3( l1m, w, -h); rad[i] = r; ++i; pos[i] = btVector3( l2m, -w, -h); rad[i] = r; ++i; // rear near pos[i] = btVector3( l2m, w, -h); rad[i] = r; ++i; pos[i] = btVector3( l2 , -w, -h); rad[i] = r2; ++i; // rear pos[i] = btVector3( l2 , w, -h); rad[i] = r2; ++i; pos[i] = btVector3( 0.4, -w*0.8, h*0.2); rad[i] = r2; ++i; // top pos[i] = btVector3( 0.4, w*0.8, h*0.2); rad[i] = r2; ++i; pos[i] = btVector3(-0.3, -w*0.8, h*0.4); rad[i] = r2; ++i; pos[i] = btVector3(-0.3, w*0.8, h*0.4); rad[i] = r2; ++i; pos[i] = btVector3(-1.1, -w*0.8, h*0.2); rad[i] = r2; ++i; // top rear pos[i] = btVector3(-1.1, w*0.8, h*0.2); rad[i] = r2; ++i; for (i=0; i < numSph; ++i) pos[i] += origin; btMultiSphereShape* chassisShape = new btMultiSphereShape(pos, rad, numSph); //chassisShape->setMargin(0.2f); #endif Dbl chassisMass = body.GetMass();// * 0.4; // Magic multiplier makes collisions better - problem: mud is very different MATRIX3 <Dbl> inertia = body.GetInertia(); btVector3 chassisInertia(inertia[0], inertia[4], inertia[8]); btTransform transform; transform.setOrigin(ToBulletVector(position)); transform.setRotation(ToBulletQuaternion(orientation)); btDefaultMotionState * chassisState = new btDefaultMotionState(); chassisState->setWorldTransform(transform); btRigidBody::btRigidBodyConstructionInfo info(chassisMass, chassisState, chassisShape, chassisInertia); info.m_angularDamping = ang_damp; info.m_restitution = 0.0; //... info.m_friction = coll_friction; /// 0.4~ 0.7 /// chasis^ chassis = world.AddRigidBody(info, true, pSet->game.collis_cars); chassis->setActivationState(DISABLE_DEACTIVATION); chassis->setUserPointer(new ShapeData(ST_Car, this, 0)); ///~~ world.AddAction(this); /// join chassis and wheel triggers //________________________________________________________ { for (int w=0; w < 4; ++w) { WHEEL_POSITION wp = WHEEL_POSITION(w); Dbl whR = GetWheel(wp).GetRadius() * 1.2; //bigger par.. MATHVECTOR<float,3> wheelpos = GetWheelPosition(wp, 0); //par wheelpos[0] += coll_Lofs; wheelpos[2] += coll_flTrig_H; btSphereShape* whSph = new btSphereShape(whR); //btCylinderShapeX* whSph = new btCylinderShapeX(btVector3(whR,whR,whR));//todo.. whTrigs = new btRigidBody(0.001f, 0, whSph); whTrigs->setUserPointer(new ShapeData(ST_Wheel, this, 0, w)); ///~~ whTrigs->setActivationState(DISABLE_DEACTIVATION); whTrigs->setCollisionFlags(whTrigs->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); world.world->addRigidBody(whTrigs); world.shapes.push_back(whSph); //todo: collision mask only to fluid triggers //todo: optimize- 1 constr only or none? //todo: cylinders? fixed constr\_ /*btTransform f1,f2; f1.setIdentity(); f2.setIdentity(); f1.setOrigin(ToBulletVector(wheelpos)); btGeneric6DofConstraint* constr = new btGeneric6DofConstraint(*chassis, *whTrigs, f1, f2, true); constr->setLimit(0,0,0); constr->setLimit(1,0,1); constr->setLimit(2,0,0); //constr->setLimit(3,0,0); //constr->setLimit(4,0,0); constr->setLimit(5,0,0);/*??*/ btTypedConstraint* constr = new btPoint2PointConstraint(*chassis, *whTrigs, ToBulletVector(wheelpos), btVector3(0,0,0)); world.world->addConstraint(constr, true); world.constraints.push_back(constr); } /// init poly for buoyancy computations //________________________________________________________ if (poly == NULL) { poly = new Polyhedron(); poly->numVerts = 8; poly->numFaces = 12; poly->verts = new Vec3[8]; poly->faces = new Face[12]; float hx = 1.2f, hy = 0.7f, hz = 0.4f; // box dim poly->verts[0] = Vec3(-hx,-hy,-hz); poly->verts[1] = Vec3(-hx,-hy, hz); poly->verts[2] = Vec3(-hx, hy,-hz); poly->verts[3] = Vec3(-hx, hy, hz); poly->verts[4] = Vec3( hx,-hy,-hz); poly->verts[5] = Vec3( hx,-hy, hz); poly->verts[6] = Vec3( hx, hy,-hz); poly->verts[7] = Vec3( hx, hy, hz); poly->faces[0] = Face(0,1,3); poly->faces[1] = Face(0,3,2); poly->faces[2] = Face(6,3,7); poly->faces[3] = Face(6,2,3); poly->faces[4] = Face(4,6,5); poly->faces[5] = Face(6,7,5); poly->faces[6] = Face(4,5,0); poly->faces[7] = Face(0,5,1); poly->faces[8] = Face(5,7,1); poly->faces[9] = Face(7,3,1); poly->faces[10]= Face(0,6,4); poly->faces[11]= Face(0,2,6); poly->length = 1.0f; // approx. length-? poly->volume = ComputeVolume(*poly); body_mass = 1900.0f * 2.688; //poly->volume; // car density body_inertia = (4.0f * body_mass / 12.0f) * btVector3(hy*hz, hx*hz, hx*hy); } } //------------------------------------------------------------- // init wheels, suspension for (int i = 0; i < WHEEL_POSITION_SIZE; i++) { wheel[WHEEL_POSITION(i)].SetInitialConditions(); wheel_velocity[i].Set(0.0); wheel_position[i] = GetWheelPositionAtDisplacement(WHEEL_POSITION(i), 0); wheel_orientation[i] = orientation * GetWheelSteeringAndSuspensionOrientation(WHEEL_POSITION(i)); } AlignWithGround();//-- }
//----------------------------------------------------------------------- void gkAuxRenderer::AuxRenderAABB( const AABB& aabb, ColorF& color /*= ColorF(1.0,1.0,1.0,1.0)*/, bool ignoreZ ) { //Vec3 vecAABB = aabb.GetCenter(); AuxRender3DBoxFrame( aabb.GetCenter(), aabb.GetSize(), color, ignoreZ ); }