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); }
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; }
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; } } }
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; } }
Ray(Point P0, Point dir, GLfloat T) { p0 = P0; r = dir.Normalize(); t = T; vect = p0 + (r * t); }
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); } } }
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); }
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; }
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; }
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); }
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; }
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; } }
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); }
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); } }
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); }
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; }
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; }
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); } }
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); } } } }
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()); } }
// 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 }