void Etherform::findContact(VectorF *contactNormal) { SceneObject *contactObject = NULL; Vector<SceneObject*> overlapObjects; _findContact(&contactObject, contactNormal, &overlapObjects ); // Check for triggers, corpses and items. const U32 filterMask = isGhost() ? sClientCollisionContactMask : sServerCollisionContactMask; for ( U32 i=0; i < overlapObjects.size(); i++ ) { SceneObject *obj = overlapObjects[i]; U32 objectMask = obj->getTypeMask(); if ( !( objectMask & filterMask ) ) continue; // Check: triggers, tactical zones, corpses and items... // if (objectMask & TriggerObjectType) { Trigger* pTrigger = static_cast<Trigger*>( obj ); pTrigger->potentialEnterObject(this); } else if (objectMask & TacticalZoneObjectType) { TacticalZone* pZone = static_cast<TacticalZone*>( obj ); pZone->potentialEnterObject(this); } else if (objectMask & CorpseObjectType) { // If we've overlapped the worldbounding boxes, then that's it... if ( getWorldBox().isOverlapped( obj->getWorldBox() ) ) { ShapeBase* col = static_cast<ShapeBase*>( obj ); queueCollision(col,getVelocity() - col->getVelocity()); } } else if (objectMask & ItemObjectType) { // If we've overlapped the worldbounding boxes, then that's it... Item* item = static_cast<Item*>( obj ); if ( getWorldBox().isOverlapped(item->getWorldBox()) && item->getCollisionObject() != this && !item->isHidden() ) queueCollision(item,getVelocity() - item->getVelocity()); } } mContactInfo.clear(); mContactInfo.contacted = contactObject != NULL; mContactInfo.contactObject = contactObject; if(mContactInfo.contacted) mContactInfo.contactNormal = *contactNormal; }
void NavPath::renderSimple(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat) { if(overrideMat) return; if(state->isReflectPass() || !(isSelected() || mAlwaysRender)) return; GFXDrawUtil *drawer = GFX->getDrawUtil(); GFXStateBlockDesc desc; desc.setZReadWrite(true, false); desc.setBlend(true); desc.setCullMode(GFXCullNone); if(isSelected()) { drawer->drawCube(desc, getWorldBox(), ColorI(136, 255, 228, 5)); desc.setFillModeWireframe(); drawer->drawCube(desc, getWorldBox(), ColorI::BLACK); } desc.setZReadWrite(!mXray, false); ColorI pathColour(255, 0, 255); if(!mIsLooping) { desc.setFillModeSolid(); if(mFromSet) drawer->drawCube(desc, Point3F(0.2f, 0.2f, 0.2f), mFrom, pathColour); if(mToSet) drawer->drawCube(desc, Point3F(0.2f, 0.2f, 0.2f), mTo, pathColour); } GFXStateBlockRef sb = GFX->createStateBlock(desc); GFX->setStateBlock(sb); PrimBuild::color3i(pathColour.red, pathColour.green, pathColour.blue); PrimBuild::begin(GFXLineStrip, mPoints.size()); for (U32 i = 0; i < mPoints.size(); i++) PrimBuild::vertex3fv(mPoints[i]); PrimBuild::end(); if(mRenderSearch && getServerObject()) { NavPath *np = static_cast<NavPath*>(getServerObject()); if(np->mQuery && !dtStatusSucceed(np->mStatus)) { duDebugDrawTorque dd; dd.overrideColor(duRGBA(250, 20, 20, 255)); duDebugDrawNavMeshNodes(&dd, *np->mQuery); dd.render(); } } }
void NavMesh::render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat) { if(overrideMat) return; if(state->isReflectPass()) return; PROFILE_SCOPE(NavMesh_Render); GFXDrawUtil *drawer = GFX->getDrawUtil(); GFXStateBlockDesc desc; desc.setZReadWrite(true, false); desc.setBlend(true); desc.setCullMode(GFXCullNone); drawer->drawCube(desc, getWorldBox(), ColorI(136, 255, 228, 45)); desc.setFillModeWireframe(); drawer->drawCube(desc, getWorldBox(), ColorI::BLACK); // Recast debug draw duDebugDrawTorque dd; NetObject *no = getServerObject(); if(no && isSelected()) { NavMesh *n = static_cast<NavMesh*>(no); RenderMode mode = mRenderMode; bool build = n->mBuilding; if(build) { mode = RENDER_NAVMESH; dd.overrideColour(duRGBA(255, 0, 0, 80)); } n->mNavMeshLock.lock(); switch(mode) { case RENDER_NAVMESH: if(n->nm) duDebugDrawNavMesh (&dd, *n->nm, 0); break; case RENDER_CONTOURS: if(n->cs) duDebugDrawContours (&dd, *n->cs); break; case RENDER_POLYMESH: if(n->pm) duDebugDrawPolyMesh (&dd, *n->pm); break; case RENDER_DETAILMESH: if(n->pmd) duDebugDrawPolyMeshDetail (&dd, *n->pmd); break; case RENDER_PORTALS: if(n->nm) duDebugDrawNavMeshPortals (&dd, *n->nm); break; } if(n->cs && mRenderConnections && !build) duDebugDrawRegionConnections(&dd, *n->cs); if(n->mInPolys && mRenderInput && !build) n->mInPolys->render(); n->mNavMeshLock.unlock(); } }
void Mortar::fire() { //Only fire if a soldier to occupying the mortar if (occupied) { // See if time to fire. if (fire_countdown > 0) return; //Reset countdown fire_countdown = fire_slowdown + (int)(rand() % 10); //Check if player is in range int y_offset = player->getPosition().getY() - getPosition().getY(); if (y_offset > 0 && boxIntersectsBox(getWorldBox(this), df::WorldManager::getInstance().getView())) { // Fire bomb on player EnemyBombShot *p = new EnemyBombShot(player->getPosition()); //Reset countdown firing_anim_countdown = firing_anim_slowdown; firing = true; // Play "fire" sound. } } }
void FootSoldier::fire() { // See if time to fire. if (fire_countdown > 0) return; //Reset countdown fire_countdown = fire_slowdown; //Check if player is in range int y_offset = player->getPosition().getY() - getPosition().getY(); if (y_offset < df::GraphicsManager::getInstance().getVertical() * 3 / 4 && y_offset > 0 && boxIntersectsBox(getWorldBox(this), df::WorldManager::getInstance().getView())) { // Fire Bullet towards target. df::Position pos; if (player->getPosition().getX() > getPosition().getX()) pos = df::Position::Position(getPosition().getX() + 2, getPosition().getY()); else pos = df::Position::Position(getPosition().getX() - 2, getPosition().getY()); EnemyGunShot *p = new EnemyGunShot(pos); p->setXVelocity((float)(player->getPosition().getX() - pos.getX()) / (float)(player->getPosition().getY() - pos.getY())); // Play "fire" sound. } }
void VehicleBlocker::buildConvex(const Box3F& box, Convex* convex) { // These should really come out of a pool mConvexList->collectGarbage(); if (box.isOverlapped(getWorldBox()) == false) return; // Just return a box convex for the entire shape... Convex* cc = 0; CollisionWorkingList& wl = convex->getWorkingList(); for (CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext) { if (itr->mConvex->getType() == BoxConvexType && itr->mConvex->getObject() == this) { cc = itr->mConvex; break; } } if (cc) return; // Create a new convex. BoxConvex* cp = new BoxConvex; mConvexList->registerObject(cp); convex->addToWorkingList(cp); cp->init(this); mObjBox.getCenter(&cp->mCenter); cp->mSize.x = mObjBox.len_x() / 2.0f; cp->mSize.y = mObjBox.len_y() / 2.0f; cp->mSize.z = mObjBox.len_z() / 2.0f; }
//.logicking >> void StaticShape::updatePhysics() { SAFE_DELETE(mPhysicsRep); if ( PHYSICSMGR) { mShapeInstance->animate(); // Get the interior collision geometry. ConcretePolyList polylist; if (buildPolyList(PLC_Collision, &polylist, getWorldBox(), getWorldSphere())) { polylist.triangulate(); PhysicsCollision *colShape = PHYSICSMGR->createCollision(); colShape->addTriangleMesh( polylist.mVertexList.address(), polylist.mVertexList.size(), polylist.mIndexList.address(), polylist.mIndexList.size() / 3, MatrixF::Identity ); PhysicsWorld *world = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" ); mPhysicsRep = PHYSICSMGR->createBody(); //.hack - set kinematic flag to prevent crash on deleting static shape in character sweep(deleting Doors) mPhysicsRep->init( colShape, 0, PhysicsBody::BF_KINEMATIC, this, world ); } if (isServerObject()) setMaskBits(PhysicsMask); } }
void EnemyTank::fire() { // See if time to fire. if (fire_countdown > 0) return; //Reset countdown fire_countdown = fire_slowdown; //Check if player is in range int y_offset = player->getPosition().getY() - getPosition().getY(); int x_offset = player->getPosition().getX() - getPosition().getX(); if (y_offset < df::GraphicsManager::getInstance().getVertical() * 3 / 4 && y_offset > 0 && boxIntersectsBox(getWorldBox(this), df::WorldManager::getInstance().getView()) && abs(x_offset) < 4) { // Fire Cannon EnemyCannonShot *p = new EnemyCannonShot(df::Position(getPosition().getX(), getPosition().getY() + 6)); // Play "cannonFire" sound. df::Sound *p_sound = df::ResourceManager::getInstance().getSound("cannon-shot"); p_sound->play(); } }
void DecalRoad::unpackUpdate( NetConnection *con, BitStream *stream ) { // Unpack Parent. Parent::unpackUpdate( con, stream ); // DecalRoadMask if ( stream->readFlag() ) { String matName; stream->read( &matName ); if ( matName != mMaterialName ) { mMaterialName = matName; Material *pMat = NULL; if ( !Sim::findObject( mMaterialName, pMat ) ) { Con::printf( "DecalRoad::unpackUpdate, failed to find Material of name %s!", mMaterialName.c_str() ); } else { mMaterial = pMat; if ( isProperlyAdded() ) _initMaterial(); } } stream->read( &mBreakAngle ); stream->read( &mSegmentsPerBatch ); stream->read( &mTextureLength ); stream->read( &mRenderPriority ); } // NodeMask if ( stream->readFlag() ) { //U32 count = stream->readInt( 16 ); //mNodes.clear(); //Point3F pos; //F32 width; //for ( U32 i = 0; i < count; i++ ) //{ // mathRead( *stream, &pos ); // stream->read( &width ); // _addNode( pos, width ); //} if (stream->readFlag()) { // Nodes have been passed in this update U32 count = stream->readInt( 16 ); mNodes.clear(); Point3F pos; F32 width; for ( U32 i = 0; i < count; i++ ) { mathRead( *stream, &pos ); stream->read( &width ); _addNode( pos, width ); } } else { // Nodes will arrive as events U32 id; stream->read( &id ); // Check if the road's nodes made it here before we did. NodeListManager::NodeList* list = NULL; if ( gClientNodeListManager->findListById( id, &list, true) ) { // Work with the completed list DecalRoadNodeList* roadList = dynamic_cast<DecalRoadNodeList*>( list ); if (roadList) buildNodesFromList( roadList ); delete list; } else { // Nodes have not yet arrived, so register our interest in the list DecalRoadNodeListNotify* notify = new DecalRoadNodeListNotify( this, id ); gClientNodeListManager->registerNotification( notify ); } } } // GenEdgesMask if ( stream->readFlag() && isProperlyAdded() ) _generateEdges(); // ReClipMask if ( stream->readFlag() && isProperlyAdded() ) _captureVerts(); // TerrainChangedMask if ( stream->readFlag() ) { if ( isProperlyAdded() ) { if ( mTerrainUpdateRect.isOverlapped( getWorldBox() ) ) { _generateEdges(); _captureVerts(); // Clear out the mTerrainUpdateRect since we have updated its // region and we now need to store future terrain changes // in it. mTerrainUpdateRect = Box3F::Invalid; } } } }
F32 GameBase::getUpdatePriority(CameraScopeQuery *camInfo, U32 updateMask, S32 updateSkips) { TORQUE_UNUSED(updateMask); // Calculate a priority used to decide if this object // will be updated on the client. All the weights // are calculated 0 -> 1 Then weighted together at the // end to produce a priority. Point3F pos; getWorldBox().getCenter(&pos); pos -= camInfo->pos; F32 dist = pos.len(); if (dist == 0.0f) dist = 0.001f; pos *= 1.0f / dist; // Weight based on linear distance, the basic stuff. F32 wDistance = (dist < camInfo->visibleDistance)? 1.0f - (dist / camInfo->visibleDistance): 0.0f; // Weight by field of view, objects directly in front // will be weighted 1, objects behind will be 0 F32 dot = mDot(pos,camInfo->orientation); //Winterleaf Modification //bool inFov = dot > camInfo->cosFov; bool inFov = dot > (cos( (camInfo->fov + 40) >360?360:camInfo->fov + 40)/2); //Winterleaf Modification F32 wFov = inFov? 1.0f: 0; // Weight by linear velocity parallel to the viewing plane // (if it's the field of view, 0 if it's not). F32 wVelocity = 0.0f; if (inFov) { Point3F vec; mCross(camInfo->orientation,getVelocity(),&vec); wVelocity = (vec.len() * camInfo->fov) / (camInfo->fov * camInfo->visibleDistance); if (wVelocity > 1.0f) wVelocity = 1.0f; } // Weight by interest. F32 wInterest; if (getTypeMask() & PlayerObjectType) wInterest = 0.75f; else if (getTypeMask() & ProjectileObjectType) { // Projectiles are more interesting if they // are heading for us. wInterest = 0.30f; F32 dot = -mDot(pos,getVelocity()); if (dot > 0.0f) wInterest += 0.20 * dot; } else { if (getTypeMask() & ItemObjectType) wInterest = 0.25f; else // Everything else is less interesting. wInterest = 0.0f; } // Weight by updateSkips F32 wSkips = updateSkips * 0.5; // Calculate final priority, should total to about 1.0f // return wFov * sUpFov + wDistance * sUpDistance + wVelocity * sUpVelocity + wSkips * sUpSkips + wInterest * sUpInterest; }
void PxSingleActor::_updateContainerForces() { if ( !mWorld->getEnabled() ) return; PROFILE_SCOPE( PxSingleActor_updateContainerForces ); // Update container drag and buoyancy properties ContainerQueryInfo info; info.box = getWorldBox(); info.mass = getMass(); // Find and retreive physics info from intersecting WaterObject(s) mContainer->findObjects( getWorldBox(), WaterObjectType|PhysicalZoneObjectType, findRouter, &info ); // Calculate buoyancy and drag F32 angDrag = mBuildAngDrag; F32 linDrag = mBuildLinDrag; F32 buoyancy = 0.0f; if ( true ) //info.waterCoverage >= 0.1f) { F32 waterDragScale = info.waterViscosity * mDataBlock->waterDragScale; F32 powCoverage = mPow( info.waterCoverage, 0.25f ); if ( info.waterCoverage > 0.0f ) { //angDrag = mBuildAngDrag * waterDragScale; //linDrag = mBuildLinDrag * waterDragScale; angDrag = mLerp( mBuildAngDrag, mBuildAngDrag * waterDragScale, powCoverage ); linDrag = mLerp( mBuildLinDrag, mBuildLinDrag * waterDragScale, powCoverage ); } buoyancy = ( info.waterDensity / mDataBlock->buoyancyDensity ) * mPow( info.waterCoverage, 2.0f ); } // Apply drag (dampening) mActor->setLinearDamping( linDrag ); mActor->setAngularDamping( angDrag ); // Apply buoyancy force if ( buoyancy != 0 ) { // A little hackery to prevent oscillation // Based on this blog post (http://reinot.blogspot.com/2005/11/oh-yes-they-float-georgie-they-all.html) // JCF: DISABLED NxVec3 gravity; mWorld->getScene()->getGravity(gravity); //NxVec3 velocity = mActor->getLinearVelocity(); NxVec3 buoyancyForce = buoyancy * -gravity * TickSec; //F32 currHeight = getPosition().z; //const F32 C = 2.0f; //const F32 M = 0.1f; //if ( currHeight + velocity.z * TickSec * C > info.waterHeight ) // buoyancyForce *= M; mActor->addForceAtPos( buoyancyForce, mActor->getCMassGlobalPosition(), NX_IMPULSE ); } // Apply physical zone forces if ( info.appliedForce.len() > 0.001f ) mActor->addForceAtPos( pxCast<NxVec3>(info.appliedForce), mActor->getCMassGlobalPosition(), NX_IMPULSE ); }
bool NavMesh::generateMesh() { // Parse objects from level into RC-compatible format NavModelData data = NavMeshLoader::mergeModels( NavMeshLoader::parseTerrainData(getWorldBox(), 0), NavMeshLoader::parseStaticObjects(getWorldBox()), true); // Check for no geometry if(!data.getVertCount()) return false; // Free intermediate and final results freeIntermediates(true); // Create mInPolys if we don't have one already if(!mInPolys && mSaveIntermediates) mInPolys = new ConcretePolyList(); // Reconstruct input geometry from out data if(mSaveIntermediates) RCtoPolyList(&data, mInPolys); // Recast initialisation data rcContext ctx(false); rcConfig cfg; dMemset(&cfg, 0, sizeof(cfg)); cfg.cs = mCellSize; cfg.ch = mCellHeight; rcCalcBounds(data.verts, data.getVertCount(), cfg.bmin, cfg.bmax); rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height); cfg.walkableHeight = mCeil(mWalkableHeight / mCellHeight); cfg.walkableClimb = mCeil(mWalkableClimb / mCellHeight); cfg.walkableRadius = mCeil(mWalkableRadius / mCellSize); cfg.walkableSlopeAngle = mWalkableSlope; cfg.borderSize = mBorderSize; cfg.detailSampleDist = mDetailSampleDist; cfg.detailSampleMaxError = mDetailSampleMaxError; cfg.maxEdgeLen = mMaxEdgeLen; cfg.maxSimplificationError = mMaxSimplificationError; cfg.maxVertsPerPoly = 3; cfg.minRegionArea = mMinRegionArea; cfg.mergeRegionArea = mMergeRegionArea; cfg.tileSize = mTileSize; if(!createPolyMesh(cfg, data, &ctx)) return false; //Detour initialisation data dtNavMeshCreateParams params; dMemset(¶ms, 0, sizeof(params)); params.walkableHeight = cfg.walkableHeight; params.walkableRadius = cfg.walkableRadius; params.walkableClimb = cfg.walkableClimb; params.tileX = 0; params.tileY = 0; params.tileLayer = 0; rcVcopy(params.bmax, cfg.bmax); rcVcopy(params.bmin, cfg.bmin); params.buildBvTree = true; params.ch = cfg.ch; params.cs = cfg.cs; params.verts = pm->verts; params.vertCount = pm->nverts; params.polys = pm->polys; params.polyAreas = pm->areas; params.polyFlags = pm->flags; params.polyCount = pm->npolys; params.nvp = pm->nvp; params.detailMeshes = pmd->meshes; params.detailVerts = pmd->verts; params.detailVertsCount = pmd->nverts; params.detailTris = pmd->tris; params.detailTriCount = pmd->ntris; if(!createNavMesh(params)) return false; return true; }
void DecalRoad::unpackUpdate( NetConnection *con, BitStream *stream ) { // Unpack Parent. Parent::unpackUpdate( con, stream ); // NodeMask if ( stream->readFlag() ) { U32 count = stream->readInt( 16 ); mNodes.clear(); Point3F pos; F32 width; for ( U32 i = 0; i < count; i++ ) { mathRead( *stream, &pos ); stream->read( &width ); _addNode( pos, width ); } } // DecalRoadMask if ( stream->readFlag() ) { String matName; stream->read( &matName ); if ( matName != mMaterialName ) { mMaterialName = matName; Material *pMat = NULL; if ( !Sim::findObject( mMaterialName, pMat ) ) { Con::printf( "DecalRoad::unpackUpdate, failed to find Material of name %s!", mMaterialName.c_str() ); } else { mMaterial = pMat; if ( isProperlyAdded() ) _initMaterial(); } } stream->read( &mBreakAngle ); stream->read( &mSegmentsPerBatch ); stream->read( &mTextureLength ); stream->read( &mRenderPriority ); } // GenEdgesMask if ( stream->readFlag() && isProperlyAdded() ) _generateEdges(); // ReClipMask if ( stream->readFlag() && isProperlyAdded() ) _captureVerts(); // TerrainChangedMask if ( stream->readFlag() ) { if ( isProperlyAdded() ) { if ( mTerrainUpdateRect.isOverlapped( getWorldBox() ) ) { _generateEdges(); _captureVerts(); // Clear out the mTerrainUpdateRect since we have updated its // region and we now need to store future terrain changes // in it. mTerrainUpdateRect = Box3F::Invalid; } } } }