/** Resolve collision with an immovable object Computes & applies the collision impulse needed to keep the body from penetrating the given surface. */ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal) { atRest = false; Point3F v,r; getOriginVector(p,&r); getVelocity(r,&v); F32 n = -mDot(v,normal); if (n >= 0.0f) { // Collision impulse, straight forward force stuff. F32 d = getZeroImpulse(r,normal); F32 j = n * (1.0f + restitution) * d; Point3F impulse = normal * j; // Friction impulse, calculated as a function of the // amount of force it would take to stop the motion // perpendicular to the normal. Point3F uv = v + (normal * n); F32 ul = uv.len(); if (ul) { uv /= -ul; F32 u = ul * getZeroImpulse(r,uv); j *= friction; if (u > j) u = j; impulse += uv * u; } // applyImpulse(r,impulse); } return true; }
bool PxSingleActor::prepRenderImage( SceneState *state, const U32 stateKey, const U32 startZone, const bool modifyBaseState ) { if ( !mShapeInstance || !state->isObjectRendered(this) ) return false; Point3F cameraOffset; getTransform().getColumn(3,&cameraOffset); cameraOffset -= state->getDiffuseCameraPosition(); F32 dist = cameraOffset.len(); if ( dist < 0.01f ) dist = 0.01f; F32 invScale = (1.0f/getMax(getMax(getScale().x,getScale().y),getScale().z)); dist *= invScale; S32 dl = mShapeInstance->setDetailFromDistance( state, dist ); if (dl<0) return false; renderObject( state ); return false; }
void Etherform::updateCameraPos(F32 delta) { // // Update 3rd person camera position. // F32 min,max; Point3F offset; MatrixF rot; this->getCameraParameters(&min,&max,&offset,&rot); Point3F vec = mCameraTargetPos - mCameraPos; F32 dist = vec.len(); if(dist == 0) { // Catch camera position up to its target position. mCameraPos = mCameraTargetPos; } else if(dist > max) { // Catch camera up to max allowed dist from target position. vec.normalize(); vec.neg(); mCameraPos = mCameraTargetPos + vec * max; } else { // Move camera pos towards its target pos. #if 0 F32 speed = mDataBlock->accelerationForce; speed *= 1 - (1/vec.lenSquared()); vec.normalize(); mCameraPos += vec * speed * delta; #else //F32 speedScale = this->getVelocity().len() / mDataBlock->accelerationForce; F32 speedScale = 4; //mDataBlock->accelerationForce / 2; F32 distScale = 1 - (1/vec.lenSquared()); vec *= speedScale * distScale * delta; if(vec.len() > dist) mCameraPos = mCameraTargetPos; else mCameraPos += vec; #endif } }
//---------------------------------------------------------------------------- void Item::updateWorkingCollisionSet(const U32 mask, const F32 dt) { // It is assumed that we will never accelerate more than 10 m/s for gravity... // Point3F scaledVelocity = mVelocity * dt; F32 len = scaledVelocity.len(); F32 newLen = len + (10 * dt); // Check to see if it is actually necessary to construct the new working list, // or if we can use the cached version from the last query. We use the x // component of the min member of the mWorkingQueryBox, which is lame, but // it works ok. bool updateSet = false; Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale()); F32 l = (newLen * 1.1) + 0.1; // from Convex::updateWorkingList convexBox.minExtents -= Point3F(l, l, l); convexBox.maxExtents += Point3F(l, l, l); // Check containment { if (mWorkingQueryBox.minExtents.x != -1e9) { if (mWorkingQueryBox.isContained(convexBox) == false) { // Needed region is outside the cached region. Update it. updateSet = true; } else { // We can leave it alone, we're still inside the cached region } } else { // Must update updateSet = true; } } // Actually perform the query, if necessary if (updateSet == true) { mWorkingQueryBox = convexBox; mWorkingQueryBox.minExtents -= Point3F(2 * l, 2 * l, 2 * l); mWorkingQueryBox.maxExtents += Point3F(2 * l, 2 * l, 2 * l); disableCollision(); if (mCollisionObject) mCollisionObject->disableCollision(); mConvex.updateWorkingList(mWorkingQueryBox, mask); if (mCollisionObject) mCollisionObject->enableCollision(); enableCollision(); } }
void CelAnimMesh::setCommonScale( Shape::Mesh & otherMesh ) { CelAnimMesh *potherMesh = dynamic_cast<CelAnimMesh *>(&otherMesh); AssertFatal(potherMesh, "TS::CelAnimMesh::setCommonScale: meshes not same type"); #if 0 // array of unpacked verts -- points only Point3F *unpackedVerts = new Point3F[fVerts.size()]; int v; for (v=0;v<fVerts.size();v++) fVerts[v].getPoint(unpackedVerts[v],fScale,fOrigin); Point3F *otherUnpackedVerts = new Point3F[potherMesh->fVerts.size()]; for (v=0;v<potherMesh->fVerts.size();v++) potherMesh->fVerts[v].getPoint(otherUnpackedVerts[v],potherMesh->fScale,potherMesh->fOrigin); // get minVert and maxVert for setting new fScale, fOrigin, and fRadius Point3F minVert = unpackedVerts[0]; Point3F maxVert = unpackedVerts[0]; for (v=1;v<fVerts.size();v++) { minVert.setMin( unpackedVerts[v] ); maxVert.setMax( unpackedVerts[v] ); } for (v=0;v<potherMesh->fVerts.size();v++) { minVert.setMin( otherUnpackedVerts[v] ); maxVert.setMax( otherUnpackedVerts[v] ); } // figure new fOrigin, fScale, and fRadius Point3F newOrigin = minVert; maxVert -= minVert; Point3F newScale( maxVert.x/255.0f, maxVert.y/255.0f, maxVert.z/255.0f); float newRadius = maxVert.len(); // re-pack this shapes verts int i; Point3F temp; for (i=0;i<fVerts.size();i++) fVerts[i].setPoint(unpackedVerts[i],newScale,newOrigin); fOrigin=newOrigin; fScale=newScale; fRadius=newRadius; // re-pack other shapes verts for (i=0;i<potherMesh->fVerts.size();i++) potherMesh->fVerts[i].setPoint(otherUnpackedVerts[i],newScale,newOrigin); potherMesh->fOrigin=fOrigin; potherMesh->fScale=newScale; potherMesh->fRadius=newRadius; delete [] unpackedVerts; delete [] otherUnpackedVerts; #endif }
void Point3NormalizeValidator::validateType(SimObject *object, void *typePtr) { Point3F *v = (Point3F *) typePtr; const F32 len = v->len(); if(!mIsEqual(len, 1.0f)) { consoleError(object, "Vector length must be %g", length); *v *= length / len; } }
bool WindEmitter::findBest( const Point3F& cameraPos, const VectorF& cameraDir, F32 viewDistance, U32 maxResults, WindEmitterList* results ) { PROFILE_START(WindEmitter_findBest); // Build a sphere from the camera point. SphereF cameraSphere; cameraSphere.center = cameraPos; cameraSphere.radius = viewDistance; // Collect the active spheres within the camera space and score them. WindEmitterList best; WindEmitterList::iterator iter = smAllEmitters.begin(); for ( ; iter != smAllEmitters.end(); iter++ ) { const SphereF& sphere = *(*iter); // Skip any spheres outside of our camera range or that are disabled. if ( !(*iter)->mEnabled || !cameraSphere.isIntersecting( sphere ) ) continue; // Simple score calculation... // // score = ( radius / distance to camera ) * dot( cameraDir, vector from camera to sphere ) // Point3F vect = sphere.center - cameraSphere.center; F32 dist = vect.len(); (*iter)->mScore = dist * sphere.radius; vect /= getMax( dist, 0.001f ); (*iter)->mScore *= mDot( vect, cameraDir ); best.push_back( *iter ); } // Sort the results by score! dQsort( best.address(), best.size(), sizeof(WindEmitter*), &WindEmitter::_sortByScore ); // Clip the results to the max requested. if ( best.size() > maxResults ) best.setSize( maxResults ); // Merge the results and return. results->merge( best ); PROFILE_END(); // WindEmitter_findBest return best.size() > 0; }
void Etherform::updateWorkingCollisionSet() { // First, we need to adjust our velocity for possible acceleration. It is assumed // that we will never accelerate more than 20 m/s for gravity, plus 10 m/s for // jetting, and an equivalent 10 m/s for jumping. We also assume that the // working list is updated on a Tick basis, which means we only expand our // box by the possible movement in that tick. Point3F scaledVelocity = mVelocity * TickSec; F32 len = scaledVelocity.len(); F32 newLen = len + (10.0f * TickSec); // Check to see if it is actually necessary to construct the new working list, // or if we can use the cached version from the last query. We use the x // component of the min member of the mWorkingQueryBox, which is lame, but // it works ok. bool updateSet = false; Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale()); F32 l = (newLen * 1.1f) + 0.1f; // from Convex::updateWorkingList const Point3F lPoint( l, l, l ); convexBox.minExtents -= lPoint; convexBox.maxExtents += lPoint; // Check containment if (mWorkingQueryBox.minExtents.x != -1e9f) { if (mWorkingQueryBox.isContained(convexBox) == false) // Needed region is outside the cached region. Update it. updateSet = true; } else { // Must update updateSet = true; } // Actually perform the query, if necessary if (updateSet == true) { const Point3F twolPoint( 2.0f * l, 2.0f * l, 2.0f * l ); mWorkingQueryBox = convexBox; mWorkingQueryBox.minExtents -= twolPoint; mWorkingQueryBox.maxExtents += twolPoint; disableCollision(); mConvex.updateWorkingList(mWorkingQueryBox, isGhost() ? sClientCollisionContactMask : sServerCollisionContactMask); enableCollision(); } }
void PxSingleActor::_onContact( NxActor *ourActor, NxActor *hitActor, SceneObject *hitObject, const Point3F &hitPoint, const Point3F &impactForce ) { if ( isGhost() ) return; String strHitPos = String::ToString( "%g %g %g", hitPoint.x, hitPoint.y, hitPoint.z ); String strImpactVec = String::ToString( "%g %g %g", impactForce.x, impactForce.y, impactForce.z ); String strImpactForce = String::ToString( "%g", impactForce.len() ); Con::executef( mDataBlock, "onCollision", getIdString(), hitObject ? hitObject->scriptThis() : "", strHitPos.c_str(), strImpactVec.c_str(), strImpactForce.c_str() ); }
// This is for panning the viewport camera. void GuiMaterialPreview::setTranslate(S32 modifier, F32 xstep, F32 ystep) { F32 transstep = (modifier & SI_SHIFT ? mTransStep : (mTransStep*mTranMult)); F32 nominalDistance = 20.0; Point3F vec = mCameraPos; vec -= mOrbitPos; transstep *= vec.len() / nominalDistance; if (modifier & SI_PRIMARY_CTRL) { mOrbitRelPos.x += ( xstep * transstep ); mOrbitRelPos.y += ( ystep * transstep ); } else { mOrbitRelPos.x += ( xstep * transstep ); mOrbitRelPos.z += ( ystep * transstep ); } }
void Lightning::scheduleThunder(Strike* newStrike) { AssertFatal(isClientObject(), "Lightning::scheduleThunder: server objects should not enter this version of the function"); // If no thunder sounds, don't schedule anything! if (mDataBlock->numThunders == 0) return; GameConnection* connection = GameConnection::getConnectionToServer(); if (connection) { MatrixF cameraMatrix; if (connection->getControlCameraTransform(0, &cameraMatrix)) { Point3F worldPos; cameraMatrix.getColumn(3, &worldPos); worldPos.x -= newStrike->xVal; worldPos.y -= newStrike->yVal; worldPos.z = 0.0f; F32 dist = worldPos.len(); F32 t = dist / 330.0f; // Ok, we need to schedule a random strike sound t secs in the future... // if (t <= 0.03f) { // If it's really close, just play it... U32 thunder = sgLightningRand.randI(0, mDataBlock->numThunders - 1); SFX->playOnce(mDataBlock->thunderSounds[thunder]); } else { Thunder* pThunder = new Thunder; pThunder->tRemaining = t; pThunder->next = mThunderListHead; mThunderListHead = pThunder; } } } }
void TSStatic::prepRenderImage( SceneRenderState* state ) { if( !mShapeInstance ) return; //WLE - Vince //Lod preloading GameConnection* connection = GameConnection::getConnectionToServer(); if (connection && !connection->didFirstRender) { TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); for (S32 i = mShapeInstance->getSmallestVisibleDL(); i >= 0; i-- ) { mShapeInstance->setCurrentDetail( i ); mShapeInstance->render( rdata ); } } Point3F cameraOffset; getRenderTransform().getColumn(3,&cameraOffset); cameraOffset -= state->getDiffuseCameraPosition(); F32 dist = cameraOffset.len(); if (dist < 0.01f) dist = 0.01f; if (mUseAlphaLod) { mAlphaLOD = 1.0f; if ((mAlphaLODStart < mAlphaLODEnd) && mAlphaLODStart > 0.1f) { if (mInvertAlphaLod) { if (dist <= mAlphaLODStart) { return; } if (dist < mAlphaLODEnd) { mAlphaLOD = ((dist - mAlphaLODStart) / (mAlphaLODEnd - mAlphaLODStart)); } } else { if (dist >= mAlphaLODEnd) { return; } if (dist > mAlphaLODStart) { mAlphaLOD -= ((dist - mAlphaLODStart) / (mAlphaLODEnd - mAlphaLODStart)); } } } } F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else mShapeInstance->setCurrentDetail( mForceDetail ); if ( mShapeInstance->getCurrentDetail() < 0 ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; if ( mMeshCulling ) { culler = state->getCullingFrustum(); MatrixF xfm( true ); xfm.scale( Point3F::One / getScale() ); xfm.mul( getRenderWorldTransform() ); xfm.mul( culler.getTransform() ); culler.setTransform( xfm ); rdata.setCuller( &culler ); } // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); mShapeInstance->animate(); if(mShapeInstance) { if (mUseAlphaLod) { mShapeInstance->setAlphaAlways(mAlphaLOD); S32 s = mShapeInstance->mMeshObjects.size(); for(S32 x = 0; x < s; x++) { mShapeInstance->mMeshObjects[x].visible = mAlphaLOD; } } } mShapeInstance->render( rdata ); if ( mRenderNormalScalar > 0 ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &TSStatic::_renderNormals ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
void terrTexGen( vertexType vtype, Point4F *clipmapMapping, const MatrixF &blockTransform, const Point3F &cameraPosition, LightInfo *light, SceneState * state) { PROFILE_SCOPE(Terrain_TexGen); SceneManager * sceneManager = state->getSceneManager(); Point3F relative; const F32 blockTexCoordScale = 1.0f / (TerrainRender::mCurrentBlock->getSquareSize() * TerrainBlock::BlockSize); // Apply texgen to the new verts... if (vtype == vertexTypeFullClipMapping) { for(U32 i=0; i<mCurVertex; i++) { mVertexStore[i].texCoord.x = mVertexStore[i].point.x * blockTexCoordScale; mVertexStore[i].texCoord.y = mVertexStore[i].point.y * blockTexCoordScale; } } else if (vtype == vertexTypeSingleTextureClipMapping) { // Compute the fixedfunction vert stuff now AssertFatal(clipmapMapping != NULL, "TerrBatch::end - vertexTypeSingleTextureClipMapping requires clipmapMapping variable!"); const F32 fadeConstant = 3.0f; const F32 blockTexCoordScale2 = blockTexCoordScale * clipmapMapping->z; for(U32 i=0; i<mCurVertex; i++) { mVertexStorePCNT[i].point = mVertexStore[i].point; mVertexStorePCNT[i].normal = mVertexStore[i].normal; mVertexStorePCNT[i].texCoord.x = mVertexStore[i].point.x * blockTexCoordScale2; mVertexStorePCNT[i].texCoord.y = mVertexStore[i].point.y * blockTexCoordScale2; relative.x = mVertexStorePCNT[i].texCoord.x - clipmapMapping->x; relative.y = mVertexStorePCNT[i].texCoord.y - clipmapMapping->y; relative.z = 0; // note: this uses 128.0f - instead of 255.0f - to hide some // transition artifacts at the edges (which are not visible // in the shader path due to its use of /2 in the vertex // shader and saturate(fade*2) in the pixel shader, which // allows sharp transitions to be interpolated more cleanly) mVertexStorePCNT[i].color.set(255, 255, 255, (U8)mClampF(128.0f - (relative.len() * (2.0f * fadeConstant) - (fadeConstant - 1.0f)) * 255.0f, 0.0f, 255.0f)); } } else if (vtype == vertexTypeDLight) { // Compute the fixedfunction vert stuff now AssertFatal(clipmapMapping != NULL, "TerrBatch::end - vertexTypeDLight requires clipmapMapping variable!"); AssertFatal(light != NULL, "TerrBatch::end - vertexTypeDLight requires light variable!"); AssertFatal(light->mRadius > 0, "TerrBatch::end - vertexTypeDLight requires light->mRadius > 0!"); const F32 blockTexCoordScale2 = blockTexCoordScale * clipmapMapping->z; const F32 heightOffset = sceneManager->getFogHeightOffset(); const F32 inverseHeightRange = sceneManager->getFogInvHeightRange(); const F32 inverseVisibleDistanceMod = 1.0f / sceneManager->getVisibleDistanceMod(); Point3F worldPoint; const F32 lightRadius = light->mRadius; const Point3F lightPosition = light->mPos; F32 intensity; const F32 inverseLightRadius = 1.0f / lightRadius; // note: this imitates sgLightingModel only very loosely for // performance reasons, it does look very similar to the shader path for(U32 i=0; i<mCurVertex; i++) { mVertexStorePCNTT[i].point = mVertexStore[i].point; mVertexStorePCNTT[i].normal = mVertexStore[i].normal; mVertexStorePCNTT[i].texCoord[0].x = mVertexStore[i].point.x * blockTexCoordScale2; mVertexStorePCNTT[i].texCoord[0].y = mVertexStore[i].point.y * blockTexCoordScale2; blockTransform.mulP(mVertexStore[i].point, &worldPoint); relative = worldPoint - cameraPosition; mVertexStorePCNTT[i].texCoord[1].x = 1.0 - (relative.len() * inverseVisibleDistanceMod); mVertexStorePCNTT[i].texCoord[1].y = (worldPoint.z - heightOffset) * inverseHeightRange; relative = worldPoint - lightPosition; intensity = getMax(1.0f - relative.len() * inverseLightRadius, 0.0f); intensity = 512.0f * intensity; if (intensity > 0) mVertexStorePCNTT[i].color.set((U8)getMin(light->mColor.red * intensity, 255.0f), (U8)getMin(light->mColor.green * intensity, 255.0f), (U8)getMin(light->mColor.blue * intensity, 255.0f), 255); else mVertexStorePCNTT[i].color.set(0, 0, 0, 255); } } else if (vtype == vertexTypeFog) { const F32 heightOffset = sceneManager->getFogHeightOffset(); const F32 inverseHeightRange = sceneManager->getFogInvHeightRange(); const F32 inverseVisibleDistanceMod = 1.0f / sceneManager->getVisibleDistanceMod(); Point3F worldPoint; for(U32 i=0; i<mCurVertex; i++) { mVertexStorePCNT[i].point = mVertexStore[i].point; mVertexStorePCNT[i].normal = mVertexStore[i].normal; blockTransform.mulP(mVertexStore[i].point, &worldPoint); relative = worldPoint - cameraPosition; mVertexStorePCNT[i].texCoord.x = 1.0 - (relative.len() * inverseVisibleDistanceMod); mVertexStorePCNT[i].texCoord.y = (worldPoint.z - heightOffset) * inverseHeightRange; mVertexStorePCNT[i].color.set(255, 255, 255, 255); } } // The only time 'vertexTypeDetail' is used is during a fixed-function detail pass. else if( vtype == vertexTypeDetail ) { // Get detail distance squared to save us from sqrt const F32 detailDistanceSquared = TerrainRender::mCurrentBlock->mDetailDistance * TerrainRender::mCurrentBlock->mDetailDistance; // Detail Brightness done via assignment of color values const U8 colorByte = mClamp( 255 * TerrainRender::mCurrentBlock->mDetailBrightness, 0, 255 ); Point3F worldPoint; for( U32 i = 0; i < mCurVertex; i++ ) { mVertexStorePCNT[i].point = mVertexStore[i].point; mVertexStorePCNT[i].normal = mVertexStore[i].normal; mVertexStorePCNT[i].texCoord.x = mVertexStore[i].point.x * blockTexCoordScale; mVertexStorePCNT[i].texCoord.y = mVertexStore[i].point.y * blockTexCoordScale; // Transform vertex into world space blockTransform.mulP( mVertexStore[i].point, &worldPoint ); relative = worldPoint - cameraPosition; // Alpha const F32 alpha = TerrainRender::mCurrentBlock->mDetailBrightness * ( 1.0f - ( relative.lenSquared() / detailDistanceSquared ) ); // Assign alpha value to vert so the detail texture blend fades mVertexStorePCNT[i].color.set( colorByte, colorByte, colorByte, mClamp( alpha * 255, 0, 255 ) ); } } else { for(U32 i=0; i<mCurVertex; i++) { mVertexStorePCNT[i].point = mVertexStore[i].point; mVertexStorePCNT[i].normal = mVertexStore[i].normal; mVertexStorePCNT[i].texCoord.x = mVertexStore[i].point.x * blockTexCoordScale; mVertexStorePCNT[i].texCoord.y = mVertexStore[i].point.y * blockTexCoordScale; mVertexStorePCNT[i].color.set(255, 255, 255, 255); } } }
void PlanetRenderImage::render(TSRenderContext &rc) { // A simple planet culling scheme would be to dot the line of sight // with the vector from the camera to the planet. This would eliminate // the length test of v below (after m_cross((Point3F)plane, vpNormal, &v)) GFXSurface *gfxSurface = rc.getSurface(); gfxSurface->setHazeSource(GFX_HAZE_NONE); gfxSurface->setShadeSource(GFX_SHADE_CONSTANT); gfxSurface->setAlphaSource(GFX_ALPHA_NONE); gfxSurface->setFillMode(GFX_FILL_TEXTURE); gfxSurface->setTransparency(FALSE); gfxSurface->setTexturePerspective(FALSE); gfxSurface->setConstantShade(1.0f); int textureHeight; gfxSurface->setTextureMap(texture); textureHeight = texture->height; TSCamera *camera = rc.getCamera(); TS::PointArray *pointArray = rc.getPointArray(); pointArray->reset(); pointArray->useIntensities(false); pointArray->useTextures(textCoord); pointArray->useTextures(true); pointArray->setVisibility( TS::ClipMask ); // find out how high the bitmap is at 100% as projected onto the viewport, // texel:pixel will be 1:1 at 640x480 //const RectF &worldVP = camera->getWorldViewport(); //const float h = textureHeight*((worldVP.upperL.y - worldVP.lowerR.y)/480.0f); //const float sz = 0.5*distance*(h/camera->getNearDist()); // find the position of the planet Point3F displacement = camera->getTCW().p; //displacement.z *= -(distance - visibleDistance)/visibleDistance; displacement.z = -displacement.z*(distance/(visibleDistance*1.5f)); Point3F pos = position; pos += displacement; // find the normal to the view plane in world coords Point3F v0(0.0f, 1.0f, 0.0f), vpNormal; m_mul(v0, (RMat3F)camera->getTCW(), &vpNormal); vpNormal.normalize(); // construct the plane that the camera, planet pos & celestial NP all // lie on PlaneF plane(pos, camera->getTCW().p, Point3F(displacement.x, displacement.y, displacement.z + distance)); // the cross product of the VP normal and the normal to the plane just // constructed is the up vector for the planet Point3F v; m_cross((Point3F)plane, vpNormal, &v); if (IsEqual(v.len(), 0.0f)) // planet is directly to the right or left of camera return; v.normalize(); // cross the up with the normal and we get the right vector Point3F u; m_cross(vpNormal, v, &u); u *= size; v *= size; TS::VertexIndexPair V[6]; Point3F ul = pos; ul -= u; ul += v; V[0].fVertexIndex = pointArray->addPoint(ul); V[0].fTextureIndex = 0; Point3F ur = pos; ur += u; ur += v; V[1].fVertexIndex = pointArray->addPoint(ur); V[1].fTextureIndex = 1; Point3F lr = pos; lr += u; lr -= v; V[2].fVertexIndex = pointArray->addPoint(lr); V[2].fTextureIndex = 2; Point3F ll = pos; ll -= u; ll -=v; V[3].fVertexIndex = pointArray->addPoint(ll); V[3].fTextureIndex = 3; if (gfxSurface->getCaps() & GFX_DEVCAP_SUPPORTS_CONST_ALPHA) gfxSurface->setZTest(GFX_NO_ZTEST); pointArray->drawPoly(4, V, 0); if (gfxSurface->getCaps() & GFX_DEVCAP_SUPPORTS_CONST_ALPHA) gfxSurface->setZTest(GFX_ZTEST_AND_WRITE); if(lensFlare) { TS::TransformedVertex vx; camera->transformProject(pos, &vx); bool vis = vx.fStatus & TS::TransformedVertex::Projected; lensFlare->setSunPos(vis, vx.fPoint, pos); } }
// warning: a work in progress...not tested yet bool CelAnimMesh::collideBox(int frameIndex, const TMat3F & trans, // from box to mesh space (box center to origin) const TMat3F & invTrans, // from mesh to box space const Point3F &radii, CollisionSurface & cs) const { cs; int hitface = -1; float hitDepth; Point3F hitNormal; float overlap; AssertFatal( fFrames.size() > 0, "Shape must have at least one frame." ); AssertFatal( frameIndex >= 0 && frameIndex < fFrames.size(), "TS::CelAnimMesh: frame index out of range" ); // get the frame struct: const Frame *frm = &fFrames[frameIndex]; int fv = frm->fFirstVert; const Point3F *pScale = &frm->fScale; const Point3F *pOrigin = &frm->fOrigin; int i; Point3F v[3],tv[3]; // tv is work space for m_polyOBox... for (i=0;i<fFaces.size();i++) { const Face & theFace = fFaces[i]; fVerts[theFace.fVIP[0].fVertexIndex+fv].getPoint(v[0],*pScale,*pOrigin); fVerts[theFace.fVIP[1].fVertexIndex+fv].getPoint(v[1],*pScale,*pOrigin); fVerts[theFace.fVIP[2].fVertexIndex+fv].getPoint(v[2],*pScale,*pOrigin); // build the normal Point3F normal; m_normal(v[0],v[1],v[2],normal); if (!m_polyOBox(radii,trans,invTrans,normal,v,tv,3,overlap)) continue; /* // build the normal Point3F normal; m_normal(v1,v2,v3,normal); float planeDist = m_dot(normal,v1); float negBoxDist = m_dot(normal,trans.p); // negative of dist of box from origin if (planeDist+negBoxDist<0.0f) // back-face from box center continue; // does the face's plane intersect the box float overlap; if (!m_planeOBox(bRadii,trans,normal,planeDist,overlap)) continue; Point3F tv1,tv2,tv3,tMin,tMax; m_mul(v1,invTrans,&tv1); m_mul(v2,invTrans,&tv2); m_mul(v3,invTrans,&tv3); tMin=tv1; tMin.setMin(tv2); tMin.setMin(tv3); tMax=tv1; tMax.setMax(tv2); tMax.setMax(tv3); if (tMin.x>bRadii.x) continue; if (tMax.x<-bRadii.x) continue; if (tMin.y>bRadii.y) continue; if (tMax.y<-bRadii.y) continue; if (tMin.z>bRadii.z) continue; if (tMax.z<-bRadii.z) continue; */ { // collision hitface = i; hitNormal = normal; hitDepth = overlap/normal.len(); } } hitNormal,hitDepth; return hitface!=-1; }
bool CelAnimMesh::collideSphere( int frameIndex, const Point3F & center, float radius, CollisionSurfaceList & csl) const { AssertFatal( fFrames.size() > 0, "Shape must have at least one frame." ); AssertFatal( frameIndex >= 0 && frameIndex < fFrames.size(), "TS::CelAnimMesh: frame index out of range" ); // get the frame struct: const Frame *frm = &fFrames[frameIndex]; int fv = frm->fFirstVert; const Point3F *pScale = &frm->fScale; const Point3F *pOrigin = &frm->fOrigin; bool gotHit=false; int i; Point3F v[3]; for (i=0;i<fFaces.size();i++) { const Face & theFace = fFaces[i]; fVerts[theFace.fVIP[0].fVertexIndex+fv].getPoint(v[0],*pScale,*pOrigin); fVerts[theFace.fVIP[1].fVertexIndex+fv].getPoint(v[1],*pScale,*pOrigin); fVerts[theFace.fVIP[2].fVertexIndex+fv].getPoint(v[2],*pScale,*pOrigin); // build the normal and distance from origin of face plane Point3F normal; m_normal(v[0],v[1],v[2],normal); float norm=normal.len(); if (norm==0.0f) // can happen if a face gets scrunched during animation continue; normal *= 1.0f/norm; // distance from origin of plane and parallel plane containing sphere center float dSphere = m_dot(normal,center); float dPlane = m_dot(normal,v[0]); float dist = dSphere-dPlane; if (dist<0) // ignore back facing planes continue; if (dist>=radius) // whole plane outside of sphere continue; // intersection of face plane and sphere is a circle on face plane // with center p (below) and radius circleRad (below) Point3F p; p.x = center.x - dist * normal.x; p.y = center.y - dist * normal.y; p.z = center.z - dist * normal.z; float circleRad2 = radius*radius - dist*dist; // square of circle radius // check to see if p is inside face (in case whole circle inside face) if (m_pointInTriangle(p,normal,v[0],v[1],v[2])) { // add entry to cil csl.increment(); CollisionSurface & info = csl.last(); info.surface=i; info.material = theFace.fMaterial; info.position = p; info.normal = normal; info.distance = dist; gotHit=true; continue; } // go through each edge, check to see if it intersects inside of circle // if so, add collision info for (int j=0;j<3;j++) { const Point3F & pivotVert = v[j]; Point3F edge; edge.x = v[(j+1) % 3].x - pivotVert.x; edge.y = v[(j+1) % 3].y - pivotVert.y; edge.z = v[(j+1) % 3].z - pivotVert.z; Point3F radialLine; radialLine.x = p.x - pivotVert.x; radialLine.y = p.y - pivotVert.y; radialLine.z = p.z - pivotVert.z; float edgeLen=edge.len(); if (edgeLen==0.0f) continue; edge *= 1.0f/edgeLen; // get length of projection of radial line onto edge line float projRadialToEdgeDist = m_dot(radialLine,edge); // find point at which perp. to edge from circle center hits edge line Point3F intPoint; intPoint.x = pivotVert.x + projRadialToEdgeDist * edge.x; intPoint.y = pivotVert.y + projRadialToEdgeDist * edge.y; intPoint.z = pivotVert.z + projRadialToEdgeDist * edge.z; float distToIntersect2 = (p.x-intPoint.x)*(p.x-intPoint.x) + (p.y-intPoint.y)*(p.y-intPoint.y) + (p.z-intPoint.z)*(p.z-intPoint.z); // is whole line outside circle if (distToIntersect2>circleRad2) continue; // length of half-cord formed by edge line // float halfcord = sqrt(circleRad2 - distToIntersect2); float halfcord2 = circleRad2 - distToIntersect2; // check to see if line lands inside of circle // if ( (projRadialToEdgeDist < 0.0f-halfcord) || // (projRadialToEdgeDist > halfcord+edgeLen) ) // continue; if (projRadialToEdgeDist < 0.0f) { if (projRadialToEdgeDist*projRadialToEdgeDist>halfcord2) continue; } else if (projRadialToEdgeDist>edgeLen) { float tmpF = projRadialToEdgeDist-edgeLen; if (tmpF*tmpF>halfcord2) continue; } // we know we hit now... // where exactly did we hit, shift intersect point onto edge to form hitPoint if (projRadialToEdgeDist < 0.0f) projRadialToEdgeDist = 0.0f; else if (projRadialToEdgeDist > edgeLen) projRadialToEdgeDist = edgeLen; Point3F hitPoint; hitPoint.x = pivotVert.x + projRadialToEdgeDist * edge.x; hitPoint.y = pivotVert.y + projRadialToEdgeDist * edge.y; hitPoint.z = pivotVert.z + projRadialToEdgeDist * edge.z; // add entry to cil csl.increment(); CollisionSurface & info = csl.last(); info.surface=i; info.material = theFace.fMaterial; info.position = hitPoint; info.normal = normal; info.distance = dist; gotHit=true; break; } } return gotHit; }
bool CelAnimMesh::collideTube( int frameIndex, const Point3F & a, const Point3F &b, float radius, CollisionSurface & cs, float minTime) const { minTime; // hitTime holds the current smallest... float hitTime = cs.time; int hitFace = -1; Point3F hitPoint; AssertFatal( fFrames.size() > 0, "Shape must have at least one frame." ); AssertFatal( frameIndex >= 0 && frameIndex < fFrames.size(), "TS::CelAnimMesh: frame index out of range" ); // get the frame struct: const Frame *frm = &fFrames[frameIndex]; int fv = frm->fFirstVert; const Point3F *pScale = &frm->fScale; const Point3F *pOrigin = &frm->fOrigin; Point3F tubeVect; tubeVect.x = b.x - a.x; tubeVect.y = b.y - a.y; tubeVect.z = b.z - a.z; float tubeLen = tubeVect.len(); float invTubeLen = 1.0f/tubeLen; // tubeVect will hold unit length vector pointing down tube tubeVect *= invTubeLen; float vectDotA = m_dot(tubeVect,a); // inverse radius squared for edgeInTube routine float invRadius2 = 1.0f / (radius*radius); int i; workVerts.setSize(fnVertsPerFrame); workRs.setSize(fnVertsPerFrame); workTs.setSize(fnVertsPerFrame); bool gotNormal; for (i=0;i<fFaces.size();i++) { const Face & theFace = fFaces[i]; int idx1 = theFace.fVIP[0].fVertexIndex; int idx2 = theFace.fVIP[1].fVertexIndex; int idx3 = theFace.fVIP[2].fVertexIndex; Point3F &v1=workVerts[idx1]; Point3F &v2=workVerts[idx2]; Point3F &v3=workVerts[idx3]; Point3F &R1=workRs[idx1]; Point3F &R2=workRs[idx2]; Point3F &R3=workRs[idx3]; float &t1=workTs[idx1]; float &t2=workTs[idx2]; float &t3=workTs[idx3]; if (!(v1Recycled&faceReuseFlags[i])) { fVerts[idx1+fv].getPoint(v1,*pScale,*pOrigin); // distance of vertex down the tube t1 = m_dot(v1,tubeVect) - vectDotA; // projection of vertex onto tube cross-section (centered on origin) R1.x = v1.x - a.x - t1 * tubeVect.x; R1.y = v1.y - a.y - t1 * tubeVect.y; R1.z = v1.z - a.z - t1 * tubeVect.z; } if (!(v2Recycled&faceReuseFlags[i])) { fVerts[idx2+fv].getPoint(v2,*pScale,*pOrigin); // distance of vertex down the tube t2 = m_dot(v2,tubeVect) - vectDotA; // projection of vertex onto tube cross-section (centered on origin) R2.x = v2.x - a.x - t2 * tubeVect.x; R2.y = v2.y - a.y - t2 * tubeVect.y; R2.z = v2.z - a.z - t2 * tubeVect.z; } if (!(v3Recycled&faceReuseFlags[i])) { fVerts[idx3+fv].getPoint(v3,*pScale,*pOrigin); // distance of vertex down the tube t3 = m_dot(v3,tubeVect) - vectDotA; // projection of vertex onto tube cross-section (centered on origin) R3.x = v3.x - a.x - t3 * tubeVect.x; R3.y = v3.y - a.y - t3 * tubeVect.y; R3.z = v3.z - a.z - t3 * tubeVect.z; } bool gotHit=false; if (!(e1Recycled&faceReuseFlags[i])) { if (t1<=t2) gotHit = edgeInTube(R1,R2,t1,t2,radius,invRadius2,invTubeLen,hitTime,hitPoint); else gotHit = edgeInTube(R2,R1,t2,t1,radius,invRadius2,invTubeLen,hitTime,hitPoint); } if (!(e2Recycled&faceReuseFlags[i])) { if (t2<=t3) gotHit |= edgeInTube(R2,R3,t2,t3,radius,invRadius2,invTubeLen,hitTime,hitPoint); else gotHit |= edgeInTube(R3,R2,t3,t2,radius,invRadius2,invTubeLen,hitTime,hitPoint); } if (!(e3Recycled&faceReuseFlags[i])) { if (t3<=t1) gotHit |= edgeInTube(R3,R1,t3,t1,radius,invRadius2,invTubeLen,hitTime,hitPoint); else gotHit |= edgeInTube(R1,R3,t1,t3,radius,invRadius2,invTubeLen,hitTime,hitPoint); } if (gotHit) { hitPoint.x += tubeLen * hitTime * tubeVect.x + a.x; hitPoint.y += tubeLen * hitTime * tubeVect.y + a.y; hitPoint.z += tubeLen * hitTime * tubeVect.z + a.z; hitFace=i; gotNormal=false; } // now check if tube goes through center of face w/o hitting any edges if (m_pointInTriangle(Point3F(0.0f,0.0f,0.0f),tubeVect,R1,R2,R3)) { // build the normal Point3F normal; m_normal(v1,v2,v3,normal); // now we need to find hitTime float d = m_dot(normal,v3); // distance of plane from origin float denom = m_dot(normal,tubeVect) * tubeLen; if (denom>=0.0f) // back face, we can ignore continue; float absT = d - m_dot(normal,a); if (absT<=hitTime*denom) // denom is neg. continue; // ok, a real collision, set ci variables... hitTime=absT/denom; hitFace=i; cs.normal=normal; gotNormal=true; hitPoint.x = a.x + hitTime * tubeLen * tubeVect.x; hitPoint.y = a.y + hitTime * tubeLen * tubeVect.y; hitPoint.z = a.z + hitTime * tubeLen * tubeVect.z; } } if (hitFace>=0) { const Face & theFace = fFaces[hitFace]; if (!gotNormal) { Point3F &v1=workVerts[theFace.fVIP[0].fVertexIndex]; Point3F &v2=workVerts[theFace.fVIP[1].fVertexIndex]; Point3F &v3=workVerts[theFace.fVIP[2].fVertexIndex]; // build the normal Point3F v13,v23; v13.x = v1.x-v3.x; v13.y = v1.y-v3.y; v13.z = v1.z-v3.z; v23.x = v2.x-v3.x; v23.y = v2.y-v3.y; v23.z = v2.z-v3.z; m_cross(v23,v13,&cs.normal); } cs.material=theFace.fMaterial; cs.surface=hitFace; cs.time=hitTime; cs.position=hitPoint; // cs.distance ?? return true; } return false; }
void TSStatic::prepRenderImage( SceneRenderState* state ) { if( !mShapeInstance ) return; Point3F cameraOffset; getRenderTransform().getColumn(3,&cameraOffset); cameraOffset -= state->getDiffuseCameraPosition(); F32 dist = cameraOffset.len(); if (dist < 0.01f) dist = 0.01f; if (mUseAlphaFade) { mAlphaFade = 1.0f; if ((mAlphaFadeStart < mAlphaFadeEnd) && mAlphaFadeStart > 0.1f) { if (mInvertAlphaFade) { if (dist <= mAlphaFadeStart) { return; } if (dist < mAlphaFadeEnd) { mAlphaFade = ((dist - mAlphaFadeStart) / (mAlphaFadeEnd - mAlphaFadeStart)); } } else { if (dist >= mAlphaFadeEnd) { return; } if (dist > mAlphaFadeStart) { mAlphaFade -= ((dist - mAlphaFadeStart) / (mAlphaFadeEnd - mAlphaFadeStart)); } } } } F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); // If we're currently rendering our own reflection we // don't want to render ourselves into it. if ( mCubeReflector.isRendering() ) return; if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else mShapeInstance->setCurrentDetail( mForceDetail ); if ( mShapeInstance->getCurrentDetail() < 0 ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); if ( mCubeReflector.isEnabled() ) rdata.setCubemap( mCubeReflector.getCubemap() ); // Acculumation rdata.setAccuTex(mAccuTex); // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; if ( mMeshCulling ) { culler = state->getCullingFrustum(); MatrixF xfm( true ); xfm.scale( Point3F::One / getScale() ); xfm.mul( getRenderWorldTransform() ); xfm.mul( culler.getTransform() ); culler.setTransform( xfm ); rdata.setCuller( &culler ); } // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() ) { RenderPassManager *pass = state->getRenderPass(); OccluderRenderInst *ri = pass->allocInst<OccluderRenderInst>(); ri->type = RenderPassManager::RIT_Occluder; ri->query = mCubeReflector.getOcclusionQuery(); mObjToWorld.mulP( mObjBox.getCenter(), &ri->position ); ri->scale.set( mObjBox.getExtents() ); ri->orientation = pass->allocUniqueXform( mObjToWorld ); ri->isSphere = false; state->getRenderPass()->addInst( ri ); } mShapeInstance->animate(); if(mShapeInstance) { if (mUseAlphaFade) { mShapeInstance->setAlphaAlways(mAlphaFade); S32 s = mShapeInstance->mMeshObjects.size(); for(S32 x = 0; x < s; x++) { mShapeInstance->mMeshObjects[x].visible = mAlphaFade; } } } mShapeInstance->render( rdata ); if ( mRenderNormalScalar > 0 ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &TSStatic::_renderNormals ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
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; }
bool xDistributedPoint3F::updateValue(Point3F value,xTimeType currentTime) { mLastTime = mCurrentTime; mCurrentTime = currentTime; mLastDeltaTime = mCurrentTime - mLastTime; mLastValue = mCurrentValue; mCurrentValue = value; mDifference = mCurrentValue - mLastValue; mThresoldTicker +=mLastDeltaTime; float lengthDiff = fabsf(mDifference.len()); float timeDiffMs = ((float)mThresoldTicker) / 1000.f; int flags = getFlags(); flags =E_DP_OK; bool result = false; if (this->getPropertyInfo()->mPredictionType == E_PTYPE_PREDICTED) { if (lengthDiff > getPredictionSettings()->getMinDifference() ) { if (mThresoldTicker2 > getPredictionSettings()->getMinSendTime()) { flags =E_DP_NEEDS_SEND; result = true ; //xLogger::xLog(ELOGINFO,XL_START,"mThresoldTicker2: %f",mThresoldTicker2); } } Point3F serverDiff = mCurrentValue-mLastServerValue ; if ( fabsf( serverDiff.len()) > getPredictionSettings()->getMinDifference() ) { if (mThresoldTicker2 > (getPredictionSettings()->getMinSendTime() * 0.2f) ) { flags =E_DP_NEEDS_SEND; result = true ; //xLogger::xLog(ELOGINFO,XL_START,"mThresoldTicker2: %f",mThresoldTicker2); } } if (mThresoldTicker2 > getPredictionSettings()->getMinSendTime()) { mThresoldTicker2 = 0 ; mThresoldTicker = 0; } } if (getPropertyInfo()->mPredictionType == E_PTYPE_RELIABLE) { flags =E_DP_NEEDS_SEND; result = true ; mLastValue = value; mCurrentValue = value; } setFlags(flags); return result; }
void TSStatic::prepRenderImage( SceneRenderState* state ) { if( !mShapeInstance ) return; Point3F cameraOffset; getRenderTransform().getColumn(3,&cameraOffset); cameraOffset -= state->getDiffuseCameraPosition(); F32 dist = cameraOffset.len(); if (dist < 0.01f) dist = 0.01f; F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else mShapeInstance->setCurrentDetail( mForceDetail ); if ( mShapeInstance->getCurrentDetail() < 0 ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; if ( mMeshCulling ) { culler = state->getCullingFrustum(); MatrixF xfm( true ); xfm.scale( Point3F::One / getScale() ); xfm.mul( getRenderWorldTransform() ); xfm.mul( culler.getTransform() ); culler.setTransform( xfm ); rdata.setCuller( &culler ); } // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); mShapeInstance->animate(); mShapeInstance->render( rdata ); if ( mRenderNormalScalar > 0 ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &TSStatic::_renderNormals ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
bool Player::initResources(GameBase::GameBaseData *in_data) { data = dynamic_cast<PlayerData *>(in_data); if(!Parent::initResources(in_data)) return false; updateImageMass(); setDrag(data->drag); setDensity(data->density); int rnode = image.shape->getShape().findNode("dummyalways root"); const TMat3F& rmat = image.shape->getTransform(rnode); image.shape->insertOverride("lowerback",0,&PlayerViewOverride); image.shape->insertOverride("lowerback",1,const_cast<TMat3F*>(&rmat)); image.shape->setOverride(2); // myThread = createThread (0); viewThread = Parent::createThread(0); viewThread->setPriority(-1); looksSequence = viewThread->GetSequenceIndex("looks"); crouchLooksSequence = viewThread->GetSequenceIndex("crouch looks"); if(crouchLooksSequence == -1) crouchLooksSequence = looksSequence; AssertFatal(looksSequence != -1, "DOH!"); viewThread->SetSequence( looksSequence, 0.0 ); damageThread = 0; int i; for (i = 0; i < Player::NUM_ANIMS; i ++) { animIndex[i] = myThread->GetSequenceIndex((char *) data->animData[i].name); if(animIndex[i] == -1) animIndex[i] = 0; } Point3F pos; clearAnimTransform (); for (int j = 0; j < Player::NUM_ANIMS; j ++) { if((j >= ANIM_MOVE_FIRST && j <= ANIM_MOVE_LAST) || (j >= ANIM_CROUCH_MOVE_FIRST && j <= ANIM_CROUCH_MOVE_LAST)) { myThread->setTimeScale(1.0); myThread->SetSequence(animIndex[j]); myThread->AdvanceTime(1.0); myThread->UpdateSubscriberList(); image.shape->animateRoot(); pos = getAnimTransform(); offsetList[j].dist = pos.len(); offsetList[j].dir = pos; if(offsetList[j].dist >= 0.1) { if (data->animData[j].direction <= 0) offsetList[j].dir *= -1 / offsetList[j].dist; else offsetList[j].dir *= 1 / offsetList[j].dist; } clearAnimTransform(); offsetList[j].hasOffset = true; } else offsetList[j].hasOffset = false; myThread->SetSequence(0); } if(currentAnimation != -1) { // it's a death animation: set it to the end myThread->SetSequence(animIndex[currentAnimation]); if (data->animData[currentAnimation].direction > 0) myThread->SetPosition (0.99f); else myThread->SetPosition (0); pickNewAnimation = false; } delete flameImage.shape; flameImage.shape = 0; flameThread = 0; if (isGhost()) { char name[256]; strcpy(name, data->flameShapeName); strcat(name, ".dts"); ResourceManager *rm = SimResource::get(manager); Resource<TSShape> shape = rm->load(name, true); if(bool(shape)) { flameImage.shape = new TSShapeInstance(shape, *rm); flameThread = flameImage.shape->CreateThread(); flameThread->setTimeScale(1.0f); flameThread->SetSequence("activation"); } } // Container & Collision boundingBox.fMin.x = -data->boxWidth; boundingBox.fMin.y = -data->boxDepth; boundingBox.fMin.z = 0; boundingBox.fMax.x = data->boxWidth; boundingBox.fMax.y = data->boxDepth; boundingBox.fMax.z = data->boxNormalHeight; collisionImage.bbox.fMin = boundingBox.fMin; collisionImage.bbox.fMax = boundingBox.fMax; collisionImage.crouchBox.fMin = boundingBox.fMin; collisionImage.crouchBox.fMax = boundingBox.fMax; setBoundingBox (); collisionImage.sphere.radius = (collisionImage.bbox.fMax.z - collisionImage.bbox.fMin.z) / 2; collisionImage.sphere.center = Point3F(0.0f,0.0f, collisionImage.sphere.radius); collisionImage.shapeInst = image.shape; collisionImage.collisionDetail = 0; chaseNode = image.shape->getShape().findNode ("dummyalways chasecam"); eyeNode = image.shape->getNodeAtCurrentDetail("dummy eye"); // Resolve all the mount node indexes. for(i = 0; i < MaxMountPoints; i++) { image.shape->setDetailLevel(0); mountNode[i] = image.shape->getNodeAtCurrentDetail(NodeMountName[i]); // HACK Alert! // Lower detail nodes are patch to reference the same // transform as the highest detail. TS::ShapeInstance::NodeInstance *node = image.shape->getNode(mountNode[i]); for (int d = 1; d < image.shape->getShape().fDetails.size(); d++) { image.shape->setDetailLevel(d); int dn = image.shape->getNodeAtCurrentDetail(NodeMountName[i]); if (dn != -1) image.shape->getNode(dn)->fpTransform = node->fpTransform; } } image.shape->setDetailLevel(0); // Update initial state of images transfered from the server. for (i = 0; i < MaxItemImages; i++) { ItemImageEntry& itemImage = itemImageList[i]; if (itemImage.state == ItemImageEntry::Fire) setImageState(i,ItemImageEntry::Fire); } return true; }