//----------------------------------------------------------------------------- // Computes the spheremap color at a particular (x,y) texcoord //----------------------------------------------------------------------------- static void CalcSphereColor( SphereCalc_t *pCalc, float x, float y ) { Vector normal; float flRadiusSq = x*x + y*y; if (flRadiusSq > pCalc->m_flRadiusSq) { // Force a glancing reflection normal.Init( 0, 1, 0 ); } else { // Compute the z distance based on x*x + y*y + z*z = r*r float z = sqrt( pCalc->m_flRadiusSq - flRadiusSq ); // Here's the untransformed surface normal normal.Init( x, y, z ); normal *= pCalc->m_flOORadius; } // Transform the normal based on the actual view direction TransformNormal( pCalc, normal ); // Compute the reflection vector (full spheremap solution) // R = 2 * (N dot L)N - L Vector vecReflect; float nDotL = DotProduct( normal, pCalc->m_vecLookDir ); VectorMA( pCalc->m_vecLookDir, -2.0f * nDotL, normal, vecReflect ); vecReflect *= -1.0f; int iFace = CalcFaceIndex( vecReflect ); CalcColor( pCalc, iFace, vecReflect, pCalc->m_pColor ); }
void Transformation(const Real O[restrict], const Real scale[restrict], const Real angle[restrict], const Real offset[restrict], Polyhedron *poly) { const RealVec Sin = {sin(angle[X]), sin(angle[Y]), sin(angle[Z])}; const RealVec Cos = {cos(angle[X]), cos(angle[Y]), cos(angle[Z])}; const Real rotate[DIMS][DIMS] = { /* point rotation matrix */ {Cos[Y]*Cos[Z], -Cos[X]*Sin[Z]+Sin[X]*Sin[Y]*Cos[Z], Sin[X]*Sin[Z]+Cos[X]*Sin[Y]*Cos[Z]}, {Cos[Y]*Sin[Z], Cos[X]*Cos[Z]+Sin[X]*Sin[Y]*Sin[Z], -Sin[X]*Cos[Z]+Cos[X]*Sin[Y]*Sin[Z]}, {-Sin[Y], Sin[X]*Cos[Y], Cos[X]*Cos[Y]}}; const Real invrot[DIMS][DIMS] = { /* inverse rotation matrix */ {rotate[0][0], rotate[1][0], rotate[2][0]}, {rotate[0][1], rotate[1][1], rotate[2][1]}, {rotate[0][2], rotate[1][2], rotate[2][2]}}; const Real num = 1.0 / sqrt(2.0); const Real axe[6][DIMS] = { /* direction vector of axis xx, yy, zz, xy, yz, zx */ {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {num, num, 0.0}, {0.0, num, num}, {num, 0.0, num}}; RealVec axis = {0.0}; /* direction vector of axis in rotated frame */ Real I[6] = {0.0}; /* inertia tensor after rotation */ /* transforming vertex and build the new bounding box */ for (int s = 0; s < DIMS; ++s) { poly->box[s][MIN] = FLT_MAX; poly->box[s][MAX] = FLT_MIN; } TransformVertex(O, scale, rotate, offset, poly->box, poly->vertN, poly->v); /* transforming normal assuming pure rotation and translation */ TransformNormal(rotate, poly->faceN, poly->Nf); TransformNormal(rotate, poly->edgeN, poly->Ne); TransformNormal(rotate, poly->vertN, poly->Nv); /* transform inertial tensor */ for (int n = 0; n < 6; ++n) { axis[X] = Dot(invrot[X], axe[n]); axis[Y] = Dot(invrot[Y], axe[n]); axis[Z] = Dot(invrot[Z], axe[n]); I[n] = TransformInertia(axis, poly->I); } poly->I[X][X] = I[0]; poly->I[X][Y] = -I[3]; poly->I[X][Z] = -I[5]; poly->I[Y][X] = -I[3]; poly->I[Y][Y] = I[1]; poly->I[Y][Z] = -I[4]; poly->I[Z][X] = -I[5]; poly->I[Z][Y] = -I[4]; poly->I[Z][Z] = I[2]; /* centroid should be transformed at last */ Real Oc[1][DIMS] = {{poly->O[X], poly->O[Y], poly->O[Z]}}; TransformVertex(O, scale, rotate, offset, poly->box, 1, Oc); poly->O[X] = Oc[0][X]; poly->O[Y] = Oc[0][Y]; poly->O[Z] = Oc[0][Z]; return; }
float Trans_Mesh::Ray_Tri_Intersect(const vec3& rayorig, const vec3& raydir, mat4& world, uint16_t startindex, uint16_t numindices) const{ world.inverse(); vec3 org(rayorig*world), di(raydir);// transform these to the mesh's space so the checks are in object space, not world space TransformNormal(di, world); // do all checks in OBJECT SPACE!!! di*=20000.0f;//make sure the ray is long enough return RayTriangleIntersect(org, di, &Vertices[0], &Indices[startindex],numindices); }
float Animated_Mesh::Ray_BV_Intersect(const vec3& rayorig, const vec3& raydir) { mat4 inverseW(GetWorld()); inverseW.inverse(); vec3 org(rayorig*inverseW), di(raydir);// transform these to the mesh's space so the checks are in object space, not world space TransformNormal(di, inverseW); // do all checks in OBJECT SPACE!!! di*=20000.0f;//make sure the ray is long enough return Bounding_Volume.RayIntersect(org, di); }
float Animated_Mesh::Ray_Tri_Intersect(const vec3& rayorig, const vec3& raydir) { mat4 inverseW(GetWorld()); inverseW.inverse(); vec3 org(rayorig*inverseW), di(raydir);// transform these to the mesh's space so the checks are in object space, not world space TransformNormal(di, inverseW); // do all checks in OBJECT SPACE!!! di*=20000.0f;//make sure the ray is long enough if(Bounding_Volume.RayIntersect(org, di) == INFINITY) return INFINITY;// did not hit the aabb, therefore, we did not hit the object if(IB.Stride == 4){ return RayTriangleIntersect(org, di, &Vertices[0], reinterpret_cast<const uint32_t*>(&Indices[0]),Indices.size()/2); } else { return RayTriangleIntersect(org, di, &Vertices[0],&Indices[0],Indices.size()); } }
bool Unit::InsideCollideTree( Unit *smaller, QVector &bigpos, Vector &bigNormal, QVector &smallpos, Vector &smallNormal, bool bigasteroid, bool smallasteroid ) { if (smaller->colTrees == NULL || this->colTrees == NULL) return false; if (hull < 0) return false; if (smaller->colTrees->usingColTree() == false || this->colTrees->usingColTree() == false) return false; csOPCODECollider::ResetCollisionPairs(); Unit *bigger = this; csReversibleTransform bigtransform( bigger->cumulative_transformation_matrix ); csReversibleTransform smalltransform( smaller->cumulative_transformation_matrix ); smalltransform.SetO2TTranslation( csVector3( smaller->cumulative_transformation_matrix.p -bigger->cumulative_transformation_matrix.p ) ); bigtransform.SetO2TTranslation( csVector3( 0, 0, 0 ) ); //we're only gonna lerp the positions for speed here... gahh! // Check for shield collisions here prior to checking for mesh on mesh or ray collisions below. csOPCODECollider *tmpCol = smaller->colTrees->colTree( smaller, bigger->GetWarpVelocity() ); if ( tmpCol && ( tmpCol->Collide( *bigger->colTrees->colTree( bigger, smaller->GetWarpVelocity() ), &smalltransform, &bigtransform ) ) ) { csCollisionPair *mycollide = csOPCODECollider::GetCollisions(); unsigned int numHits = csOPCODECollider::GetCollisionPairCount(); if (numHits) { smallpos.Set( (mycollide[0].a1.x+mycollide[0].b1.x+mycollide[0].c1.x)/3.0f, (mycollide[0].a1.y+mycollide[0].b1.y+mycollide[0].c1.y)/3.0f, (mycollide[0].a1.z+mycollide[0].b1.z+mycollide[0].c1.z)/3.0f ); smallpos = Transform( smaller->cumulative_transformation_matrix, smallpos ); bigpos.Set( (mycollide[0].a2.x+mycollide[0].b2.x+mycollide[0].c2.x)/3.0f, (mycollide[0].a2.y+mycollide[0].b2.y+mycollide[0].c2.y)/3.0f, (mycollide[0].a2.z+mycollide[0].b2.z+mycollide[0].c2.z)/3.0f ); bigpos = Transform( bigger->cumulative_transformation_matrix, bigpos ); csVector3 sn, bn; sn.Cross( mycollide[0].b1-mycollide[0].a1, mycollide[0].c1-mycollide[0].a1 ); bn.Cross( mycollide[0].b2-mycollide[0].a2, mycollide[0].c2-mycollide[0].a2 ); sn.Normalize(); bn.Normalize(); smallNormal.Set( sn.x, sn.y, sn.z ); bigNormal.Set( bn.x, bn.y, bn.z ); smallNormal = TransformNormal( smaller->cumulative_transformation_matrix, smallNormal ); bigNormal = TransformNormal( bigger->cumulative_transformation_matrix, bigNormal ); return true; } } un_iter i; static float rsizelim = XMLSupport::parse_float( vs_config->getVariable( "physics", "smallest_subunit_to_collide", ".2" ) ); clsptr bigtype = bigasteroid ? ASTEROIDPTR : bigger->isUnit(); clsptr smalltype = smallasteroid ? ASTEROIDPTR : smaller->isUnit(); if ( bigger->SubUnits.empty() == false && (bigger->graphicOptions.RecurseIntoSubUnitsOnCollision == true || bigtype == ASTEROIDPTR) ) { i = bigger->getSubUnits(); float rad = smaller->rSize(); for (Unit *un; (un = *i); ++i) { float subrad = un->rSize(); if ( (bigtype != ASTEROIDPTR) && (subrad/bigger->rSize() < rsizelim) ) { break; } if ( ( un->Position()-smaller->Position() ).Magnitude() <= subrad+rad ) { if ( ( un->InsideCollideTree( smaller, bigpos, bigNormal, smallpos, smallNormal, bigtype == ASTEROIDPTR, smalltype == ASTEROIDPTR ) ) ) return true; } } } if ( smaller->SubUnits.empty() == false && (smaller->graphicOptions.RecurseIntoSubUnitsOnCollision == true || smalltype == ASTEROIDPTR) ) { i = smaller->getSubUnits(); float rad = bigger->rSize(); for (Unit *un; (un = *i); ++i) { float subrad = un->rSize(); if ( (smalltype != ASTEROIDPTR) && (subrad/smaller->rSize() < rsizelim) ) break; if ( ( un->Position()-bigger->Position() ).Magnitude() <= subrad+rad ) { if ( ( bigger->InsideCollideTree( un, bigpos, bigNormal, smallpos, smallNormal, bigtype == ASTEROIDPTR, smalltype == ASTEROIDPTR ) ) ) return true; } } } //FIXME //doesn't check all i*j options of subunits vs subunits return false; }
void GameUnit<UnitType>::UpdatePhysics2 (const Transformation &trans, const Transformation & old_physical_state, const Vector & accel, float difficulty, const Matrix &transmat, const Vector & cum_vel, bool lastframe, UnitCollection *uc) { int player = -1; UnitType::UpdatePhysics2( trans, old_physical_state, accel, difficulty, transmat, cum_vel, lastframe, uc); // Here send (new position + direction = curr_physical_state.position and .orientation) // + speed to server (which velocity is to consider ?) // + maybe Angular velocity to anticipate rotations in the other network clients if( Network!=NULL) { //cout<<"SEND UPDATE"<<endl; // Check if this is a player, because in network mode we should only send updates of our moves player= _Universe->whichPlayerStarship( this); if( player>=0 /* && this->networked */ ) { if (Network[0].isTime()) { //cout<<"Player number : "<<player<<endl; // (NetForce + Transform (ship_matrix,NetLocalForce) )/mass = GLOBAL ACCELERATION //curr_physical_state.position = curr_physical_state.position + (Velocity*SIMULATION_ATOM*difficulty).Cast(); // If we want to inter(extra)polate sent position, DO IT HERE // if( !(old_physical_state.position == this->curr_physical_state.position && old_physical_state.orientation == this->curr_physical_state.orientation) ) // We moved so update { /* If you're going to send an alive message, you might as well send your position while you're at it. */ ClientState cstmp( this->serial, this->curr_physical_state, this->Velocity, accel, this->AngularVelocity, 0); Network[player].sendPosition( &cstmp); } // else // { // // Say we are still alive // Network[player].sendAlive(); // } } this->AddVelocity(difficulty); } else { // Not a player so update the unit's position and stuff with the last received snapshot from the server // This may be be a bot or a unit controlled by the server if( !this->networked) // Case it is a local unit this->AddVelocity(difficulty); else { // Networked unit so interpolate its position this->AddVelocity(difficulty); this->curr_physical_state = Network[0].Interpolate( this, SIMULATION_ATOM); } } } else { this->AddVelocity(difficulty); } #ifdef DEPRECATEDPLANETSTUFF if (planet) { Matrix basis; curr_physical_state.to_matrix (this->cumulative_transformation_matrix); Vector p,q,r,c; MatrixToVectors (this->cumulative_transformation_matrix,p,q,r,c); planet->trans->InvTransformBasis (this->cumulative_transformation_matrix,p,q,r,c); planet->cps=Transformation::from_matrix (this->cumulative_transformation_matrix); } #endif this->cumulative_transformation = this->curr_physical_state; this->cumulative_transformation.Compose (trans,transmat); this->cumulative_transformation.to_matrix (this->cumulative_transformation_matrix); this->cumulative_velocity = TransformNormal (transmat,this->Velocity)+cum_vel; Transformation * ct; Matrix * ctm=NULL; unsigned int i; if (lastframe) { char tmp=0; double blah=queryTime(); for (i=0;i<this->meshdata.size();i++) { if (!this->meshdata[i]) continue; tmp |=this->meshdata[i]->HasBeenDrawn(); if (!this->meshdata[i]->HasBeenDrawn()) { this->meshdata[i]->UpdateFX(SIMULATION_ATOM); } this->meshdata[i]->UnDraw(); } double blah1=queryTime(); if (!tmp&&this->hull<0) { Explode(false,SIMULATION_ATOM); } double blah2=queryTime(); if (blah2-blah1>.001||blah1-blah>.001) { //printf ("Too much time in physics: fx: %f exp: %f \n",blah1-blah,blah2-blah1); } } //UnitType::UpdatePhysics2 (trans,old_physical_state,accel,difficulty,transmat, cum_vel, lastframe,uc); }
Vector3 CVector3::TransformNormal(Vector3 normal, Matrix matrix) { TransformNormal(normal, matrix, normal); return normal; }