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 collisionFilter(SceneObject* object,void *key) { SceneContainer::CallbackInfo* info = reinterpret_cast<SceneContainer::CallbackInfo*>(key); ShapeBase* ptr = reinterpret_cast<ShapeBase*>(info->key); if (object->getTypeMask() & ItemObjectType) { // We've hit it's bounding box, that's close enough for items. Item* item = static_cast<Item*>(object); if (ptr != item->getCollisionObject()) ptr->queueCollision(item,ptr->getVelocity() - item->getVelocity()); } else if (object->getTypeMask() & TriggerObjectType) { // We've hit it's bounding box, that's close enough for triggers Trigger* pTrigger = static_cast<Trigger*>(object); pTrigger->potentialEnterObject(ptr); } else if (object->getTypeMask() & CorpseObjectType) { // Ok, guess it's close enough for corpses too... ShapeBase* col = static_cast<ShapeBase*>(object); ptr->queueCollision(col,ptr->getVelocity() - col->getVelocity()); } else object->buildPolyList(info->context,info->polyList,info->boundingBox,info->boundingSphere); }
void SFX3DObject::getEarTransform( MatrixF& transform ) const { // If it's not a ShapeBase, just use the object transform. ShapeBase* shape = dynamic_cast< ShapeBase* >( mObject ); if ( !shape ) { transform = mObject->getTransform(); return; } // It it's ShapeBase, use the earNode transform if one was defined. // Otherwise, use the camera transform. TSShapeInstance* shapeInstance = shape->getShapeInstance(); if ( !shapeInstance ) { // Just in case. transform = mObject->getTransform(); return; } ShapeBaseData* datablock = dynamic_cast< ShapeBaseData* >( shape->getDataBlock() ); AssertFatal( datablock, "SFX3DObject::getEarTransform() - shape without ShapeBaseData datablock!" ); // Get the transform for the ear node. const S32 earNode = datablock->earNode; if ( earNode != -1 && earNode != datablock->eyeNode ) { transform = shape->getTransform(); transform *= shapeInstance->mNodeTransforms[ earNode ]; } else { GameConnection* connection = dynamic_cast<GameConnection *>(NetConnection::getConnectionToServer()); if ( !connection || !connection->getControlCameraTransform( 0.0f, &transform ) ) transform = mObject->getTransform(); } }
void FishWave::addFish(){ fishPos = polyline.getPointAtPercent(ofRandom(0, 1)); fishes.clear(); shapes.clear(); particle myParticle; myParticle.setInitialCondition(fishPos.x, fishPos.y, 0, ofRandom(-0.7, -0.8)); fishGravity = ofRandom(-3, -0.8); fishDirection = ofRandom(-0.7, 0.7); myParticle.radius = ofRandom(20, 30); fishes.push_back(myParticle); ofPath p; float scale = 100; float angle = 0; float r = ofRandom(30, 60); int index = (int)ofRandom(shapeTypes.size()); ShapeType t = shapeTypes[index]; ShapeBase* s = ShapeFactory(t); s->setColor(baseColor); s->setup(); shapes.push_back(s); }
// Used to build potential target list static void _scanCallback( SceneObject* object, void* data ) { AITurretShape* turret = (AITurretShape*)data; ShapeBase* shape = dynamic_cast<ShapeBase*>(object); if (shape && shape->getDamageState() == ShapeBase::Enabled) { Point3F targetPos = shape->getBoxCenter(); // Put target position into the scan node's space turret->mScanWorkspaceScanWorldMat.mulP(targetPos); // Is the target within scanning distance if (targetPos.lenSquared() > turret->getMaxScanDistanceSquared()) return; // Make sure the target is in front and within the maximum // heading range Point2F targetXY(targetPos.x, targetPos.y); targetXY.normalizeSafe(); F32 headingDot = mDot(Point2F(0, 1), targetXY); F32 heading = mAcos(headingDot); if (headingDot < 0 || heading > turret->getMaxScanHeading()) return; // Make sure the target is in front and within the maximum // pitch range Point2F targetZY(targetPos.z, targetPos.y); targetZY.normalizeSafe(); F32 pitchDot = mDot(Point2F(0, 1), targetZY); F32 pitch = mAcos(pitchDot); if (pitchDot < 0 || pitch > turret->getMaxScanPitch()) return; turret->addPotentialTarget(shape); } }
void AITurretShape::_performScan() { // Only on server if (isClientObject()) return; // Are we ready for a scan? --mTicksToNextScan; if (mTicksToNextScan > 0) return; _cleanupPotentialTargets(); _setScanBox(); // Set up for the scan getScanTransform(mScanWorkspaceScanMat); mScanWorkspaceScanWorldMat = mScanWorkspaceScanMat; mScanWorkspaceScanWorldMat.affineInverse(); disableCollision(); for ( SimSetIterator iter(&mIgnoreObjects); *iter; ++iter ) { ShapeBase* obj = static_cast<ShapeBase*>( *iter ); obj->disableCollision(); } gServerContainer.findObjects( mTransformedScanBox, sScanTypeMask, _scanCallback, (void*)this ); for ( SimSetIterator iter(&mIgnoreObjects); *iter; ++iter ) { ShapeBase* obj = static_cast<ShapeBase*>( *iter ); obj->enableCollision(); } enableCollision(); if (mPotentialTargets.size() == 0) { // No targets in range. Clear out our current target, if necessary. _lostTarget(); } else { // Sort the targets comparePoint = getPosition(); dQsort(mPotentialTargets.address(),mPotentialTargets.size(),sizeof(SimObjectList::value_type),_sortCallback); // Go through the targets in order to find one that is not blocked from view Point3F start; mScanWorkspaceScanMat.getColumn(3, &start); S32 index = 0; bool los = false; disableCollision(); for (index=0; index < mPotentialTargets.size(); ++index) { ShapeBase* shape = (ShapeBase*)mPotentialTargets[index]; Point3F sightPoint; los = _testTargetLineOfSight(start, shape, sightPoint); // Check if we have a clear line of sight if (los) break; } enableCollision(); // If we found a valid, visible target (no hits between here and there), latch on to it if (los) { _gainedTarget((ShapeBase*)mPotentialTargets[index]); } } // Prepare for next scan period mTicksToNextScan = mScanTickFrequency; if (mScanTickFrequencyVariance > 0) { mTicksToNextScan += gRandGen.randI(0, mScanTickFrequencyVariance); } }
void SimpleDeferredDemo::render() { if( m_firstFrame ) { for(int i=0; i<MAX_BODIES; i++) { const float4& pos = m_pos[i]; const Quaternion& quat = qtGetIdentity(); ShapeBase* boxShape = m_shapes[i]; const float4* vtx = boxShape->getVertexBuffer(); const int4* tris = boxShape->getTriangleBuffer(); float4* v = new float4[boxShape->getNumTris()*3]; u32* idx = new u32[boxShape->getNumTris()*3]; float4* n = new float4[boxShape->getNumTris()*3]; const float4 colors[] = { make_float4(0,1,1,1), make_float4(1,0,1,1), make_float4(1,1,0,1), make_float4(0,0,1,1), make_float4(0,1,0,1), make_float4(1,0,0,1) }; float c = 0.4f; float4 color = make_float4(0.8f-c,0.8f-c,0.8f,1.f)*1.8f; color = make_float4(0.5f,1,0.5f,1); if( i==0 ) color = make_float4(1.f,1.f,1.f, 1.f); for(int it=0; it<boxShape->getNumTris(); it++) { const int4& t = tris[it]; idx[3*it+0] = it*3; idx[3*it+1] = it*3+1; idx[3*it+2] = it*3+2; v[3*it+0] = vtx[t.x]; v[3*it+1] = vtx[t.y]; v[3*it+2] = vtx[t.z]; if( i==0 ) swap2(v[3*it+1], v[3*it+2]); float4 tn = cross3( v[3*it+1] - v[3*it+0], v[3*it+2] - v[3*it+0] ); tn = normalize3( tn ); n[3*it+0] = tn; n[3*it+1] = tn; n[3*it+2] = tn; } int nTris = boxShape->getNumTris(); int nVtx = boxShape->getNumVertex(); // pxReleaseDrawTriangleListTransformed( v, n, idx, nTris*3, nTris*3, color, pos, quat ); pxDrawTriangleListTransformed( v, n, idx, nTris*3, nTris*3, color, pos, quat ); delete [] v; delete [] idx; delete [] n; } // m_firstFrame = false; } }
void Item::updatePos(const U32 /*mask*/, const F32 dt) { // Try and move Point3F pos; mObjToWorld.getColumn(3,&pos); delta.posVec = pos; bool contact = false; bool nonStatic = false; bool stickyNotify = false; CollisionList collisionList; F32 time = dt; static Polyhedron sBoxPolyhedron; static ExtrudedPolyList sExtrudedPolyList; static EarlyOutPolyList sEarlyOutPolyList; MatrixF collisionMatrix(true); Point3F end = pos + mVelocity * time; U32 mask = isServerObject() ? sServerCollisionMask : sClientCollisionMask; // Part of our speed problem here is that we don't track contact surfaces, like we do // with the player. In order to handle the most common and performance impacting // instance of this problem, we'll use a ray cast to detect any contact surfaces below // us. This won't be perfect, but it only needs to catch a few of these to make a // big difference. We'll cast from the top center of the bounding box at the tick's // beginning to the bottom center of the box at the end. Point3F startCast((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5, (mObjBox.minExtents.y + mObjBox.maxExtents.y) * 0.5, mObjBox.maxExtents.z); Point3F endCast((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5, (mObjBox.minExtents.y + mObjBox.maxExtents.y) * 0.5, mObjBox.minExtents.z); collisionMatrix.setColumn(3, pos); collisionMatrix.mulP(startCast); collisionMatrix.setColumn(3, end); collisionMatrix.mulP(endCast); RayInfo rinfo; bool doToughCollision = true; disableCollision(); if (mCollisionObject) mCollisionObject->disableCollision(); if (getContainer()->castRay(startCast, endCast, mask, &rinfo)) { F32 bd = -mDot(mVelocity, rinfo.normal); if (bd >= 0.0) { // Contact! if (mDataBlock->sticky && rinfo.object->getTypeMask() & (STATIC_COLLISION_TYPEMASK)) { mVelocity.set(0, 0, 0); mAtRest = true; mAtRestCounter = 0; stickyNotify = true; mStickyCollisionPos = rinfo.point; mStickyCollisionNormal = rinfo.normal; doToughCollision = false;; } else { // Subtract out velocity into surface and friction VectorF fv = mVelocity + rinfo.normal * bd; F32 fvl = fv.len(); if (fvl) { F32 ff = bd * mDataBlock->friction; if (ff < fvl) { fv *= ff / fvl; fvl = ff; } } bd *= 1 + mDataBlock->elasticity; VectorF dv = rinfo.normal * (bd + 0.002); mVelocity += dv; mVelocity -= fv; // Keep track of what we hit contact = true; U32 typeMask = rinfo.object->getTypeMask(); if (!(typeMask & StaticObjectType)) nonStatic = true; if (isServerObject() && (typeMask & ShapeBaseObjectType)) { ShapeBase* col = static_cast<ShapeBase*>(rinfo.object); queueCollision(col,mVelocity - col->getVelocity()); } } } } enableCollision(); if (mCollisionObject) mCollisionObject->enableCollision(); if (doToughCollision) { U32 count; for (count = 0; count < 3; count++) { // Build list from convex states here... end = pos + mVelocity * time; collisionMatrix.setColumn(3, end); Box3F wBox = getObjBox(); collisionMatrix.mul(wBox); Box3F testBox = wBox; Point3F oldMin = testBox.minExtents; Point3F oldMax = testBox.maxExtents; testBox.minExtents.setMin(oldMin + (mVelocity * time)); testBox.maxExtents.setMin(oldMax + (mVelocity * time)); sEarlyOutPolyList.clear(); sEarlyOutPolyList.mNormal.set(0,0,0); sEarlyOutPolyList.mPlaneList.setSize(6); sEarlyOutPolyList.mPlaneList[0].set(wBox.minExtents,VectorF(-1,0,0)); sEarlyOutPolyList.mPlaneList[1].set(wBox.maxExtents,VectorF(0,1,0)); sEarlyOutPolyList.mPlaneList[2].set(wBox.maxExtents,VectorF(1,0,0)); sEarlyOutPolyList.mPlaneList[3].set(wBox.minExtents,VectorF(0,-1,0)); sEarlyOutPolyList.mPlaneList[4].set(wBox.minExtents,VectorF(0,0,-1)); sEarlyOutPolyList.mPlaneList[5].set(wBox.maxExtents,VectorF(0,0,1)); CollisionWorkingList& eorList = mConvex.getWorkingList(); CollisionWorkingList* eopList = eorList.wLink.mNext; while (eopList != &eorList) { if ((eopList->mConvex->getObject()->getTypeMask() & mask) != 0) { Box3F convexBox = eopList->mConvex->getBoundingBox(); if (testBox.isOverlapped(convexBox)) { eopList->mConvex->getPolyList(&sEarlyOutPolyList); if (sEarlyOutPolyList.isEmpty() == false) break; } } eopList = eopList->wLink.mNext; } if (sEarlyOutPolyList.isEmpty()) { pos = end; break; } collisionMatrix.setColumn(3, pos); sBoxPolyhedron.buildBox(collisionMatrix, mObjBox, true); // Build extruded polyList... VectorF vector = end - pos; sExtrudedPolyList.extrude(sBoxPolyhedron, vector); sExtrudedPolyList.setVelocity(mVelocity); sExtrudedPolyList.setCollisionList(&collisionList); CollisionWorkingList& rList = mConvex.getWorkingList(); CollisionWorkingList* pList = rList.wLink.mNext; while (pList != &rList) { if ((pList->mConvex->getObject()->getTypeMask() & mask) != 0) { Box3F convexBox = pList->mConvex->getBoundingBox(); if (testBox.isOverlapped(convexBox)) { pList->mConvex->getPolyList(&sExtrudedPolyList); } } pList = pList->wLink.mNext; } if (collisionList.getTime() < 1.0) { // Set to collision point F32 dt = time * collisionList.getTime(); pos += mVelocity * dt; time -= dt; // Pick the most resistant surface F32 bd = 0; const Collision* collision = 0; for (int c = 0; c < collisionList.getCount(); c++) { const Collision &cp = collisionList[c]; F32 dot = -mDot(mVelocity,cp.normal); if (dot > bd) { bd = dot; collision = &cp; } } if (collision && mDataBlock->sticky && collision->object->getTypeMask() & (STATIC_COLLISION_TYPEMASK)) { mVelocity.set(0, 0, 0); mAtRest = true; mAtRestCounter = 0; stickyNotify = true; mStickyCollisionPos = collision->point; mStickyCollisionNormal = collision->normal; break; } else { // Subtract out velocity into surface and friction if (collision) { VectorF fv = mVelocity + collision->normal * bd; F32 fvl = fv.len(); if (fvl) { F32 ff = bd * mDataBlock->friction; if (ff < fvl) { fv *= ff / fvl; fvl = ff; } } bd *= 1 + mDataBlock->elasticity; VectorF dv = collision->normal * (bd + 0.002); mVelocity += dv; mVelocity -= fv; // Keep track of what we hit contact = true; U32 typeMask = collision->object->getTypeMask(); if (!(typeMask & StaticObjectType)) nonStatic = true; if (isServerObject() && (typeMask & ShapeBaseObjectType)) { ShapeBase* col = static_cast<ShapeBase*>(collision->object); queueCollision(col,mVelocity - col->getVelocity()); } } } } else { pos = end; break; } } if (count == 3) { // Couldn't move... mVelocity.set(0, 0, 0); } } // If on the client, calculate delta for backstepping if (isGhost()) { delta.pos = pos; delta.posVec -= pos; delta.dt = 1; } // Update transform MatrixF mat = mObjToWorld; mat.setColumn(3,pos); Parent::setTransform(mat); enableCollision(); if (mCollisionObject) mCollisionObject->enableCollision(); updateContainer(); if ( mPhysicsRep ) mPhysicsRep->setTransform( mat ); // if (contact) { // Check for rest condition if (!nonStatic && mVelocity.len() < sAtRestVelocity) { mVelocity.x = mVelocity.y = mVelocity.z = 0; mAtRest = true; mAtRestCounter = 0; } // Only update the client if we hit a non-static shape or // if this is our final rest pos. if (nonStatic || mAtRest) setMaskBits(PositionMask); } // Collision callbacks. These need to be processed whether we hit // anything or not. if (!isGhost()) { SimObjectPtr<Item> safePtr(this); if (stickyNotify) { notifyCollision(); if(bool(safePtr)) onStickyCollision_callback( getIdString() ); } else notifyCollision(); // water if(bool(safePtr)) { if(!mInLiquid && mWaterCoverage != 0.0f) { mInLiquid = true; if ( !isGhost() ) mDataBlock->onEnterLiquid_callback( this, mWaterCoverage, mLiquidType.c_str() ); } else if(mInLiquid && mWaterCoverage == 0.0f) { mInLiquid = false; if ( !isGhost() ) mDataBlock->onLeaveLiquid_callback( this, mLiquidType.c_str() ); } } } }
void Turret::shoot (bool playerControlled, Player* targetPlayer) { if (data && data->isSustained == false) { if (data && data->projectile.type == -1) { if (!isGhost()) if (const char* script = scriptName("onFire")) Console->executef(2, script, scriptThis()); } else { float energy = getEnergy(); if (waitTime <= manager->getCurrentTime() && data && energy >= data->minGunEnergy && data->projectile.type != -1) { TMat3F muzzleTransform; getMuzzleTransform(0, &muzzleTransform); Projectile* bullet = createProjectile(data->projectile); if (!playerControlled && data->deflection) { static Random random; EulerF angles; muzzleTransform.angles (&angles); angles.x += (random.getFloat() - 0.5) * M_2PI * data->deflection; angles.z += (random.getFloat() - 0.5) * M_2PI * data->deflection; muzzleTransform.set (angles, muzzleTransform.p); } else if (playerControlled) { Point3F start = muzzleTransform.p; muzzleTransform = getEyeTransform (); aimedTransform (&muzzleTransform, start); muzzleTransform.p = start; } bullet->initProjectile (muzzleTransform, Point3F (0, 0, 0), getId()); if (bullet->isTargetable() == true) { if (targetPlayer != NULL) { if (GameBase* mo = targetPlayer->getMountObject()) bullet->setTarget(static_cast<ShapeBase*>(mo)); else bullet->setTarget(targetPlayer); } else if (playerControlled) { ShapeBase* pClosest = NULL; Point3F closeHisPos; float closestVal = -2.0f; SimSet::iterator itr; Point3F lookDir; getEyeTransform().getRow(1, &lookDir); lookDir.normalize(); SimContainerQuery collisionQuery; SimCollisionInfo info; collisionQuery.id = getId(); collisionQuery.type = -1; collisionQuery.mask = Projectile::csm_collisionMask; collisionQuery.detail = SimContainerQuery::DefaultDetail; collisionQuery.box.fMin = getEyeTransform().p; SimContainer* pRoot = (SimContainer*)manager->findObject(SimRootContainerId); SimSet* pSet = dynamic_cast<SimSet*>(manager->findObject(PlayerSetId)); AssertFatal(pSet != NULL, "No player set?"); for (itr = pSet->begin(); itr != pSet->end(); itr++) { Player* pPlayer = dynamic_cast<Player*>(*itr); if (!pPlayer || pPlayer->getVisibleToTeam(getTeam()) == false) continue; collisionQuery.box.fMax = pPlayer->getBoxCenter(); if (pRoot->findLOS(collisionQuery, &info, SimCollisionImageQuery::High) == true) { if (info.object != (SimObject*)pPlayer) continue; } Point3F hisPos = pPlayer->getBoxCenter(); hisPos -= getLinearPosition(); hisPos.normalize(); float prod = m_dot(hisPos, lookDir); if (prod > 0.0f && prod > closestVal) { closestVal = prod; pClosest = pPlayer; closeHisPos = hisPos; } } pSet = dynamic_cast<SimSet*>(manager->findObject(MoveableSetId)); AssertFatal(pSet != NULL, "No moveable set?"); for (itr = pSet->begin(); itr != pSet->end(); itr++) { if (((*itr)->getType() & VehicleObjectType) == 0) continue; ShapeBase* pObject = dynamic_cast<ShapeBase*>(*itr); if (pObject->getVisibleToTeam(getTeam()) == false) continue; collisionQuery.box.fMax = pObject->getBoxCenter(); if (pRoot->findLOS(collisionQuery, &info, SimCollisionImageQuery::High) == true) { if (info.object != (SimObject*)pObject) continue; } Point3F hisPos = pObject->getBoxCenter(); hisPos -= getLinearPosition(); hisPos.normalize(); float prod = m_dot(hisPos, lookDir); if (prod > 0.0f && prod > closestVal) { closestVal = prod; closeHisPos = hisPos; pClosest = pObject; } } // We need to find the current FOV, and take the percentage of // it specified in the .dat file for this turret. Only if the // do product is greater than this, do we allow the target to // be set... // float myFov = (fov / 2.0) * data->targetableFovRatio; float compCos = cos(myFov); if (compCos > 0.996f) // hack for single precision math. It's very compCos = 0.996; // hard to get more precise answers from the dot prod. if (pClosest != NULL && closestVal > compCos) bullet->setTarget(pClosest); } } if (data->maxGunEnergy) { float e; e = energy > data->maxGunEnergy ? data->maxGunEnergy : energy; float pofm = e / float(data->maxGunEnergy); bullet->setEnergy (e, pofm); energy -= e; setEnergy (energy); } SimGroup *grp = NULL; if(SimObject *obj = manager->findObject("MissionCleanup")) grp = dynamic_cast<SimGroup*>(obj); if(!manager->registerObject(bullet)) delete bullet; else { if(grp) grp->addObject(bullet); else manager->addObject(bullet); } waitTime = manager->getCurrentTime() + data->reloadDelay; if (animThread) { setFireThread (); animThread->SetPosition (0.0); } fireCount++; setMaskBits (ShootingMask); } } } else { if (data && data->projectile.type == -1) { if (!isGhost()) if (const char* script = scriptName("onFire")) Console->executef(2, script, scriptThis()); } else { float energy = getEnergy(); if (waitTime <= manager->getCurrentTime() && data && energy >= data->minGunEnergy && data->projectile.type != -1) { TMat3F muzzleTransform; getMuzzleTransform(0, &muzzleTransform); Projectile* bullet = createProjectile(data->projectile); if (!playerControlled && data->deflection) { static Random random; EulerF angles; muzzleTransform.angles (&angles); angles.x += (random.getFloat() - 0.5) * M_2PI * data->deflection; angles.z += (random.getFloat() - 0.5) * M_2PI * data->deflection; muzzleTransform.set (angles, muzzleTransform.p); } else if (playerControlled) { Point3F start = muzzleTransform.p; muzzleTransform = getEyeTransform (); aimedTransform (&muzzleTransform, start); muzzleTransform.p = start; } bullet->initProjectile (muzzleTransform, Point3F (0, 0, 0), getId()); AssertFatal(bullet->isSustained() == true, "Error, must be sustained bullet"); SimGroup *grp = NULL; if(SimObject *obj = manager->findObject("MissionCleanup")) grp = dynamic_cast<SimGroup*>(obj); if(!manager->registerObject(bullet)) delete bullet; else { if(grp) grp->addObject(bullet); else manager->addObject(bullet); } if (animThread) { setFireThread (); animThread->SetPosition (0.0); } fireCount++; setMaskBits (ShootingMask); m_fireState = Firing; m_beganState = wg->currentTime; m_pProjectile = bullet; m_pTarget = targetPlayer; if (m_pTarget) deleteNotify(m_pTarget); } } } }
Move HoverPodController::getMove(ShapeBase* obj) { Move retMove = NullMove; GameConnection* client = NULL; if(!Sim::findObject(mClientId, client)) return retMove; ShapeBase* control = client->getControlObject(); if(control) { Move cMove = client->lastReceivedMove(); Point3F v1, v2; control->getTransform().getColumn(0, &v1); control->getTransform().getColumn(1, &v2); Point3F pv = v1*cMove.x + v2*cMove.y; //pv = mDirection * mDot(pv, mDirection); obj->getTransform().getColumn(0, &v1); obj->getTransform().getColumn(1, &v2); retMove.x = mDot(v1, pv); retMove.y = mDot(v2, pv); } return retMove; #if 0 if(this->isServerObject() && this->isMounted()) { Move mMove = NullMove; ShapeBase* mount = this->getObjectMount(); if(mount->getType() & VehicleObjectType) { Vehicle* vehicle = (Vehicle*)mount; if(move && move->x != 0) { mMove.yaw = move->x; } else { Point3F zv; vehicle->getTransform().getColumn(2, &zv); zv.normalize(); Point3F m = vehicle->getRigid().angMomentum; //Point3F v = vehicle->getRigid().angVelocity; F32 dot = mDot(zv, m); //Con::printf("%f / %f %f %f / %f %f %f", dot, // m.x, m.y, m.z, v.x, v.y, v.z); mMove.yaw = dot / 50; } if(move) mMove.y = move->y; } else if(move) { Point3F v1, v2; this->getTransform().getColumn(0, &v1); this->getTransform().getColumn(1, &v2); Point3F pv = v1*move->x + v2*move->y; mount->getTransform().getColumn(0, &v1); mount->getTransform().getColumn(1, &v2); mMove.x = mDot(v1, pv); mMove.y = mDot(v2, pv); } mount->processTick(&mMove); } #endif
//---------------------------------------------------------------------------- /// Core rendering method for this control. /// /// This method scans through all the current client ShapeBase objects. /// If one is named, it displays the name and damage information for it. /// /// Information is offset from the center of the object's bounding box, /// unless the object is a PlayerObjectType, in which case the eye point /// is used. /// /// @param updateRect Extents of control. void afxGuiTextHud::onRender( Point2I, const RectI &updateRect) { // Background fill first if (mShowFill) GFX->getDrawUtil()->drawRectFill(updateRect, mFillColor.toColorI()); // Must be in a TS Control GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent()); if (!parent) return; // Must have a connection and control object GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn) return; GameBase * control = dynamic_cast<GameBase*>(conn->getControlObject()); if (!control) return; // Get control camera info MatrixF cam; Point3F camPos; VectorF camDir; conn->getControlCameraTransform(0,&cam); cam.getColumn(3, &camPos); cam.getColumn(1, &camDir); F32 camFovCos; conn->getControlCameraFov(&camFovCos); camFovCos = mCos(mDegToRad(camFovCos) / 2); // Visible distance info & name fading F32 visDistance = gClientSceneGraph->getVisibleDistance(); F32 visDistanceSqr = visDistance * visDistance; F32 fadeDistance = visDistance * mDistanceFade; // Collision info. We're going to be running LOS tests and we // don't want to collide with the control object. static U32 losMask = TerrainObjectType | TerrainLikeObjectType | ShapeBaseObjectType; if (!mEnableControlObjectOcclusion) control->disableCollision(); if (mLabelAllShapes) { // This section works just like GuiShapeNameHud and renders labels for // all the shapes. // All ghosted objects are added to the server connection group, // so we can find all the shape base objects by iterating through // our current connection. for (SimSetIterator itr(conn); *itr; ++itr) { ///if ((*itr)->getTypeMask() & ShapeBaseObjectType) ///{ ShapeBase* shape = dynamic_cast<ShapeBase*>(*itr); if ( shape ) { if (shape != control && shape->getShapeName()) { // Target pos to test, if it's a player run the LOS to his eye // point, otherwise we'll grab the generic box center. Point3F shapePos; if (shape->getTypeMask() & PlayerObjectType) { MatrixF eye; // Use the render eye transform, otherwise we'll see jittering shape->getRenderEyeTransform(&eye); eye.getColumn(3, &shapePos); } else { // Use the render transform instead of the box center // otherwise it'll jitter. MatrixF srtMat = shape->getRenderTransform(); srtMat.getColumn(3, &shapePos); } VectorF shapeDir = shapePos - camPos; // Test to see if it's in range F32 shapeDist = shapeDir.lenSquared(); if (shapeDist == 0 || shapeDist > visDistanceSqr) continue; shapeDist = mSqrt(shapeDist); // Test to see if it's within our viewcone, this test doesn't // actually match the viewport very well, should consider // projection and box test. shapeDir.normalize(); F32 dot = mDot(shapeDir, camDir); if (dot < camFovCos) continue; // Test to see if it's behind something, and we want to // ignore anything it's mounted on when we run the LOS. RayInfo info; shape->disableCollision(); SceneObject *mount = shape->getObjectMount(); if (mount) mount->disableCollision(); bool los = !gClientContainer.castRay(camPos, shapePos,losMask, &info); shape->enableCollision(); if (mount) mount->enableCollision(); if (!los) continue; // Project the shape pos into screen space and calculate // the distance opacity used to fade the labels into the // distance. Point3F projPnt; shapePos.z += mVerticalOffset; if (!parent->project(shapePos, &projPnt)) continue; F32 opacity = (shapeDist < fadeDistance)? 1.0: 1.0 - (shapeDist - fadeDistance) / (visDistance - fadeDistance); // Render the shape's name drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity); } } } } // This section renders all text added by afxGuiText effects. for (S32 i = 0; i < text_items.size(); i++) { HudTextSpec* spec = &text_items[i]; if (spec->text && spec->text[0] != '\0') { VectorF shapeDir = spec->pos - camPos; // do range test F32 shapeDist = shapeDir.lenSquared(); if (shapeDist == 0 || shapeDist > visDistanceSqr) continue; shapeDist = mSqrt(shapeDist); // Test to see if it's within our viewcone, this test doesn't // actually match the viewport very well, should consider // projection and box test. shapeDir.normalize(); F32 dot = mDot(shapeDir, camDir); if (dot < camFovCos) continue; // Test to see if it's behind something, and we want to // ignore anything it's mounted on when we run the LOS. RayInfo info; if (spec->obj) spec->obj->disableCollision(); bool los = !gClientContainer.castRay(camPos, spec->pos, losMask, &info); if (spec->obj) spec->obj->enableCollision(); if (!los) continue; // Project the shape pos into screen space. Point3F projPnt; if (!parent->project(spec->pos, &projPnt)) continue; // Calculate the distance opacity used to fade text into the distance. F32 opacity = (shapeDist < fadeDistance)? 1.0 : 1.0 - (shapeDist - fadeDistance) / (25.0f); if (opacity > 0.01f) drawName(Point2I((S32)projPnt.x, (S32)projPnt.y), spec->text, opacity, &spec->text_clr); } } // Restore control object collision if (!mEnableControlObjectOcclusion) control->enableCollision(); // Border last if (mShowFrame) GFX->getDrawUtil()->drawRect(updateRect, mFrameColor.toColorI()); reset(); }