Пример #1
0
//-----------------------------------------------------------------------------
// 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());
	}
}
Пример #6
0
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);
}
Пример #8
0
Vector3 CVector3::TransformNormal(Vector3 normal, Matrix matrix)
{
	TransformNormal(normal, matrix, normal);
	return normal;
}