void
CameraDirector::Chase(double seconds)
{
    double step  = 1;

    if (requested_mode == MODE_COCKPIT)
    step = transition;

    else if (requested_mode == MODE_CHASE)
    step = 1 - transition;

    camera.Clone(ship->Cam());
    Point velocity = camera.vpn();

    if (ship->Velocity().length() > 10) {
        velocity = ship->Velocity();
        velocity.Normalize();
        velocity *= 0.25;
        velocity += camera.vpn() * 2;
        velocity.Normalize();
    }

    Point chase  = ship->ChaseLocation();
    Point bridge = ship->BridgeLocation();
    Point cpos   = camera.Pos()                        + 
    camera.vrt() * bridge.x * (1-step)  +
    camera.vpn() * bridge.y * (1-step)  +
    camera.vup() * bridge.z * (1-step)  +
    velocity     * chase.y  * step      + 
    camera.vup() * chase.z  * step;

    camera.MoveTo(cpos);
}
示例#2
0
Matrix& Matrix::ComputeAxisMatrix(Point& axis, float angle)
{
	MakeIdentity();

	float length = axis.Magnitude();
	// Normalize the z basis vector3
	axis /= length;

	// Get the dot product, and calculate the projection of the z basis
	// vector3 onto the up vector3. The projection is the y basis vector3.
	float dotProduct = Point(0, 1, 0) | axis;
	Point Up = Point(0, 1, 0) - dotProduct * axis;

	// This is to prevent bogus view matrix (up view vector3 equals to axis)
	if (Up.Magnitude() < 1e-6f)	{
		Up = Point(0, 0, 1);
	}
	else	{
	// Normalize the y basis vector3
		Up /= length;
		Up.Normalize();
	}

	// The x basis vector3 is found simply with the cross product of the y
	// and z basis vectors
	Point Right = Up ^ axis;

	SetCol( 0, Right );
	SetCol( 1, Up );
	SetCol( 2, axis );
	Transpose();

	return *this;
}
示例#3
0
void
QuantumFlash::UpdateVerts(const Point& cam_pos)
{
    if (length < radius) {
        length += radius/80;
        width  += 1;
    }

    for (int i = 0; i < npolys; i++) {
        Matrix& m = beams[i];
        
        m.Yaw(0.05);
        Point vpn = Point(m(2,0), m(2,1), m(2,2));

        Point head  = loc;
        Point tail  = loc - vpn * length;
        Point vtail = tail - head;
        Point vcam  = cam_pos - loc;
        Point vtmp  = vcam.cross(vtail);
        vtmp.Normalize();
        Point vlat  = vtmp * -width;

        verts->loc[4*i+0] = head + vlat;
        verts->loc[4*i+1] = tail + vlat * 8;
        verts->loc[4*i+2] = tail - vlat * 8;
        verts->loc[4*i+3] = head - vlat;

        DWORD color = D3DCOLOR_RGBA((BYTE) (255*shade), (BYTE) (255*shade), (BYTE) (255*shade), 255);

        for (int n = 0; n < 4; n++) {
            verts->diffuse[4*i+n] = color;
        }
    }
}
示例#4
0
bool Triangle::IntersectSphere(const Point& center, const double radius) const
{
	Point p[3], e[3];
	p[0] = p0 - center;
	p[1] = p1 - center;
	p[2] = p2 - center;

	double radius2 = radius*radius;
	for(int i=0; i<3; i++)
		if( p[i].Norm2()  < radius2)
			return true;
             
	// This is the buggy part
	for(int i=0; i<3; i++)
	{
		e[i] = p[i] - p[(i+1)%3];
		double n2 = e[i].Norm2();
		double d = (p[i] | e[i]);
		if(d > 0 && -d < n2 && p[i].Norm2() - d*d/n2 < radius2 )
			return true;
	}

	Point n = e[0]^e[1];
	n = n.Normalize();
	double d = (p[0]|n);
	if( abs(d) >= radius)
		return false;

	n = d*n;

	int sign01 = SignMask(e[0]^(p[0] - n)); 
	int sign12 = SignMask(e[1]^(p[1] - n));
	int sign20 = SignMask(e[2]^(p[2] - n));            
	return (sign01 & sign12 & sign20) != 0;
}
// GetSecondAngleAxis looks for the axis defined by the pointer finger
// And the left base
bool GloveType::GetBothAxes(int i) {
    if (!GetFirstAxis(i)) return false;
    if (axis_points2_.size() == 2) {
        // Check the first Axis validity
        if (base_left_->current_ == 0 || base_right_->current_ == 0) {
            return false;
        }
        /*check second axis*/
        Point u;
        if (fore_->current_ == 0) {
            return false;
        } else {
            u = fore_->Sub(*base_left_);
        }
        Point v = fore_->Sub(*base_left_);
        axis2_ = u.Sub(v.Normalize().Times(u.Dot(v))).Normalize();
        // Now find the normal component
        return true;
    } else {
        if (base_left_->current_ == 0 || fore_->current_ == 0) return false;
        axis_points2_.push_back(fore_);
        axis_points2_.push_back(base_left_);
        Point v = fore_->Sub(*base_left_);
        axis2_ =  v.Sub(axis1_.Times(v.Dot(axis1_))).Normalize();
        Point y_axis;
        y_axis.Init(0, 1, 0);
        original_axis2_ = y_axis;
        return true;
    }
}
示例#6
0
	Ray(Point P0, Point dir, GLfloat T)
	{
		p0 = P0;
		r = dir.Normalize();
		t = T;
		vect = p0 + (r * t);
	}
示例#7
0
void
Trail::UpdateVerts(const Point& cam_pos)
{
	if (ntrail < 2) return;

	int bright = 255 - dim*ntrail;

	Point head  = trail[1] + loc;
	Point tail  = trail[0] + loc;
	Point vcam  = cam_pos - head;
	Point vtmp  = vcam.cross(head-tail);
	vtmp.Normalize();
	Point vlat  = vtmp * (width + (0.1 * width * ntrail));

	verts->loc[0]     = tail - vlat;
	verts->loc[1]     = tail + vlat;
	verts->diffuse[0] = 0;
	verts->diffuse[1] = 0;

	for (int i = 0; i < ntrail-1; i++) {
		bright+=dim;
		Point head  = trail[i+1] + loc;
		Point tail  = trail[i] + loc;
		Point vcam  = cam_pos - head;
		Point vtmp  = vcam.cross(head-tail);
		vtmp.Normalize();
		
		float trail_width = (float) (width + (ntrail-i) * width * 0.1);
		if (i == ntrail-2) trail_width = (float) (width * 0.7);
		Point vlat  = vtmp * trail_width;

		verts->loc[2*i+2] = head - vlat;
		verts->loc[2*i+3] = head + vlat;

		if (bright <= 0) {
			verts->diffuse[2*i+2] = 0;
			verts->diffuse[2*i+3] = 0;
		}
		else {
			verts->diffuse[2*i+2] = D3DCOLOR_RGBA(bright,bright,bright,bright);
			verts->diffuse[2*i+3] = D3DCOLOR_RGBA(bright,bright,bright,bright);
		}
	}
}
示例#8
0
void RotateCamera(int dx, int dy)
{
	gDir = gDir.Normalize();
	gN = gDir ^ Point(0,1,0);

	NxQuat qx(NxPiF32 * dx * 20/ 180.0f, Point(0,1,0));
	qx.rotate(gDir);
	NxQuat qy(NxPiF32 * dy * 20/ 180.0f, gN);
	qy.rotate(gDir);
}
示例#9
0
void
Camera::LookAt(const Point& target, const Point& eye, const Point& up)
{
    Point zaxis = target - eye;         zaxis.Normalize();
    Point xaxis = up.cross(zaxis);      xaxis.Normalize();
    Point yaxis = zaxis.cross(xaxis);   yaxis.Normalize();

    orientation(0,0)  = xaxis.x;
    orientation(0,1)  = xaxis.y;
    orientation(0,2)  = xaxis.z;

    orientation(1,0)  = yaxis.x;
    orientation(1,1)  = yaxis.y;
    orientation(1,2)  = yaxis.z;

    orientation(2,0)  = zaxis.x;
    orientation(2,1)  = zaxis.y;
    orientation(2,2)  = zaxis.z;

    pos               = eye;
}
示例#10
0
Matrix4x4& Matrix4x4::SelfShadow(const Point& light)
{
	Point Light = light;
	Light.Normalize();

	Zero();
	m[0][0] = Light.x * 0.5f;
	m[0][1] = Light.y * 0.5f;
	m[0][2] = Light.z * 0.5f;
	m[0][3] = 0.5f;
	m[3][3] = 1.0f;
	return *this;
}
示例#11
0
void RotateCamera(int dx, int dy)
{
	const Point Up(0.0f, 1.0f, 0.0f);

	gDir.Normalize();
	gViewY = gDir^Up;

	// #### TODO: replicate this using Ice quats
	MyQuat qx(NxPiF32 * dx * 20.0f/ 180.0f, Up);
	qx.rotate(gDir);
	MyQuat qy(NxPiF32 * dy * 20.0f/ 180.0f, gViewY);
	qy.rotate(gDir);
}
示例#12
0
  void MeshOptimize2dOCCSurfaces :: 
  GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const
  {
    //  static int cnt = 0;
    //  if (cnt++ % 1000 == 0) cout << "GetNV cnt = " << cnt << endl;
    Standard_Real u,v;

    gp_Pnt pnt(p(0), p(1), p(2));

    Handle(Geom_Surface) occface;
    occface = BRep_Tool::Surface(TopoDS::Face(geometry.fmap(surfind)));

    /*
    GeomAPI_ProjectPointOnSurf proj(pnt, occface);

    if (proj.NbPoints() < 1)
      {
	cout << "ERROR: OCCSurface :: GetNormalVector: GeomAPI_ProjectPointOnSurf failed!"
	     << endl;
	cout << p << endl;
	return;
      }
 
    proj.LowerDistanceParameters (u, v);
    */
    
    Handle( ShapeAnalysis_Surface ) su = new ShapeAnalysis_Surface( occface );
    gp_Pnt2d suval = su->ValueOfUV ( pnt, BRep_Tool::Tolerance( TopoDS::Face(geometry.fmap(surfind)) ) );
    suval.Coord( u, v);
    pnt = occface->Value( u, v );
    
    

    gp_Vec du, dv;
    occface->D1(u,v,pnt,du,dv);

    /*
      if (!occface->IsCNu (1) || !occface->IsCNv (1))
      (*testout) << "SurfOpt: Differentiation FAIL" << endl;
    */

    n = Cross (Vec3d(du.X(), du.Y(), du.Z()),
	       Vec3d(dv.X(), dv.Y(), dv.Z()));
    n.Normalize();

    if (geometry.fmap(surfind).Orientation() == TopAbs_REVERSED) n = -1*n;  
  }
示例#13
0
void Triangle::Inflate(float fat_coeff, bool constant_border)
{
	// Compute triangle center
	Point TriangleCenter;
	Center(TriangleCenter);

	// Don't normalize?
	// Normalize => add a constant border, regardless of triangle size
	// Don't => add more to big triangles
	for(udword i=0;i<3;i++)
	{
		Point v = mVerts[i] - TriangleCenter;

		if(constant_border)	v.Normalize();

		mVerts[i] += v * fat_coeff;
	}
}
示例#14
0
bool Triangle::IntersectCylinder(const Point& c0, const Point& c1, const double radius) const
{
	// check intersection with the edges
	if(SegmentSegmentDistance(p0, p1, c0, c1) < radius)
		return true;
	if(SegmentSegmentDistance(p1, p2, c0, c1) < radius)
		return true;
	if(SegmentSegmentDistance(p2, p1, c0, c1) < radius)
		return true;

	// check intersection with the inner 
	Point n = ((p0-p1)^(p0-p2)).Normalize();
	Point intersect;

	double origin = n|p0;
	double nC0 = (n|c0) - origin;
	double nC1 = (n|c1) - origin;

	if(nC0*nC1 > 0)
	{

		if(abs(nC0) < abs(nC1))
		{
			if(abs(nC0) > radius)
				return false;

			intersect = c0 - n*nC0;
		}
		else
		{
			if(abs(nC1) > radius)
				return false;

			intersect = c1 - n*nC1;
		}
	}
	else
	{
		Point dir = c1 - c0;
		intersect = c0 + (nC0/(dir|n))*dir.Normalize();
	}

	return IntersectPoint(intersect);
}
void
Physical::LinearFrame(double seconds)
{
	// deal with lateral thrusters:

	if (trans_x) { // side-to-side
		Point transvec = cam.vrt();
		transvec *= ((trans_x/mass) * seconds);

		velocity += transvec;
	}

	if (trans_y) { // fore-and-aft
		Point transvec = cam.vpn();
		transvec *= ((trans_y/mass) * seconds);

		velocity += transvec;
	}

	if (trans_z) { // up-and-down
		Point transvec = cam.vup();
		transvec *= ((trans_z/mass) * seconds) * 2;			//**Compensate extra gravity

		velocity += transvec;
	}

	// if gravity applies, attract:
	if (primary_mass > 0) {
		Point  g = primary_loc - cam.Pos();
		double r = g.Normalize();

		g *= GRAV * primary_mass / (r*r);

		velocity += g * seconds;
	}

	// constant gravity:
	else if (g_accel > 0)
	velocity += Point(0, -g_accel, 0) * seconds;

	// if drag applies, decellerate:
	if (drag)
	velocity *= exp(-drag * seconds);
}
示例#16
0
void
CameraDirector::Target(double seconds)
{
    Point target_loc = external_point;

    if (external_ship)
    target_loc = external_ship->Location();

    if (!external_ship || external_ship == ship) {
        if (!external_point) {
            if (ship->Cockpit())
            Virtual(seconds);
            else
            Orbit(seconds);

            return;
        }
    }

    double step  = 1;

    if (requested_mode == MODE_COCKPIT)
    step = transition;

    else if (requested_mode == MODE_TARGET)
    step = 1 - transition;

    if (ship->Cockpit()) {
        // internal padlock:
        Cockpit(seconds);
        camera.Padlock(target_loc, 3*PI/4, PI/8, PI/3);
    }
    else {
        // external padlock:
        Point delta = target_loc - ship->Location();
        delta.Normalize();
        delta *= -5 * ship->Radius() * step;
        delta.y += ship->Radius() * step; 

        camera.MoveTo(ship->Location() + delta);
        camera.LookAt(target_loc);
    }
}
示例#17
0
  void MeshOptimize2dOCCSurfaces :: 
  GetNormalVector(INDEX surfind, const Point<3> & p, PointGeomInfo & geominfo, Vec<3> & n) const
  {
    gp_Pnt pnt;
    gp_Vec du, dv;

    Handle(Geom_Surface) occface;
    occface = BRep_Tool::Surface(TopoDS::Face(geometry.fmap(surfind)));

    occface->D1(geominfo.u,geominfo.v,pnt,du,dv);

    n = Cross (Vec<3>(du.X(), du.Y(), du.Z()),
	       Vec<3>(dv.X(), dv.Y(), dv.Z()));
    n.Normalize();

    if (geometry.fmap(surfind).Orientation() == TopAbs_REVERSED) n = -1*n;  
  
    //  GetNormalVector (surfind, p, n);
  }
示例#18
0
	Light(GLfloat x, GLfloat y, GLfloat z, 
			GLfloat SExponent, GLfloat AExponent, GLfloat theta,
			GLfloat xdir, GLfloat ydir, GLfloat zdir, 
			GLfloat A0, GLfloat A1, GLfloat A2)
	{
		coordiante.x = x;
		coordiante.y = y;
		coordiante.z = z;
		direction.x = xdir;
		direction.y = ydir;
		direction.z = zdir;
		direction.Normalize();
		angle = theta;
		angularAttenuationExponent = AExponent;
		specularExponent = SExponent;
		radialAttenuationA0 = A0;
		radialAttenuationA1 = A1;
		radialAttenuationA2 = A2;
	}
示例#19
0
Steer
SteerAI::Flee(const Point& pt)
{
    Steer s;

    Point point = pt;
    point.Normalize();

    // approach
    if (point.z > 0.0f) {
        if (point.x > 0) s.yaw = -1.0f;
        else             s.yaw =  1.0f;
    }

    // flee
    else {
        s.yaw   = -point.x;
        s.pitch =  point.y;
    }

    return s;
}
示例#20
0
void
Bolt::Render(Video* video, DWORD flags)
{
	if ((flags & RENDER_ADDITIVE) == 0)
	return;

	if (visible && !hidden && video && life) {
		const Camera*  camera = video->GetCamera();

		Point head  = loc;
		Point tail  = origin;
		Point vtail = tail - head;
		Point vcam  = camera->Pos() - loc;
		Point vtmp  = vcam.cross(vtail);
		vtmp.Normalize();
		Point vlat  = vtmp * -width;
		Vec3  vnrm  = camera->vpn() * -1;

		vset.loc[0] = head + vlat;
		vset.loc[1] = tail + vlat;
		vset.loc[2] = tail - vlat;
		vset.loc[3] = head - vlat;

		vset.nrm[0] = vnrm;
		vset.nrm[1] = vnrm;
		vset.nrm[2] = vnrm;
		vset.nrm[3] = vnrm;

		ColorValue  white((float) shade, (float) shade, (float) shade);
		mtl.Ka = white;
		mtl.Kd = white;
		mtl.Ks = Color::Black;
		mtl.Ke = white;

		video->DrawPolys(1, &poly);
	}
}
示例#21
0
bool
Scene::IsLightObscured(const Point& obj_pos, const Point& light_pos, double obj_radius, Point* impact_point) const
{
    Point  dir = light_pos - obj_pos;
    double len = dir.Normalize();

    Scene*      pThis    = (Scene*) this; // cast-away const
    Graphic*    g        = 0;
    bool        obscured = false;

    ListIter<Graphic> g_iter = pThis->graphics;
    while (++g_iter && !obscured) {
        g = g_iter.value();

        if (g->CastsShadow() && !g->Hidden() && !g->IsInfinite()) {
            double gdist = (g->Location() - obj_pos).length();
            if (gdist > 0.1 &&                     // different than object being obscured
                    g->Radius() > obj_radius &&        // larger than object being obscured
                    (g->Radius()*400)/gdist > 10) {    // projects to a resonable size

                Point  delta = (g->Location() - light_pos);

                if (delta.length() > g->Radius() / 100) { // not the object that is emitting the light
                    Point  impact;
                    obscured = g->CheckRayIntersection(obj_pos, dir, len, impact, false) ? true : false;

                    if (impact_point)
                    *impact_point = impact;
                }
            }

            else if (obj_radius < 0 && gdist < 0.1) { // special case for camera (needed for cockpits)
                Point  delta = (g->Location() - light_pos);

                if (delta.length() > g->Radius() / 100) { // not the object that is emitting the light
                    Point  impact;
                    obscured = g->CheckRayIntersection(obj_pos, dir, len, impact, false) ? true : false;
                }
            }
        }
    }

    g_iter.attach(pThis->foreground);
    while (++g_iter && !obscured) {
        g = g_iter.value();

        if (g->CastsShadow() && !g->Hidden()) {
            double gdist = (g->Location() - obj_pos).length();
            if (gdist > 0.1 &&                     // different than object being obscured
                    g->Radius() > obj_radius &&        // larger than object being obscured
                    (g->Radius()*400)/gdist > 10) {    // projects to a resonable size

                Point  delta = (g->Location() - light_pos);

                if (delta.length() > g->Radius() / 100) { // not the object that is emitting the light
                    Point  impact;
                    obscured = g->CheckRayIntersection(obj_pos, dir, len, impact, false) ? true : false;

                    if (impact_point)
                    *impact_point = impact;
                }
            }

            else if (obj_radius < 0 && gdist < 0.1) { // special case for camera (needed for cockpits)
                Point  delta = (g->Location() - light_pos);

                if (delta.length() > g->Radius() / 100) { // not the object that is emitting the light
                    Point  impact;
                    obscured = g->CheckRayIntersection(obj_pos, dir, len, impact, false) ? true : false;
                }
            }
        }
    }

    return obscured;
}
// Vector normalization can handle a Near-Zero Magnitude
TEST_F(PointTest, NormNearZeroMag) {
  Point p = NearZeroMag_; 
  p = p.Normalize();
  EXPECT_FALSE(p.Equals(ZeroMag_)) << "Normalize near 0 vector == 0 vector";
  ASSERT_EQ(p.Magnitude(), 1)  << "Normalize near 0 vector: Mag != 1";
}
// Normalization Tests
// Vector normalization can handle a Zero Magnitude
TEST_F(PointTest, NormZeroMag) {
  Point p = ZeroMag_;
  p = p.Normalize();
  ASSERT_TRUE(p.Equals(ZeroMag_)) << "Normalize 0 vector !=  0 vector";
  ASSERT_EQ(p.Magnitude(), 0)  << "Normalize 0 vector: Mag != 0";
}
void
StarshipAI::ThrottleControl()
{
	// signifies this ship is a dead hulk:
	if (ship && ship->Design()->auto_roll < 0) {
		return;
	}

	// station keeping:

	if (distance < 0) {
		old_throttle = 0;
		throttle     = 0;

		ship->SetThrottle(0);

		if (ship->GetFLCS())
		ship->GetFLCS()->FullStop();

		return;
	}

	// normal throttle processing:

	double   ship_speed  = ship->Velocity() * ship->Heading();
	double   brakes      = 0;
	Ship*    ward        = ship->GetWard();
	Ship*    s_threat    = 0;

	if (threat && threat->Class() >= ship->Class())
	s_threat = threat;

	if (target || s_threat) {  // target pursuit, or retreat
		throttle = 100;

		if (target && distance < 50e3) {
			double closing_speed = ship_speed;

			if (target) {
				Point delta = target->Location() - ship->Location();
				delta.Normalize();

				closing_speed = ship->Velocity() * delta;
			}

			if (closing_speed > 300) {
				throttle = 30;
				brakes   = 0.25;
			}
		}

		throttle *= (1 - accumulator.brake);

		if (throttle < 1 && ship->GetFLCS() != 0)
		ship->GetFLCS()->FullStop();
	}

	else if (ward) {           // escort, match speed of ward
		double zone = ship->Radius() * 3;
		double ws = ward->Velocity().length();
		double ss = ship_speed;

		if (distance < 1e3) 
		throttle = old_throttle;

		if (distance >  zone*3)
			throttle = 100;
		
		else if (distance >  zone) {
			if((ss - ws) > 300) {
			throttle = 0;
			brakes = 0.5;
			}

			else if((ss - ws) < 250)
				throttle = ward->Throttle() + 20;

			else throttle = 0;
		}

		else if (distance < -zone*2) {
			throttle = old_throttle - 10;
			brakes   = 1;
		}
		else if (distance < -zone) {
			throttle = old_throttle;
			brakes   = 1;
		}
		else {
		double ds = ws - ss;
		double at = 0;

		if (ds > 0)
			at = ds  * seconds;
		else if (ds < 0) {
			at = ds  * seconds;
			brakes = 1;
			}
		throttle = old_throttle + at;
		}


/**		double speed = ward->Velocity().length();
		throttle = old_throttle;

		if (speed == 0) {
			double d = (ship->Location() - ward->Location()).length();

			if (d > 30e3)
			speed = (d - 30e3) / 100;
		}

		if (speed > 0) {
			if (ship_speed > speed) {
				throttle = old_throttle - 1;
				brakes   = 0.2;
			}
			else if (ship_speed < speed - 10) {
				throttle =  old_throttle + 1;
			}
		}
		else {
			throttle = 0;
			brakes   = 0.5;
		}	**/
	}

	else if (patrol || farcaster) {  // seek patrol point
		throttle = 100;

		if (distance < 10 * ship_speed) {
			if (ship->Velocity().length() > 200)
			throttle = 5;
			else
			throttle = 50;
		}
	}

	else if (navpt) {          // lead only, get speed from navpt
		double speed = navpt->Speed();
		throttle = old_throttle;

		if (hold) {
			throttle = 0;
			brakes   = 1;
		}

		else {
			if (speed <= 0)
			speed = 300;

			if (ship_speed > speed) {
				if (throttle > 0 && old_throttle > 1)
				throttle = old_throttle - 1;

				brakes   = 0.25;
			}
			else if (ship_speed < speed - 10) {
				throttle =  old_throttle + 1;
			}
		}
	}

	else if (element_index > 1) { // wingman
		Ship*  lead = ship->GetElement()->GetShip(1);
		double lv = lead->Velocity().length();
		double sv = ship_speed;
		double dv = lv-sv;
		double dt = 0;

		if (dv > 0)       dt = dv * 1e-2 * seconds;
		else if (dv < 0)  dt = dv * 1e-2 * seconds;

		throttle = old_throttle + dt;
	}

	else {
		throttle = 0;
	}

	old_throttle = throttle;
	ship->SetThrottle(throttle);

	if (ship_speed > 1 && brakes > 0)
	ship->SetTransY(-brakes * ship->Design()->trans_y);

	else if (throttle > 10 && (ship->GetEMCON() < 2 || ship->GetFuelLevel() < 10))
	ship->SetTransY(ship->Design()->trans_y);
}
bool
TerrainPatch::BuildDetailLevel(int level)
{
	int i, j;

	int detail_size = 1 << level;
	int ds1 = detail_size+1;

	if (detail_size > PATCH_SIZE)
	return false;

	Model* model   = new(__FILE__,__LINE__) Model;
	detail_levels[level] = model;

	model->SetLuminous(luminous);
	model->SetDynamic(true);

	const int   NUM_STRIPS        = 4;
	const int   NUM_INDICES_TRI   = 3;
	const int   NUM_INDICES_QUAD  = 6;

	int nverts     = ds1*ds1 + ds1*2*NUM_STRIPS;
	int npolys     = detail_size*detail_size*2;
	int strip_len  = detail_size;
	int total      = npolys + strip_len*NUM_STRIPS;

	if (water) {
		nverts      = ds1*ds1;
		strip_len   = 0;
		total       = npolys;
	}

	Surface*    s     = new(__FILE__,__LINE__) Surface;
	VertexSet*  vset  = 0;

	if (s) {
		s->SetName("default");
		s->CreateVerts(nverts);
		s->CreatePolys(total);
		s->AddIndices(npolys*NUM_INDICES_TRI + strip_len*NUM_STRIPS*NUM_INDICES_QUAD);

		vset = s->GetVertexSet();
		if (!water)
		vset->CreateAdditionalTexCoords();

		ZeroMemory(vset->loc,      nverts * sizeof(Vec3));
		ZeroMemory(vset->diffuse,  nverts * sizeof(DWORD));
		ZeroMemory(vset->specular, nverts * sizeof(DWORD));
		ZeroMemory(vset->tu,       nverts * sizeof(float));
		ZeroMemory(vset->tv,       nverts * sizeof(float));
		if (!water) {
			ZeroMemory(vset->tu1,      nverts * sizeof(float));
			ZeroMemory(vset->tv1,      nverts * sizeof(float));
		}
		ZeroMemory(vset->rw,       nverts * sizeof(float));

		// initialize vertices
		Vec3*  pVert   = vset->loc;
		float* pTu     = vset->tu;
		float* pTv     = vset->tv;
		float* pTu1    = vset->tu1;
		float* pTv1    = vset->tv1;
		DWORD* pSpec   = vset->specular;

		int    dscale  = (PATCH_SIZE-1)/detail_size;
		double dt      = 0.0625 / (ds1-1); // terrain texture scale
		double dtt     = 2.0000 / (ds1-1); // tile texture scale
		double tu0     = (double) rect.x / rect.w / 16.0 + 1.0/16.0;
		double tv0     = (double) rect.y / rect.h / 16.0;

		// surface verts
		for (i = 0; i < ds1; i++) {
			for (j = 0; j < ds1; j++) {
				*pVert   = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)),
				(float) (heights[i*dscale*PATCH_SIZE + j*dscale]),
				(float) (i* scale * dscale - (HALF_PATCH_SIZE*scale)));

				if (level >= 2) {
					*pTu++   = (float) (-j*dtt);
					*pTv++   = (float) ( i*dtt);

					if (level >= 4 && !water) {
						*pTu1++  = (float) (-j*dtt*3);
						*pTv1++  = (float) ( i*dtt*3);
					}

					*pSpec++ = BlendValue(pVert->y);
				}

				else {
					*pTu++   = (float) (tu0 - j*dt);
					*pTv++   = (float) (tv0 + i*dt);
				}

				pVert++;
			}
		}

		if (!water) {
			// strip 1 & 2 verts
			for (i = 0; i < ds1; i += detail_size) {
				for (j = 0; j < ds1; j++) {
					Vec3 vl  = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)),
					(float) (heights[i*dscale*PATCH_SIZE + j*dscale]),
					(float) (i* scale * dscale - (HALF_PATCH_SIZE*scale)));

					*pVert++ = vl;

					DWORD blend = 0;

					if (level >= 2) {
						blend = BlendValue(vl.y);

						*pSpec++ = blend;
						*pTu++   = (float) (-j*dtt);
						*pTv++   = (float) ( i*dtt);
					}

					else {
						*pTu++   = (float) (tu0 - j*dt);
						*pTv++   = (float) (tv0 + i*dt);
					}

					vl.y     = -5000.0f;

					*pVert++ = vl;

					if (level >= 2) {
						*pSpec++ = blend;
						*pTu++   = (float) (-j*dtt);
						*pTv++   = (float) ( i*dtt);
					}

					else {
						*pTu++   = (float) (tu0 - j*dt);
						*pTv++   = (float) (tv0 + i*dt);
					}
				}
			}

			// strip 3 & 4 verts
			for (j = 0; j < ds1; j += detail_size) {
				for (i = 0; i < ds1; i++) {
					Vec3 vl  = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)),
					(float) (heights[i*dscale*PATCH_SIZE + j*dscale]),
					(float) (i* scale * dscale - (HALF_PATCH_SIZE*scale)));

					*pVert++ = vl;

					DWORD blend = 0;

					if (level >= 2) {
						blend = BlendValue(vl.y);

						*pSpec++ = blend;
						*pTu++   = (float) (-j*dtt);
						*pTv++   = (float) ( i*dtt);
					}

					else {
						*pTu++   = (float) (tu0 - j*dt);
						*pTv++   = (float) (tv0 + i*dt);
					}

					vl.y     = -5000.0f;

					*pVert++ = vl;

					if (level >= 2) {
						*pSpec++ = blend;
						*pTu++   = (float) (-j*dtt);
						*pTv++   = (float) ( i*dtt);
					}

					else {
						*pTu++   = (float) (tu0 - j*dt);
						*pTv++   = (float) (tv0 + i*dt);
					}
				}
			}
		}

		Material* m = materials.first();

		// initialize the polys
		for (i = 0; i < npolys; i++) {
			Poly* p        = s->GetPolys() + i;
			p->nverts      = 3;
			p->vertex_set  = vset;
			p->visible     = 1;
			p->sortval     = 0;
			p->material    = m;

			if (level >= 2 && !water) {
				p->material = materials.at(1);
				p->sortval  = 1;
			}
		}

		for (i = npolys; i < total; i++) {
			Poly* p        = s->GetPolys() + i;
			p->nverts      = 4;
			p->vertex_set  = vset;
			p->visible     = 1;
			p->sortval     = 0;
			p->material    = m;
		}

		int index = 0;

		// build main patch polys:
		for (i = 0; i < detail_size; i++) {
			for (j = 0; j < detail_size; j++) {
				int v[4] = {
					(ds1 * (i  ) + (j  )),
					(ds1 * (i  ) + (j+1)),
					(ds1 * (i+1) + (j  )),
					(ds1 * (i+1) + (j+1)) };

				bisect(vset, v);

				// first triangle
				Poly* p = s->GetPolys() + index++;
				p->verts[0]   = v[0];
				p->verts[1]   = v[1];
				p->verts[2]   = v[3];

				if (level >= 2 && !water) {
					int layer = CalcLayer(p) + 1;
					p->material = materials.at(layer);
					p->sortval  = layer;
				}

				// second triangle
				p = s->GetPolys() + index++;
				p->verts[0]   = v[0];
				p->verts[1]   = v[3];
				p->verts[2]   = v[2];

				if (level >= 2 && !water) {
					int layer = CalcLayer(p) + 1;
					p->material = materials.at(layer);
					p->sortval  = layer;
				}
			}
		}

		// build vertical edge strip polys:

		if (!water) {
			for (i = 0; i < NUM_STRIPS; i++) {
				Poly* p = s->GetPolys() + npolys + i*strip_len;
				int   base_index = ds1*ds1 + ds1*2*i;

				for (j = 0; j < strip_len; j++) {
					int v       = base_index + j * 2;
					p->nverts   = 4;

					if (i == 1 || i == 2) {
						p->verts[0] = v;
						p->verts[1] = v+2;
						p->verts[2] = v+3;
						p->verts[3] = v+1;
					}

					else {
						p->verts[0] = v;
						p->verts[1] = v+1;
						p->verts[2] = v+3;
						p->verts[3] = v+2;
					}

					if (level >= 2) {
						int layer = CalcLayer(p) + 1;
						p->material = materials.at(layer);
						p->sortval  = layer;
					}

					p++;
				}
			}
		}

		// update the poly planes:
		for (i = 0; i < total; i++) {
			Poly*   p      = s->GetPolys() + i;
			Plane&  plane  = p->plane;
			WORD*   v      = p->verts;

			plane = Plane(vset->loc[v[0]] + loc,
			vset->loc[v[1]] + loc,
			vset->loc[v[2]] + loc);
		}

		s->Normalize();

		// create continguous segments for each material:
		// sort the polys by material index:
		qsort((void*) s->GetPolys(), s->NumPolys(), sizeof(Poly), mcomp);

		// then assign them to cohesive segments:
		Segment* segment = 0;
		Poly*    spolys  = s->GetPolys();

		for (int n = 0; n < s->NumPolys(); n++) {
			if (segment && segment->material == spolys[n].material) {
				segment->npolys++;
			}
			else {
				segment = 0;
			}

			if (!segment) {
				segment = new(__FILE__,__LINE__) Segment;

				segment->npolys   = 1;
				segment->polys    = &spolys[n];
				segment->material = segment->polys->material;
				segment->model    = model;

				s->GetSegments().append(segment);
			}
		}

		Solid::EnableCollision(false);
		model->AddSurface(s);
		Solid::EnableCollision(true);

		// copy vertex normals:
		const Vec3B* tnorms = terrain->Normals();

		for (i = 0; i < ds1; i++) {
			for (j = 0; j < ds1; j++) {

				if (water) {
					vset->nrm[i*ds1+j] = Point(0,1,0);
				}

				// blend adjacent normals:
				else if (dscale > 1) {
					Point normal;

					// but don't blend more than 16 normals per vertex:
					int step = 1;
					if (dscale > 4)
					step = dscale / 4;

					for (int dy = -dscale/2; dy < dscale/2; dy += step) {
						for (int dx = -dscale/2; dx < dscale/2; dx += step) {
							int ix = rect.x + (ds1-1-j)*dscale + dx;
							int iy = rect.y + i*dscale + dy;

							if (ix < 0)                ix = 0;
							if (ix > terrain_width-1)  ix = terrain_width-1;
							if (iy < 0)                iy = 0;
							if (iy > terrain_width-1)  iy = terrain_width-1;

							Vec3B vbn = tnorms[iy*terrain_width + ix];
							normal += Point((128-vbn.x)/127.0, (vbn.z-128)/127.0, (vbn.y-128)/127.0);
						}
					}

					normal.Normalize();
					vset->nrm[i*ds1+j] = normal;
				}

				// just copy the one normal:
				else {
					Vec3B vbn    = tnorms[(rect.y + i*dscale)*terrain_width + (rect.x + (ds1-1-j) * dscale)];
					Point normal = Point((128-vbn.x)/127.0, (vbn.z-128)/127.0, (vbn.y-128)/127.0);
					vset->nrm[i*ds1+j] = normal;
				}
			}
		}

		if (!water) {
			pVert = &vset->nrm[ds1*ds1];

			// strip 1 & 2 verts
			for (i = 0; i < ds1; i += detail_size) {
				for (j = 0; j < ds1; j++) {
					Vec3 vn  = vset->nrm[i*ds1 + j];

					*pVert++ = vn;
					*pVert++ = vn;
				}
			}

			// strip 3 & 4 verts
			for (j = 0; j < ds1; j += detail_size) {
				for (i = 0; i < ds1; i++) {
					Vec3 vn  = vset->nrm[i*ds1 + j];

					*pVert++ = vn;
					*pVert++ = vn;
				}
			}
		}
	}

	if (level > max_detail)
	max_detail = level;

	return true;
}
void
StarshipAI::FireControl()
{
	// identify unknown contacts:
	if (identify) {
		if (fabs(ship->GetHelmHeading() - ship->CompassHeading()) < 10*DEGREES) {
			Contact* contact = ship->FindContact(target);

			if (contact && !contact->ActLock()) {
				if (!ship->GetProbe()) {
					ship->LaunchProbe();
				}
			}
		}

		return;
	}

	// investigate last known location of enemy ship:
	if (rumor && !target && ship->GetProbeLauncher() && !ship->GetProbe()) {
		// is rumor in basket?
		Point rmr = Transform(rumor->Location());
		rmr.Normalize();

		double dx = fabs(rmr.x);
		double dy = fabs(rmr.y);

		if (dx < 10*DEGREES && dy < 10*DEGREES && rmr.z > 0) {
			ship->LaunchProbe();
		}
	}

	// Corvettes and Frigates are anti-air platforms.  They need to
	// target missile threats even when the threat is aimed at another
	// friendly ship.  Forward facing weapons must be on auto fire,
	// while lateral and aft facing weapons are set to point defense.

	if (ship->Class() == Ship::CORVETTE || ship->Class() == Ship::FRIGATE) {
		ListIter<WeaponGroup> iter = ship->Weapons();
		while (++iter) {
			WeaponGroup* group = iter.value();

			ListIter<Weapon> w_iter = group->GetWeapons();
			while (++w_iter) {
				Weapon* weapon = w_iter.value();

				double az = weapon->GetAzimuth();
				if (fabs(az) < 45*DEGREES) {
					weapon->SetFiringOrders(Weapon::AUTO);
					weapon->SetTarget(target, 0);
				}

				else {
					weapon->SetFiringOrders(Weapon::POINT_DEFENSE);
				}
			}
		}
	}

	// All other starships are free to engage ship targets.  Weapon
	// fire control is managed by the type of weapon.

	else {
		System* subtgt = SelectSubtarget();

		ListIter<WeaponGroup> iter = ship->Weapons();
		while (++iter) {
			WeaponGroup* weapon = iter.value();

			if (weapon->GetDesign()->target_type & Ship::DROPSHIPS) {   // anti-air weapon?
				weapon->SetFiringOrders(Weapon::POINT_DEFENSE);
			}
			else if (weapon->IsDrone()) {                               // torpedoes
				weapon->SetFiringOrders(Weapon::MANUAL);
				weapon->SetTarget(target, 0);

				if (target && target->GetRegion() == ship->GetRegion()) {
					Point  delta = target->Location() - ship->Location();
					double range = delta.length();

					if (range < weapon->GetDesign()->max_range * 0.9 && 
							!AssessTargetPointDefense())
					weapon->SetFiringOrders(Weapon::AUTO);

					else if (range < weapon->GetDesign()->max_range * 0.5)
					weapon->SetFiringOrders(Weapon::AUTO);
				}
			}
			else {                                                      // anti-ship weapon
				weapon->SetFiringOrders(Weapon::AUTO);
				weapon->SetTarget(target, subtgt);
				weapon->SetSweep(subtgt ? Weapon::SWEEP_NONE : Weapon::SWEEP_TIGHT);
			}
		}
	}
}
示例#27
0
	Plane(Point P0, Point Normal, GLfloat *Color, GLfloat *SpecColor):Shape(Color, SpecColor)
	{
		p0 = P0;
		normal = Normal.Normalize();		
	}
void
Physical::AeroFrame(double s)
{
	arcade_velocity = Point();

	// if this object is under direction,
	// but doesn't need subframe accuracy,
	// update the control parameters:
	if (dir && !dir->Subframe())
	dir->ExecFrame(s);

	// decrement life before destroying the frame time:
	if (life > 0)
	life -= s;

	// integrate equations
	// using slices no larger
	// than sub_frame:

	double seconds = s;

	while (s > 0.0) {
		if (s > sub_frame)
		seconds = sub_frame;
		else
		seconds = s;

		// if the director needs subframe accuracy, run it now:
		if (dir && dir->Subframe())
		dir->ExecFrame(seconds);

		AngularFrame(seconds);

		// LINEAR MOVEMENT ----------------------------
		Point pos = cam.Pos();

		// if the object is thrusting,
		// accelerate along the camera normal:
		if (thrust) {
			Point thrustvec = cam.vpn();
			thrustvec *= ((thrust/mass) * seconds);
			velocity += thrustvec;
		}

		// AERODYNAMICS ------------------------------

		if (lat_thrust)
		LinearFrame(seconds);

		// if no thrusters, do constant gravity:
		else if (g_accel > 0)
		velocity += Point(0, -g_accel, 0) * seconds;

		// compute alpha, rho, drag, and lift:

		Point  vfp     = velocity;
		double v       = vfp.Normalize();
		double v_2     = 0;
		double rho     = GetDensity();
		double lift    = 0;

		if (v > 150) {					
			v_2 = (v-150) * (v-150);

			Point  vfp1 = vfp - cam.vrt() * (vfp * cam.vrt());
			vfp1.Normalize();

			double cos_alpha = vfp1 * cam.vpn();

			if (cos_alpha >= 1) {
				alpha = 0.0f;
			}
			else {
				alpha = (float) acos(cos_alpha);
			}

			// if flight path is above nose, alpha is negative:
			if (vfp1 * cam.vup() > 0)
			alpha = -alpha;

			if (alpha <= stall) {
				lift = CL * alpha * rho * v_2;
			}
			else {
				lift = CL * (2*stall - alpha) * rho * v_2;
			}

			// add lift to velocity:
			if (_finite(lift))
			velocity += cam.vup() * lift * seconds;
			else
			lift = 0;

			// if drag applies, decellerate:
			double alpha_2 = alpha*alpha;
			double drag_eff = (drag + (CD * alpha_2)) * rho * v_2;

			Point vn = velocity;
			vn.Normalize();

			velocity += vn * -drag_eff * seconds;
		}
		else {
			velocity *= exp(-drag * seconds);
		}

		// move the position by the (time-frame scaled) velocity:
		pos += velocity * seconds;
		cam.MoveTo(pos);

		s -= seconds;
	}

	// now update the graphic rep and light sources:
	if (rep) {
		rep->MoveTo(cam.Pos());
		rep->SetOrientation(cam.Orientation());
	}

	if (light) {
		light->MoveTo(cam.Pos());
	}
}
示例#29
0
// VectorPerpendicularTo finds the vector perpendicular to a line
// line: a vector of two points that define a line in R3
// return: the shortest distance from this point to that line
Point Point::VectorPerpendicularTo(vector<Point> line) {
  Point v = line[1].Sub(line[0]);
  Point u = this->Sub(line[0]);
  return u.Sub(v.Normalize().Times(v.Dot(u)));
}
void dxTriMeshData::Preprocess()
{

#if dTRIMESH_ENABLED

	// If this mesh has already been preprocessed, exit
	if (UseFlags)
		return;

	udword numTris = Mesh.GetNbTriangles();
	udword numEdges = numTris * 3;

	UseFlags = new uint8[numTris];
	memset(UseFlags, 0, sizeof(uint8) * numTris);

	EdgeRecord* records = new EdgeRecord[numEdges];

	// Make a list of every edge in the mesh
	const IndexedTriangle* tris = Mesh.GetTris();
	const unsigned tristride = Mesh.GetTriStride();
	for (unsigned int i = 0; i < numTris; i++)
	{
		SetupEdge(&records[i*3],   0, i, tris->mVRef);
		SetupEdge(&records[i*3+1], 1, i, tris->mVRef);
		SetupEdge(&records[i*3+2], 2, i, tris->mVRef);

		tris = (const IndexedTriangle*)(((uint8*)tris) + tristride);
	}

	// Sort the edges, so the ones sharing the same verts are beside each other
	qsort(records, numEdges, sizeof(EdgeRecord), EdgeCompare);

	// Go through the sorted list of edges and flag all the edges and vertices that we need to use
	for (unsigned int i = 0; i < numEdges; i++)
	{
		EdgeRecord* rec1 = &records[i];
		EdgeRecord* rec2 = 0;
		if (i < numEdges - 1)
			rec2 = &records[i+1];

		if (rec2 &&
			rec1->VertIdx1 == rec2->VertIdx1 &&
			rec1->VertIdx2 == rec2->VertIdx2)
		{
			VertexPointers vp;
			ConversionArea vc;
			Mesh.GetTriangle(vp, rec1->TriIdx, vc);

			// Get the normal of the first triangle
			Point triNorm = (*vp.Vertex[2] - *vp.Vertex[1]) ^ (*vp.Vertex[0] - *vp.Vertex[1]);
			triNorm.Normalize();

			// Get the vert opposite this edge in the first triangle
			Point oppositeVert1 = GetOppositeVert(rec1, vp.Vertex);

			// Get the vert opposite this edge in the second triangle
			Mesh.GetTriangle(vp, rec2->TriIdx, vc);
			Point oppositeVert2 = GetOppositeVert(rec2, vp.Vertex);

			float dot = triNorm.Dot((oppositeVert2 - oppositeVert1).Normalize());

			// We let the dot threshold for concavity get slightly negative to allow for rounding errors
			static const float kConcaveThresh = -0.000001f;

			// This is a concave edge, leave it for the next pass
			if (dot >= kConcaveThresh)
				rec1->Concave = true;
			// If this is a convex edge, mark its vertices and edge as used
			else
				UseFlags[rec1->TriIdx] |= rec1->Vert1Flags | rec1->Vert2Flags | rec1->EdgeFlags;

			// Skip the second edge
			i++;
		}
		// This is a boundary edge
		else
		{
			UseFlags[rec1->TriIdx] |= rec1->Vert1Flags | rec1->Vert2Flags | rec1->EdgeFlags;
		}
	}

	// Go through the list once more, and take any edge we marked as concave and
	// clear it's vertices flags in any triangles they're used in
	for (unsigned int i = 0; i < numEdges; i++)
	{
		EdgeRecord& er = records[i];

		if (er.Concave)
		{
			for (unsigned int j = 0; j < numEdges; j++)
			{
				EdgeRecord& curER = records[j];

				if (curER.VertIdx1 == er.VertIdx1 ||
					curER.VertIdx1 == er.VertIdx2)
					UseFlags[curER.TriIdx] &= ~curER.Vert1Flags;

				if (curER.VertIdx2 == er.VertIdx1 ||
					curER.VertIdx2 == er.VertIdx2)
					UseFlags[curER.TriIdx] &= ~curER.Vert2Flags;
			}
		}
	}

	delete [] records;

#endif // dTRIMESH_ENABLED

}