예제 #1
0
void CCharShape::AdjustOrientation (CControl *ctrl, double dtime,
		 double dist_from_surface, TVector3 surf_nml) {
    TVector3 new_x, new_y, new_z; 
    TMatrix cob_mat, inv_cob_mat;
    TMatrix rot_mat;
    TQuaternion new_orient;
    double time_constant;
    static TVector3 minus_z_vec = { 0, 0, -1};
    static TVector3 y_vec = { 0, 1, 0 };

    if  (dist_from_surface > 0) {
		new_y = ScaleVector (1, ctrl->cvel);
		NormVector (&new_y);
		new_z = ProjectToPlane (new_y, MakeVector(0, -1, 0));
		NormVector (&new_z);
		new_z = AdjustRollvector (ctrl, ctrl->cvel, new_z);
    } else { 
		new_z = ScaleVector (-1, surf_nml);
		new_z = AdjustRollvector (ctrl, ctrl->cvel, new_z);
		new_y = ProjectToPlane (surf_nml, ScaleVector (1, ctrl->cvel));
		NormVector(&new_y);
    }

    new_x = CrossProduct (new_y, new_z);
    MakeBasismatrix_Inv (cob_mat, inv_cob_mat, new_x, new_y, new_z);
    new_orient = MakeQuaternionFromMatrix (cob_mat);

    if (!ctrl->orientation_initialized) {
		ctrl->orientation_initialized = true;
		ctrl->corientation = new_orient;
    }

    time_constant = dist_from_surface > 0 ? TO_AIR_TIME : TO_TIME;

    ctrl->corientation = InterpolateQuaternions (
			ctrl->corientation, new_orient, 
			min (dtime / time_constant, 1.0));

    ctrl->plane_nml = RotateVector (ctrl->corientation, minus_z_vec);
    ctrl->cdirection = RotateVector (ctrl->corientation, y_vec);
    MakeMatrixFromQuaternion (cob_mat, ctrl->corientation);

    // Trick rotations 
    new_y = MakeVector (cob_mat[1][0], cob_mat[1][1], cob_mat[1][2]); 
    RotateAboutVectorMatrix (rot_mat, new_y, (ctrl->roll_factor * 360));
    MultiplyMatrices (cob_mat, rot_mat, cob_mat);
    new_x = MakeVector (cob_mat[0][0], cob_mat[0][1], cob_mat[0][2]); 
    RotateAboutVectorMatrix (rot_mat, new_x, ctrl->flip_factor * 360);
    MultiplyMatrices (cob_mat, rot_mat, cob_mat);

    TransposeMatrix (cob_mat, inv_cob_mat);
    TransformNode (0, cob_mat, inv_cob_mat); 
}
예제 #2
0
TQuaternion MakeRotationQuaternion (TVector3 s, TVector3 t){
    TQuaternion res;
    TVector3 u;
    double cos2phi, sin2phi;
    double cosphi, sinphi;

    u = CrossProduct (s, t);
    sin2phi = NormVector (&u);

    if  (sin2phi < EPS) {
	res = MakeQuaternion (0., 0., 0., 1.);
    } else {
	cos2phi = DotProduct (s, t);

	sinphi = sqrt ( (1 - cos2phi) / 2.0);
	cosphi = sqrt ( (1 + cos2phi) / 2.0);

	res.x = sinphi * u.x;
	res.y = sinphi * u.y;
	res.z = sinphi * u.z;
	res.w = cosphi;
    }

    return res;
}
예제 #3
0
TVector3 MakeNormal (const TPolygon& p, TVector3 *v) {
	TVector3 v1 = SubtractVectors (v[p.vertices[1]], v[p.vertices[0]]);
	TVector3 v2 = SubtractVectors (v[p.vertices[p.num_vertices-1]], v[p.vertices[0]]);
	TVector3 normal = CrossProduct (v1, v2);

	NormVector (normal);
	return normal;
}
예제 #4
0
void EarClipper::RemoveCollinearPointsFromConsideration()
{
   if (vertices.size() > 3)
   {
      VertexList::iterator first = vertices.begin();
      VertexList::iterator second = first.next();

      Line2D_t ray(*(first->point), NormVector(*(second->point) - *(first->point)), true); 

      VertexList::iterator currentSafe = first;
      VertexList::iterator possibleCollinear = second;
      VertexList::iterator currentCheck = second.next();

      do
      {
         if (ray.IsPointOnLine(*(currentCheck->point), COLLINEAR_TOLERANCE))
         {
            currentSafe->collinearPoints.push_back(possibleCollinear->point);
            vertices.erase(possibleCollinear);
         }
         else
         {
            currentSafe = possibleCollinear;

            ray.P = *(currentSafe->point);
            ray.V = NormVector(*(currentCheck->point) - ray.P);
         }

         possibleCollinear = currentCheck;
         currentCheck = currentCheck.next();
      } while (possibleCollinear != vertices.begin());

      ray.P = *(currentSafe->point);
      ray.V = NormVector(*(possibleCollinear->point) - ray.P);

      if (ray.IsPointOnLine(*(currentCheck->point), COLLINEAR_TOLERANCE))
      {
         currentSafe->collinearPoints.push_back(possibleCollinear->point);

         MigrateCollinearPoints(currentSafe, possibleCollinear);

         vertices.erase(possibleCollinear);
      }
   }
}
예제 #5
0
bool IntersectPolygon (TPolygon p, TVector3 *v) {
    TRay ray; 
    TVector3 nml, edge_nml, edge_vec;
    TVector3 pt;
    double d, s, nuDotProd, wec;
    double edge_len, t, distsq;
    int i;

    nml = MakeNormal (p, v);
    ray.pt = MakeVector (0., 0., 0.);
    ray.vec = nml;

    nuDotProd = DotProduct (nml, ray.vec);
    if  (fabs(nuDotProd) < EPS)
        return false;

    d = - (nml.x * v[p.vertices[0]].x + 
           nml.y * v[p.vertices[0]].y + 
           nml.z * v[p.vertices[0]].z);

    if  (fabs (d) > 1) return false;

    for  (i=0; i < p.num_vertices; i++) {
		TVector3 *v0, *v1;

		v0 = &v[p.vertices[i]];
		v1 = &v[p.vertices[ (i+1) % p.num_vertices ]]; 

		edge_vec = SubtractVectors (*v1, *v0);
		edge_len = NormVector (&edge_vec);

		t = - DotProduct (*((TVector3 *) v0), edge_vec);

		if  (t < 0) {
			distsq = MAG_SQD2 (*v0);
		} else if  (t > edge_len) {
			distsq = MAG_SQD2 (*v1);
		} else {
			*v0 = AddVectors (*v0, ScaleVector (t, edge_vec));
			distsq = MAG_SQD2 (*v0);
		}

		if  (distsq <= 1) return true;
    }

    s = - (d + DotProduct (nml, MakeVector (ray.pt.x, ray.pt.y, ray.pt.z))) / nuDotProd;
    pt = AddVectors (ray.pt, ScaleVector (s, ray.vec));

    for  (i=0; i < p.num_vertices; i++) {
        edge_nml = CrossProduct (nml, 
            SubtractVectors (v[p.vertices[ (i+1) % p.num_vertices ]], v[p.vertices[i]]));

        wec = DotProduct (SubtractVectors (pt, v[p.vertices[i]]), edge_nml);
        if (wec < 0) return false;
    } 
    return true;
} 
예제 #6
0
void EarClipper::AdjustForPossibleResultingCollinearity(VertexListIteratorList& ears, VertexList::iterator& beforeEar, VertexList::iterator& afterEar)
{
   beforeEar->collinearPoints.clear();

   if (vertices.size() > 3)
   {
      FVector2 beforeToAfter = NormVector(*(afterEar->point) - *(beforeEar->point));

      Line2D_t rayBefore(*(beforeEar->point), -beforeToAfter, true);
      Line2D_t rayAfter(*(afterEar->point), beforeToAfter, true);

      VertexList::iterator twiceBeforeEar = beforeEar.previous();
      VertexList::iterator twiceAfterEar = afterEar.next();

      bool removeBeforeEar = rayBefore.IsPointOnLine(*(twiceBeforeEar->point), COLLINEAR_TOLERANCE);
      bool removeAfterEar = rayAfter.IsPointOnLine(*(twiceAfterEar->point), COLLINEAR_TOLERANCE);

      if (removeBeforeEar && removeAfterEar)
      {
         twiceBeforeEar->collinearPoints.push_back(beforeEar->point);
         twiceBeforeEar->collinearPoints.push_back(afterEar->point);

         MigrateCollinearPoints(twiceBeforeEar, afterEar);
      }
      else if (removeBeforeEar)
      {
         twiceBeforeEar->collinearPoints.push_back(beforeEar->point);
      }
      else if (removeAfterEar)
      {
         beforeEar->collinearPoints.push_back(afterEar->point);

         MigrateCollinearPoints(beforeEar, afterEar);
      }

      if (removeBeforeEar)
      {
         if (beforeEar->type == VertexType::Ear)
         {
            RemoveEar(beforeEar->point, ears);
         }

         vertices.erase(beforeEar);
      }

      if (removeAfterEar)
      {
         if (afterEar->type == VertexType::Ear)
         {
            RemoveEar(afterEar->point, ears);
         }

         vertices.erase(afterEar);
      }
   }
}
예제 #7
0
TVector3 MakeNormal (TPolygon p, TVector3 *v) {
    TVector3 normal, v1, v2;

    v1 = SubtractVectors (v[p.vertices[1]], v[p.vertices[0]]);
    v2 = SubtractVectors (v[p.vertices[p.num_vertices-1]], v[p.vertices[0]]);
    normal = CrossProduct (v1, v2);

    NormVector (&normal);
    return normal;
} 
예제 #8
0
TVector3 CCharShape::AdjustRollvector (CControl *ctrl, TVector3 vel, TVector3 zvec) {
    TMatrix rot_mat; 
    vel = ProjectToPlane (zvec, vel);
    NormVector (&vel);
    if (ctrl->is_braking) {
		RotateAboutVectorMatrix (rot_mat, vel, ctrl->turn_fact * BRAKING_ROLL_ANGLE);
    } else {
		RotateAboutVectorMatrix (rot_mat, vel, ctrl->turn_fact * MAX_ROLL_ANGLE);
    }
    return TransformVector (rot_mat, zvec);
}
예제 #9
0
TVector3 CCourse::FindCourseNormal (double x, double z) const {

    double *elevation = Course.elevation;
    int x0, x1, y0, y1;
    GetIndicesForPoint (x, z, &x0, &y0, &x1, &y1);

    TIndex2 idx0, idx1, idx2;
    double u, v;
    FindBarycentricCoords (x, z, &idx0, &idx1, &idx2, &u, &v);

	const TVector3& n0 = Course.nmls[ idx0.i + nx * idx0.j ];
	const TVector3& n1 = Course.nmls[ idx1.i + nx * idx1.j ];
	const TVector3& n2 = Course.nmls[ idx2.i + nx * idx2.j ];

	TVector3 p0 = COURSE_VERTX (idx0.i, idx0.j);
	TVector3 p1 = COURSE_VERTX (idx1.i, idx1.j);
	TVector3 p2 = COURSE_VERTX (idx2.i, idx2.j);

	TVector3 smooth_nml = AddVectors (
		ScaleVector (u, n0),
		AddVectors (ScaleVector (v, n1), ScaleVector (1.-u-v, n2)));

	TVector3 tri_nml = CrossProduct (
		SubtractVectors (p1, p0), SubtractVectors (p2, p0));
    NormVector (tri_nml);

	double min_bary = min (u, min (v, 1. - u - v));
	double interp_factor = min (min_bary / NORM_INTERPOL, 1.0);

	TVector3 interp_nml = AddVectors (
		ScaleVector (interp_factor, tri_nml),
		ScaleVector (1.-interp_factor, smooth_nml));
    NormVector (interp_nml);

    return interp_nml;
}
예제 #10
0
void CalcFinishControls (CControl *ctrl, double timestep, bool airborne) {
	TVector3 movdir = ctrl->cvel;
	double speed = NormVector (movdir);
	double dir_angle = atan (movdir.x / movdir.z) * 57.3;

	if (fabs (dir_angle) > 5 && speed > 5) {
		ctrl->turn_fact = dir_angle / 20;
		if (ctrl->turn_fact < -1) ctrl->turn_fact = -1;
		if (ctrl->turn_fact > 1) ctrl->turn_fact = 1;
		ctrl->turn_animation += ctrl->turn_fact * 2 * timestep;
	} else {
		ctrl->turn_fact = 0;
		if (timestep < ROLL_DECAY) {
	    	ctrl->turn_animation *= 1.0 - timestep / ROLL_DECAY;
		} else ctrl->turn_animation = 0.0;
	}
}
예제 #11
0
TQuaternion MakeRotationQuaternion (const TVector3& s, const TVector3& t) {
	TVector3 u = CrossProduct (s, t);
	double sin2phi = NormVector (u);

	if (sin2phi < EPS) {
		return TQuaternion (0., 0., 0., 1.);
	} else {
		double cos2phi = DotProduct (s, t);

		double sinphi = sqrt ( (1 - cos2phi) / 2.0);
		double cosphi = sqrt ( (1 + cos2phi) / 2.0);

		return TQuaternion(
			sinphi * u.x,
			sinphi * u.y,
			sinphi * u.z,
			cosphi);
	}
}
예제 #12
0
// -------------------------------------------------------
void DrawHud (CControl *ctrl) {
    TVector3 vel;
    double speed;

	if (!param.show_hud) return;
    vel = ctrl->cvel;
    speed = NormVector (&vel);
    SetupGuiDisplay ();

    draw_gauge (speed * 3.6, ctrl->jump_amt);
	set_gl_options (TEXFONT);
	glColor4f (1, 1, 1, 1);
    draw_time();
    draw_herring_count (g_game.herring);
    DrawSpeed (speed * 3.6);
	DrawFps ();
	DrawCoursePosition (ctrl);
	if (g_game.wind_id > 0) DrawWind2 (Wind.Angle (), Wind.Speed (), ctrl);
}
예제 #13
0
void Asteroid::ResolveCollision(Asteroid& otherAsteroid)
{
   std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();

   if (lastCollision == &otherAsteroid)
   {
      std::chrono::high_resolution_clock::duration diff = now - lastCollisionTime;
      if (std::chrono::duration_cast<std::chrono::milliseconds>(diff).count() < 500)
      {
         return;
      }
   }

   if (otherAsteroid.lastCollision == this)
   {
      std::chrono::high_resolution_clock::duration diff = now - otherAsteroid.lastCollisionTime;
      if (std::chrono::duration_cast<std::chrono::milliseconds>(diff).count() < 500)
      {
         return;
      }
   }

   Locus::Triangle3D_t intersectingTriangle1, intersectingTriangle2;

   if ( GetAsteroidIntersection(otherAsteroid, intersectingTriangle1, intersectingTriangle2) )
   {
      Locus::FVector3 collisionPoint = Locus::Triangle3D_t::ComputeCentroid(intersectingTriangle1, intersectingTriangle2);

      Locus::FVector3 impulseDirection = NormVector(intersectingTriangle1.Normal());

      Locus::ResolveCollision(1.0f, BoundingSphere(), otherAsteroid.BoundingSphere(), collisionPoint, impulseDirection,
                              motionProperties, otherAsteroid.motionProperties);

      lastCollision = &otherAsteroid;
      otherAsteroid.lastCollision = this;

      now = std::chrono::high_resolution_clock::now();

      lastCollisionTime = now;
      otherAsteroid.lastCollisionTime = now;
   }
}
예제 #14
0
bool CCourse::LoadObjectTypes () {
	CSPList list (MAX_OBJECT_TYPES+10);

	if (!list.Load (param.obj_dir, "object_types.lst")) {
		Message ("could not load object types");
		return false;
	}

	ObjTypes.resize(list.Count());

	for (size_t i=0; i<list.Count(); i++) {
		const string& line = list.Line(i);
	    ObjTypes[i].name = SPStrN (line, "name", "");
		ObjTypes[i].textureFile = ObjTypes[i].name;
		ObjTypes[i].texture = NULL;

		ObjTypes[i].drawable = SPBoolN (line, "draw", true);
		if (ObjTypes[i].drawable) {
			ObjTypes[i].textureFile = SPStrN (line, "texture", "");
		}
		ObjTypes[i].collectable = SPBoolN (line, "snap", -1) != 0;
		if (ObjTypes[i].collectable == 0) {
			ObjTypes[i].collectable = -1;
		}

		ObjTypes[i].collidable = SPBoolN (line, "coll", false);
		ObjTypes[i].reset_point = SPBoolN (line, "reset", false);
		ObjTypes[i].use_normal = SPBoolN (line, "usenorm", false);

		if (ObjTypes[i].use_normal) {
			ObjTypes[i].normal = SPVector3N (line, "norm", TVector3(0, 1, 0));
			NormVector ((ObjTypes[i].normal));
		}
		ObjTypes[i].poly = 1;
	}
	list.MakeIndex (ObjectIndex, "name");
	return true;
}
예제 #15
0
Model_t ModelUtility::MakeSphere(float radius, unsigned int subdivisions)
{
   if (subdivisions > ModelUtility::MAX_SPHERE_SUBDIVISIONS)
   {
      subdivisions = ModelUtility::MAX_SPHERE_SUBDIVISIONS;
   }

   Model_t octahedron = ModelUtility::MakeOctahedron(radius);

   std::vector<Triangle3D_t> initialTriangles;

   Transformation identity;

   for (std::size_t faceIndex = 0, numFaces = octahedron.NumFaces(); faceIndex < numFaces; ++faceIndex)
   {
      initialTriangles.push_back(octahedron.GetFaceTriangle(faceIndex, identity));
   }

   std::vector<Triangle3D_t> subdividedTriangles;
   subdividedTriangles.reserve( initialTriangles.size() * static_cast<std::size_t>(std::pow(4, subdivisions)) );

   for (const Triangle3D_t& triangle : initialTriangles)
   {
      ModelUtility::SubdivideTriangle(triangle, subdividedTriangles, subdivisions);
   }

   std::vector<std::vector<ModelVertex>> trianglesOnSphere;
   trianglesOnSphere.reserve(subdividedTriangles.size());

   for (const Triangle3D_t& triangle : subdividedTriangles)
   {
      trianglesOnSphere.emplace_back( std::vector<ModelVertex>{ {NormVector(triangle[0]) * radius}, {NormVector(triangle[1]) * radius}, {NormVector(triangle[2]) * radius} } );
   }

   return Model_t(trianglesOnSphere);
}
예제 #16
0
int GzPutAttribute(GzRender	*render, int numAttributes, GzToken	*nameList,
                   GzPointer	*valueList) /* void** valuelist */
{
    /*
    - set renderer attribute states (e.g.: GZ_RGB_COLOR default color)
    - later set shaders, interpolaters, texture maps, and lights
    */

    if (!render || !nameList || !valueList)
        return GZ_FAILURE;
    for (int i = 0; i < numAttributes; i++) {
        switch (nameList[i]) {
        case GZ_RGB_COLOR:
            GzColor* color;
            color = (GzColor *)valueList[i];
            render->flatcolor[RED] = color[i][RED];
            render->flatcolor[GREEN] = color[i][GREEN];
            render->flatcolor[BLUE] = color[i][BLUE];
            break;
        case GZ_INTERPOLATE:
            int * interpmodept;
            interpmodept = (int *)valueList[i];
            render->interp_mode = *interpmodept;
            break;
        case GZ_DIRECTIONAL_LIGHT:
            GzLight* dirlight;
            dirlight = (GzLight *)valueList[i];
            if (render->numlights < MAX_LIGHTS) {
                render->lights[render->numlights] = *dirlight;
                NormVector(render->lights[render->numlights].direction);
                render->numlights += 1;
            }
            break;
        case GZ_AMBIENT_LIGHT:
            GzLight* amblight;
            amblight = (GzLight *)valueList[i];
            render->ambientlight = *amblight;
            break;
        case GZ_AMBIENT_COEFFICIENT:
            float* ka;
            ka = (float*)valueList[i];
            render->Ka[RED] = ka[RED];
            render->Ka[GREEN] = ka[GREEN];
            render->Ka[BLUE] = ka[BLUE];
            break;
        case GZ_DIFFUSE_COEFFICIENT:
            float* kd;
            kd = (float*)valueList[i];
            render->Kd[RED] = kd[RED];
            render->Kd[GREEN] = kd[GREEN];
            render->Kd[BLUE] = kd[BLUE];
            break;
        case GZ_SPECULAR_COEFFICIENT:
            float* ks;
            ks = (float*)valueList[i];
            render->Ks[RED] = ks[RED];
            render->Ks[GREEN] = ks[GREEN];
            render->Ks[BLUE] = ks[BLUE];
            break;
        case GZ_DISTRIBUTION_COEFFICIENT:
            float* specpower;
            specpower = (float*)valueList[i];
            render->spec = *specpower;
            break;
        case GZ_TEXTURE_MAP:
            GzTexture texturefun;
            texturefun= (GzTexture)valueList[i];
            render->tex_fun = texturefun;
            break;
        case GZ_AASHIFTX:
            float *dx;
            dx	= (float*)valueList[i];
            render->dx = *dx;
            break;
        case GZ_AASHIFTY:
            float *dy;
            dy = (float*)valueList[i];
            render->dy = *dy;
            break;
        }

    }
    return GZ_SUCCESS;
}
예제 #17
0
int GzPutTriangle(GzRender	*render, int numParts, GzToken *nameList, GzPointer	*valueList)
/* numParts : how many names and values */
{
    /*
    - pass in a triangle description with tokens and values corresponding to
    GZ_POSITION:3 vert positions in model space
    - Xform positions of verts using matrix on top of stack
    - Clip - just discard any triangle with any vert(s) behind view plane
    - optional: test for triangles with all three verts off-screen (trivial frustum cull)
    - invoke triangle rasterizer
    */
    //check error
    if (render == NULL) {
        return GZ_FAILURE;
    }
    if (nameList == NULL) {
        return GZ_FAILURE;
    }
    if (valueList == NULL) {
        return GZ_FAILURE;
    }

    GzCoord* cord;
    GzCoord* Norms;
    GzTextureIndex* Textcord;//uv
    for (int i = 0; i < numParts; i++) {
        switch (nameList[i]) {
        case GZ_NULL_TOKEN:
            break;
        case GZ_POSITION:
            cord = (GzCoord*)valueList[i];
            break;
        case GZ_NORMAL:
            Norms = (GzCoord *)valueList[i];
            break;
        case GZ_TEXTURE_INDEX:
            Textcord = (GzTextureIndex *)valueList[i];//uv
            break;
        }
    }

    bool behind = false;//behind Visual point
    GzCoord* xformcord = new GzCoord[3];
    GzCoord* xformNorms = new GzCoord[3];
    //get triangle cord

    // Xform positions of verts using matrix on top of stack
    GzMatrix tosmatrx;
    memcpy(tosmatrx, render->Ximage[render->matlevel], sizeof(GzMatrix));
    GzMatrix tosNmatrx;
    memcpy(tosNmatrx, render->Xnorm[render->matlevel], sizeof(GzMatrix));
    float W;
    for (int j = 0; j < 3; j++) {
        // xform verticies

        xformcord[j][X] = tosmatrx[0][0] * cord[j][X] + tosmatrx[0][1] * cord[j][Y] +
                          tosmatrx[0][2] * cord[j][Z] + tosmatrx[0][3] * (float)1.0;
        xformcord[j][Y] = tosmatrx[1][0] * cord[j][X] + tosmatrx[1][1] * cord[j][Y] +
                          tosmatrx[1][2] * cord[j][Z] + tosmatrx[1][3] * (float)1.0;
        xformcord[j][Z] = tosmatrx[2][0] * cord[j][X] + tosmatrx[2][1] * cord[j][Y] +
                          tosmatrx[2][2] * cord[j][Z] + tosmatrx[2][3] * (float)1.0;

        W = tosmatrx[3][0] * cord[j][X] + tosmatrx[3][1] * cord[j][Y] + tosmatrx[3][2] * cord[j][Z] + tosmatrx[3][3] * (float)1.0;


        //Clip - just discard any triangle with any vert(s) behind view plane
        if (xformcord[j][Z] < render->camera.position[Z]) {
            behind = true;
            break;
        }
        xformcord[j][X] /= W;
        xformcord[j][Y] /= W;
        xformcord[j][Z] /= W;
    }

    //
    NormVector(Norms[0]);
    NormVector(Norms[1]);
    NormVector(Norms[2]);

    for (int j = 0; j < 3; j++) {
        xformNorms[j][X] = tosNmatrx[0][0] * Norms[j][X] + tosNmatrx[0][1] * Norms[j][Y] + tosNmatrx[0][2] * Norms[j][Z];
        xformNorms[j][Y] = tosNmatrx[1][0] * Norms[j][X] + tosNmatrx[1][1] * Norms[j][Y] + tosNmatrx[1][2] * Norms[j][Z];
        xformNorms[j][Z] = tosNmatrx[2][0] * Norms[j][X] + tosNmatrx[2][1] * Norms[j][Y] + tosNmatrx[2][2] * Norms[j][Z];
    }
    NormVector(xformNorms[0]);
    NormVector(xformNorms[1]);
    NormVector(xformNorms[2]);

    for (int i = 0; i < 3; i++) {
        xformcord[i][X] = xformcord[i][X] + render->dx;
        xformcord[i][Y] = xformcord[i][Y] + render->dy;
    }
    if (behind == true) {
        return GZ_SUCCESS;
    }
    if (rastlee(render, xformcord, xformNorms, Textcord)) {
        return GZ_SUCCESS;
    }


    return GZ_SUCCESS;
}
예제 #18
0
bool rastlee(GzRender* render, GzCoord* cord, GzCoord * norms, GzTextureIndex * Textcord) {

    //swap and sort Y of vertex

    //sort Y by ascending order

    for (int j = 0; j < 2; j++) {
        for (int k = 0; k < 2 - j; k++) {
            if (cord[k][Y]>cord[k + 1][Y]) {
                float tempx = cord[k][X];
                float tempy = cord[k][Y];
                float tempz = cord[k][Z];
                cord[k][X] = cord[k + 1][X];
                cord[k][Y] = cord[k + 1][Y];
                cord[k][Z] = cord[k + 1][Z];
                cord[k + 1][X] = tempx;
                cord[k + 1][Y] = tempy;
                cord[k + 1][Z] = tempz;

                float tempNx = norms[k][X];
                float tempNy = norms[k][Y];
                float tempNz = norms[k][Z];
                norms[k][X] = norms[k + 1][X];
                norms[k][Y] = norms[k + 1][Y];
                norms[k][Z] = norms[k + 1][Z];
                norms[k + 1][X] = tempNx;
                norms[k + 1][Y] = tempNy;
                norms[k + 1][Z] = tempNz;

                float tempU = Textcord[k][U];
                float tempV = Textcord[k][V];
                Textcord[k][U] = Textcord[k + 1][U];
                Textcord[k][V] = Textcord[k + 1][V];
                Textcord[k + 1][U] = tempU;
                Textcord[k + 1][V] = tempV;

            }
        }
    }


    // determine L/R CW
    //horizontal case have two top Y
    if (cord[0][Y] == cord[1][Y]) {
        if (cord[0][X] > cord[1][X]) {
            float tempx = cord[0][X];
            float tempy = cord[0][Y];
            float tempz = cord[0][Z];
            cord[0][X] = cord[1][X];
            cord[0][Y] = cord[1][Y];
            cord[0][Z] = cord[1][Z];
            cord[1][X] = tempx;
            cord[1][Y] = tempy;
            cord[1][Z] = tempz;

            float tempNx = norms[0][X];
            float tempNy = norms[0][Y];
            float tempNz = norms[0][Z];
            norms[0][X] = norms[1][X];
            norms[0][Y] = norms[1][Y];
            norms[0][Z] = norms[1][Z];
            norms[1][X] = tempNx;
            norms[1][Y] = tempNy;
            norms[1][Z] = tempNz;


            float tempU = Textcord[0][U];
            float tempV = Textcord[0][V];
            Textcord[0][U] = Textcord[1][U];
            Textcord[0][V] = Textcord[1][V];
            Textcord[1][U] = tempU;
            Textcord[1][V] = tempV;

        }

    }
    //horizontal case have two bot Y
    else if (cord[1][Y] == cord[2][Y]) {
        if (cord[2][X] > cord[1][X]) {
            float tempx = cord[2][X];
            float tempy = cord[2][Y];
            float tempz = cord[2][Z];
            cord[2][X] = cord[1][X];
            cord[2][Y] = cord[1][Y];
            cord[2][Z] = cord[1][Z];
            cord[1][X] = tempx;
            cord[1][Y] = tempy;
            cord[1][Z] = tempz;

            float tempNx = norms[2][X];
            float tempNy = norms[2][Y];
            float tempNz = norms[2][Z];
            norms[2][X] = norms[1][X];
            norms[2][Y] = norms[1][Y];
            norms[2][Z] = norms[1][Z];
            norms[1][X] = tempNx;
            norms[1][Y] = tempNy;
            norms[1][Z] = tempNz;

            float tempU = Textcord[2][U];
            float tempV = Textcord[2][V];
            Textcord[2][U] = Textcord[1][U];
            Textcord[2][V] = Textcord[1][V];
            Textcord[1][U] = tempU;
            Textcord[1][V] = tempV;
        }
    }

    //bound box
    int top = (int)floor(cord[0][Y]);
    int bot = (int)ceil(cord[2][Y]);
    int left = cord[0][X];
    int right = cord[2][X];

    for (int i = 0; i < 3; i++) {
        if (cord[i][X] < left)
            left = (int)floor(cord[i][X]);
        if (cord[i][X]>right)
            right = (int)ceil(cord[i][X]);
    }

    //interpolate z
    float interpz;
    GzCoord vec01, vec12;
    vec01[X] = cord[1][X] - cord[0][X];
    vec01[Y] = cord[1][Y] - cord[0][Y];
    vec01[Z] = cord[1][Z] - cord[0][Z];

    vec12[X] = cord[2][X] - cord[1][X];
    vec12[Y] = cord[2][Y] - cord[1][Y];
    vec12[Z] = cord[2][Z] - cord[1][Z];

    float A = vec01[Y] * vec12[Z] - vec01[Z] * vec12[Y];
    float B = vec01[Z] * vec12[X] - vec01[X] * vec12[Z];
    float C = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
    float D = -(A*cord[0][X] + B*cord[0][Y] + C*cord[0][Z]);



    //Gouraud shading
    GzColor goudinter;
    GzColor color0, color1, color2;
    /*
    ShadingEquation(render, color0, norms[0]);
    ShadingEquation(render, color1, norms[1]);
    ShadingEquation(render, color2, norms[2]);*/

    if (render->interp_mode == GZ_COLOR) {
        if (render->tex_fun == NULL) {
            ShadingEquation(render, color0, norms[0]);
            ShadingEquation(render, color1, norms[1]);
            ShadingEquation(render, color2, norms[2]);
        }
        else {//use texture function
            render->Ka[RED] =1;
            render->Ka[GREEN] =1;
            render->Ka[BLUE] = 1;

            render->Kd[RED] = 1;
            render->Kd[GREEN] =1;
            render->Kd[BLUE] = 1;

            render->Ks[RED] = 1;
            render->Ks[GREEN] =1;
            render->Ks[BLUE] = 1;
            ShadingEquation(render, color0, norms[0]);
            ShadingEquation(render, color1, norms[1]);
            ShadingEquation(render, color2, norms[2]);
        }
    }
    GzColor gA, gB, gC, gD;


    gA[RED] = vec01[Y] * (color2[RED] - color1[RED]) - (color1[RED] - color0[RED]) * vec12[Y];
    gB[RED] = (color1[RED] - color0[RED]) * vec12[X] - vec01[X] * (color2[RED] - color1[RED]);
    gC[RED] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
    gD[RED] = -(gA[RED]*cord[0][X] + gB[RED]*cord[0][Y] + gC[RED]*color0[RED]);

    gA[GREEN] = vec01[Y] * (color2[GREEN] - color1[GREEN]) - (color1[GREEN] - color0[GREEN]) * vec12[Y];
    gB[GREEN] = (color1[GREEN] - color0[GREEN]) * vec12[X] - vec01[X] * (color2[GREEN] - color1[GREEN]);
    gC[GREEN] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
    gD[GREEN] = -(gA[GREEN] * cord[0][X] + gB[GREEN] * cord[0][Y] + gC[GREEN] * color0[GREEN]);

    gA[BLUE] = vec01[Y] * (color2[BLUE] - color1[BLUE]) - (color1[BLUE] - color0[BLUE]) * vec12[Y];
    gB[BLUE] = (color1[BLUE] - color0[BLUE]) * vec12[X] - vec01[X] * (color2[BLUE] - color1[BLUE]);
    gC[BLUE] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
    gD[BLUE] = -(gA[BLUE] * cord[0][X] + gB[BLUE] * cord[0][Y] + gC[BLUE] * color0[BLUE]);

    //prepare for interp UV texture
    float Vzp;// Vz'
    GzTextureIndex*  perspTextcord = new GzTextureIndex[3];//warp uv-> UV from image space to perspective space for each vertex
    for (int k = 0; k < 3; k++) {

        Vzp = cord[k][Z] / (INT_MAX - cord[k][Z]);
        perspTextcord[k][U] = Textcord[k][U] / (Vzp + 1);
        perspTextcord[k][V] = Textcord[k][V] / (Vzp + 1);
    }



    //if in bbox draw pixel
    for (int i = left; i < right; i++) {
        if (i<0 || i>render->display->xres) {
            continue;
        }
        for (int j = top; j < bot; j++) {
            if (j<0 || j>render->display->yres) {
                continue;
            }

            float a01 = cord[1][Y] - cord[0][Y];
            float a12 = cord[2][Y] - cord[1][Y];
            float a20 = cord[0][Y] - cord[2][Y];
            float b01 = -(cord[1][X] - cord[0][X]);
            float b12 = -(cord[2][X] - cord[1][X]);
            float b20 = -(cord[0][X] - cord[2][X]);
            float c01 = -b01*cord[0][Y] - a01*cord[0][X];
            float c12 = -b12*cord[1][Y] - a12*cord[1][X];
            float c20 = -b20*cord[2][Y] - a20*cord[2][X];

            float e01 = a01*(float)i + b01*(float)j + c01;
            float e12 = a12*(float)i + b12*(float)j + c12;
            float e20 = a20*(float)i + b20*(float)j + c20;

            if ((e01 == 0 || e12 == 0 || e20 == 0)||((e01 > 0) && (e12 > 0) && (e20 > 0)) ||
                    ((e01 < 0) && (e12 < 0) && (e20 < 0))) {

                interpz = (-(A*i) - (B*j) - D) / C;
                GzIntensity r, g, b, a;
                GzDepth z;

                GzGetDisplay(render->display, i, j, &r, &g, &b, &a, &z);

                if (interpz < z) {
                    GzCoord pers01, pers12;
                    pers01[U] = perspTextcord[1][U] - perspTextcord[0][U];
                    pers01[V] = perspTextcord[1][V] - perspTextcord[0][V];

                    pers12[U] = perspTextcord[2][U] - perspTextcord[1][U];
                    pers12[V] = perspTextcord[2][V] - perspTextcord[1][V];


                    //	GzCoord intepcrossprod;
                    //crossvector(pers01, pers12, intepcrossprod);

                    GzTextureIndex tA, tB, tC, tD, textureinter, newuv;
                    tA[U] = vec01[Y] * (pers12[U]) - (pers01[U]) * vec12[Y];
                    tB[U] = (pers01[U]) * vec12[X] - vec01[X] * (pers12[U]);
                    tC[U] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
                    tD[U] = -(tA[U] * cord[0][X] + tB[U] * cord[0][Y] + tC[U] * perspTextcord[0][U]);

                    tA[V] = vec01[Y] * (pers12[V]) - (pers01[V]) * vec12[Y];
                    tB[V] = (pers01[V]) * vec12[X] - vec01[X] * (pers12[V]);
                    tC[V] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
                    tD[V] = -(tA[V] * cord[0][X] + tB[V] * cord[0][Y] + tC[V] * perspTextcord[0][V]);
                    // interpolateUV to pixel
                    /*textureinter[U] = -(tA[U] * i + tB[U] * j + tD[U]) / tC[U];
                    textureinter[V] = -(tA[V] * i + tB[V] * j + tD[V]) / tC[V];*/
                    textureinter[U] = interpolate(tA[U], tB[U], tC[U], tD[U], i, j);
                    textureinter[V] = interpolate(tA[V], tB[V], tC[V], tD[V], i, j);
                    //unwarping
                    float Vzp = interpz / (INT_MAX - interpz);
                    newuv[U] = textureinter[U] * (Vzp + 1);
                    newuv[V] = textureinter[V] * (Vzp + 1);

                    //texture color lookup with bilinear interpolation
                    GzColor texColor;
                    if (render->tex_fun != NULL) {
                        render->tex_fun(newuv[U], newuv[V], texColor);
                    }
                    switch (render->interp_mode) {
                    case GZ_FLAT:
                        r = (GzIntensity)ctoi((float)render->flatcolor[0]);
                        g = (GzIntensity)ctoi((float)render->flatcolor[1]);
                        b = (GzIntensity)ctoi((float)render->flatcolor[2]);
                        z = interpz;
                        break;
                    case GZ_COLOR://ground shading


                        render->Ka[RED] = texColor[RED];
                        render->Ka[GREEN] = texColor[GREEN];
                        render->Ka[BLUE] = texColor[BLUE];
                        render->Kd[RED] = texColor[RED];
                        render->Kd[GREEN] = texColor[GREEN];
                        render->Kd[BLUE] = texColor[BLUE];
                        render->Ks[RED] = texColor[RED];
                        render->Ks[GREEN] = texColor[GREEN];
                        render->Ks[BLUE] = texColor[BLUE];


                        goudinter[RED] = -(gA[RED] * i + gB[RED] * j + gD[RED]) / gC[RED];
                        goudinter[GREEN] = -(gA[GREEN] * i + gB[GREEN] * j + gD[GREEN]) / gC[GREEN];
                        goudinter[BLUE] = -(gA[BLUE] * i + gB[BLUE] * j + gD[BLUE]) / gC[BLUE];

                        //texture color
                        if (render->tex_fun != NULL) {
                            goudinter[RED] *= texColor[RED] ;
                            goudinter[GREEN] *= texColor[GREEN];
                            goudinter[BLUE] *= texColor[BLUE];
                        }

                        if (goudinter[RED] > 1.0) goudinter[RED] = 1.0;
                        if (goudinter[GREEN] > 1.0) goudinter[GREEN] = 1.0;
                        if (goudinter[BLUE] > 1.0) goudinter[BLUE] = 1.0;
                        r = (GzIntensity)ctoi(goudinter[RED]);
                        g = (GzIntensity)ctoi(goudinter[GREEN]);
                        b = (GzIntensity)ctoi(goudinter[BLUE]);
                        z = interpz;
                        break;

                    case GZ_NORMALS:
                        //interpolizing norms;
                        GzColor pA, pB, pC, pD;
                        pA[RED] = vec01[Y] * (norms[2][RED] - norms[1][RED]) - (norms[1][RED] - norms[0][RED]) * vec12[Y];
                        pB[RED] = (norms[1][RED] - norms[0][RED]) * vec12[X] - vec01[X] * (norms[2][RED] - norms[1][RED]);
                        pC[RED] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
                        pD[RED] = -(pA[RED] * cord [0][X] + pB[RED] * cord[0][Y] + pC[RED] * norms[0][RED]);

                        pA[GREEN] = vec01[Y] * (norms[2][GREEN] - norms[1][GREEN]) - (norms[1][GREEN] - norms[0][GREEN]) * vec12[Y];
                        pB[GREEN] = (norms[1][GREEN] - norms[0][GREEN]) * vec12[X] - vec01[X] * (norms[2][GREEN] - norms[1][GREEN]);
                        pC[GREEN] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
                        pD[GREEN] = -(pA[GREEN] * cord[0][X] + pB[GREEN] * cord[0][Y] + pC[GREEN] * norms[0][GREEN]);

                        pA[BLUE] = vec01[Y] * (norms[2][BLUE] - norms[1][BLUE]) - (norms[1][BLUE] - norms[0][BLUE]) * vec12[Y];
                        pB[BLUE] = (norms[1][BLUE] - norms[0][BLUE]) * vec12[X] - vec01[X] * (norms[2][BLUE] - norms[1][BLUE]);
                        pC[BLUE] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X];
                        pD[BLUE] = -(pA[BLUE] * cord[0][X] + pB[BLUE] * cord[0][Y] + pC[BLUE] * norms[0][BLUE]);

                        GzColor phonginter;

                        phonginter[0] = -(pA[0] * i + pB[0] * j + pD[0]) / pC[0];
                        phonginter[1] = -(pA[1] * i + pB[1] * j + pD[1]) / pC[1];
                        phonginter[2] = -(pA[2] * i + pB[2] * j + pD[2]) / pC[2];
                        NormVector(phonginter);

                        //Then shading calculation with texture color used as Kd and Ka
                        if (render->tex_fun != NULL) {
                            render->Ka[RED] = render->Kd[RED] = texColor[RED];
                            render->Ka[GREEN] = render->Kd[GREEN] = texColor[GREEN];
                            render->Ka[BLUE] = render->Kd[BLUE] = texColor[BLUE];
                        }
                        GzColor colorpix;
                        ShadingEquation(render, colorpix, phonginter);
                        r = (GzIntensity)ctoi(colorpix[RED]);
                        g = (GzIntensity)ctoi(colorpix[GREEN]);
                        b = (GzIntensity)ctoi(colorpix[BLUE]);
                        z = interpz;

                        break;
                    }
                    GzPutDisplay(render->display, i, j, r, g, b, a, z);
                }
            }


        }

    }
    return true;
}
예제 #19
0
// --------------------------------------------------------------------
//                      add_track_mark
// --------------------------------------------------------------------
void add_track_mark(const CControl *ctrl, int *id) {
    if (param.perf_level < 3)
		return;

	TTerrType *TerrList = &Course.TerrList[0];

	*id = Course.GetTerrainIdx (ctrl->cpos.x, ctrl->cpos.z, 0.5);
	if (*id < 1) {
		break_track_marks();
		return;
	}

	if (!TerrList[*id].trackmarks) {
		break_track_marks();
		return;
	}

	TVector3 vel = ctrl->cvel;
    double speed = NormVector (vel);
    if (speed < SPEED_TO_START_TRENCH) {
		break_track_marks();
		return;
    }

    TVector3 width_vector = CrossProduct (ctrl->cdirection, TVector3 (0, 1, 0));
    double magnitude = NormVector (width_vector);
    if (magnitude == 0) {
		break_track_marks();
		return;
    }

    TVector3 left_vector = ScaleVector (TRACK_WIDTH/2.0, width_vector);
    TVector3 right_vector = ScaleVector (-TRACK_WIDTH/2.0, width_vector);
    TVector3 left_wing =  SubtractVectors (ctrl->cpos, left_vector);
    TVector3 right_wing = SubtractVectors (ctrl->cpos, right_vector);
    double left_y = Course.FindYCoord (left_wing.x, left_wing.z);
    double right_y = Course.FindYCoord (right_wing.x, right_wing.z);

	if (fabs(left_y-right_y) > MAX_TRACK_DEPTH) {
		break_track_marks();
		return;
    }

    TPlane surf_plane = Course.GetLocalCoursePlane (ctrl->cpos);
    double dist_from_surface = DistanceToPlane (surf_plane, ctrl->cpos);
	// comp_depth = get_compression_depth(Snow);
	double comp_depth = 0.1;
    if (dist_from_surface >= (2 * comp_depth)) {
		break_track_marks();
		return;
    }

	if(track_marks.quads.size() < MAX_TRACK_MARKS)
		track_marks.quads.push_back(track_quad_t());
	list<track_quad_t>::iterator qprev = track_marks.current_mark;
	if(track_marks.current_mark == track_marks.quads.end())
		track_marks.current_mark = track_marks.quads.begin();
	else
		track_marks.current_mark = incrementRingIterator(track_marks.current_mark);
	list<track_quad_t>::iterator q = track_marks.current_mark;

    if (!continuing_track) {
		q->track_type = TRACK_HEAD;
		q->v1 = TVector3 (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z);
		q->v2 = TVector3 (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z);
		q->v3 = TVector3 (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z);
		q->v4 = TVector3 (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z);
		q->n1 = Course.FindCourseNormal (q->v1.x, q->v1.z);
		q->n2 = Course.FindCourseNormal (q->v2.x, q->v2.z);
		q->t1 = TVector2(0.0, 0.0);
		q->t2 = TVector2(1.0, 0.0);
    } else {
		q->track_type = TRACK_TAIL;
		if (qprev != track_marks.quads.end()) {
		    q->v1 = qprev->v3;
	    	q->v2 = qprev->v4;
		    q->n1 = qprev->n3;
		    q->n2 = qprev->n4;
		    q->t1 = qprev->t3;
		    q->t2 = qprev->t4;
	if (qprev->track_type == TRACK_TAIL) qprev->track_type = TRACK_MARK;
		}
		q->v3 = TVector3 (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z);
		q->v4 = TVector3 (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z);
		q->n3 = Course.FindCourseNormal (q->v3.x, q->v3.z);
		q->n4 = Course.FindCourseNormal (q->v4.x, q->v4.z);
		double tex_end = speed*g_game.time_step/TRACK_WIDTH;
		if (q->track_type == TRACK_HEAD) {
		    q->t3= TVector2 (0.0, 1.0);
		    q->t4= TVector2 (1.0, 1.0);
		} else {
		    q->t3 = TVector2 (0.0, q->t1.y + tex_end);
		    q->t4 = TVector2 (1.0, q->t2.y + tex_end);
		}
    }
    q->alpha = min ((2*comp_depth-dist_from_surface)/(4*comp_depth), 1.0);
    continuing_track = true;
}
예제 #20
0
void CCourse::CalcNormals () {
	for (int y=0; y<ny; y++) {
        for (int x=0; x<nx; x++) {
            TVector3 nml(0.0, 0.0, 0.0);
            TVector3 p0 (XCD(x), ELEV(x,y), ZCD(y));

			if ((x + y) % 2 == 0) {
				if (x > 0 && y > 0) {
					TVector3 p1 = NMLPOINT(x,  y-1);
					TVector3 p2 = NMLPOINT(x-1,y-1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);

					p1 = NMLPOINT (x-1, y-1);
					p2 = NMLPOINT (x-1, y);
					v1 = SubtractVectors (p1, p0);
					v2 = SubtractVectors (p2, p0);
					n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x > 0 && y < ny-1) {
					TVector3 p1 = NMLPOINT(x-1,y);
					TVector3 p2 = NMLPOINT(x-1,y+1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);

					p1 = NMLPOINT(x-1,y+1);
					p2 = NMLPOINT(x  ,y+1);
					v1 = SubtractVectors (p1, p0);
					v2 = SubtractVectors (p2, p0);
					n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x < nx-1 && y > 0) {
					TVector3 p1 = NMLPOINT(x+1,y);
					TVector3 p2 = NMLPOINT(x+1,y-1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);

					p1 = NMLPOINT(x+1,y-1);
					p2 = NMLPOINT(x  ,y-1);
					v1 = SubtractVectors (p1, p0);
					v2 = SubtractVectors (p2, p0);
					n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x < nx-1 && y < ny-1) {
					TVector3 p1 = NMLPOINT(x+1,y);
					TVector3 p2 = NMLPOINT(x+1,y+1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v1, v2);

					NormVector (n);
					nml = AddVectors (nml, n);

					p1 = NMLPOINT(x+1,y+1);
					p2 = NMLPOINT(x  ,y+1);
					v1 = SubtractVectors (p1, p0);
					v2 = SubtractVectors (p2, p0);
					n = CrossProduct (v1, v2);

					NormVector (n);
					nml = AddVectors (nml, n);

				}
			} else {
				if (x > 0 && y > 0) {
					TVector3 p1 = NMLPOINT(x,  y-1);
					TVector3 p2 = NMLPOINT(x-1,y);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x > 0 && y < ny-1) {
					TVector3 p1 = NMLPOINT(x-1,y);
					TVector3 p2 = NMLPOINT(x  ,y+1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x < nx-1 && y > 0) {
					TVector3 p1 = NMLPOINT(x+1,y);
					TVector3 p2 = NMLPOINT(x  ,y-1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x < nx-1 && y < ny-1) {
					TVector3 p1 = NMLPOINT(x+1,y);
					TVector3 p2 = NMLPOINT(x  ,y+1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v1, v2);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
			}
            NormVector (nml);
			nmls [x + nx * y] = nml;
            continue;

		}
    }
}
예제 #21
0
std::unique_ptr<Mesh> MeshUtility::MakeSphere(float radius, unsigned int subdivisions)
{
   if (subdivisions > ModelUtility::MAX_SPHERE_SUBDIVISIONS)
   {
      subdivisions = ModelUtility::MAX_SPHERE_SUBDIVISIONS;
   }

   std::unique_ptr<Mesh> octahedron = MeshUtility::MakeOctahedron(radius);

   std::vector<Triangle3D_t> initialTriangles;

   Transformation identity;

   for (std::size_t iFace = 0, numFaces = octahedron->NumFaces(); iFace < numFaces; ++iFace)
   {
      initialTriangles.push_back(octahedron->GetFaceTriangle(iFace, identity));
   }

   std::vector<Triangle3D_t> subdividedTriangles;

   for (const Triangle3D_t& triangle : initialTriangles)
   {
      ModelUtility::SubdivideTriangle(triangle, subdividedTriangles, subdivisions);
   }

   std::vector<std::vector<MeshVertex>> trianglesOnSphere;
   trianglesOnSphere.reserve(subdividedTriangles.size());

   std::vector<MeshVertex> triangleOnSphere(3, MeshVertex(Color::White(), Locus::TextureCoordinate()));

   Plane fixSmearPlane(Vec3D::ZeroVector(), Vec3D::NegativeZAxis());

   for (const Triangle3D_t& triangle : subdividedTriangles)
   {
      for (std::size_t i = 0; i < Triangle3D_t::NumPointsOnATriangle; ++i)
      {
         triangleOnSphere[i].position = NormVector(triangle[i]) * radius;
         triangleOnSphere[i].textureCoordinate = MeshUtility::SphericalUVMapping(triangleOnSphere[i].position);
      }

      //
      //HACK: fixing smearing that occurs at the boundary where U = 0.0 or 1.0. The
      //spherical UV mapping algorithm always returns U = 1.0 at the boundary. Here
      //we find if the triangle that was just generated is at this boundary. The "real"
      //way to do it would be to unwrap the sphere or make a UV sphere.
      //
      Plane::IntersectionQuery intersectionQuery = fixSmearPlane.triangleIntersectionTest(triangle);
      if ((intersectionQuery == Plane::IntersectionQuery::None) || (intersectionQuery == Plane::IntersectionQuery::Positive))
      {
         for (std::size_t i = 0; i < Triangle3D_t::NumPointsOnATriangle; ++i)
         {
            if (FEqual<float>(triangleOnSphere[i].textureCoordinate.x, 1.0f))
            {
               triangleOnSphere[i].textureCoordinate.x = 0.0f;
            }
         }
      }

      trianglesOnSphere.push_back(triangleOnSphere);
   }

   return std::make_unique<Mesh>(trianglesOnSphere);
}
예제 #22
0
int ShadingEquation(GzRender *render, GzColor color, GzCoord norm) {
    NormVector(norm);//normalize vector
    GzCoord  E = { 0.0, 0.0, -1.0 };
    GzCoord* R = new GzCoord[render->numlights];
    NormVector(E);
    //N*L
    float NdotE;
    int* testN = new int[render->numlights];
    float* NdotL = new float[render->numlights];
    float* negNdotL = new float[render->numlights];
    float* RdotE = new float[render->numlights];


    GzCoord negN = { -norm[X], -norm[Y], -norm[Z] };

    NdotE = dotvector(norm, E);
    //compute R
    for (int i = 0; i < render->numlights; i++) {
        NdotL[i] = dotvector(norm, render->lights[i].direction);
        negNdotL[i] = dotvector(negN, render->lights[i].direction);
        if (NdotL[i] >= 0 && NdotE >= 0) {
            //compute lighting model
            //R = 2(NdotL)N-L
            R[i][X] = 2 * NdotL[i]*norm[X] - render->lights[i].direction[X];
            R[i][Y] = 2 * NdotL[i]*norm[Y] - render->lights[i].direction[Y];
            R[i][Z] = 2 * NdotL[i]*norm[Z] - render->lights[i].direction[Z];
            NormVector(R[i]);
            testN[i] = 0;
        }
        else if (NdotL[i] < 0 && NdotE < 0) {
            //flip N and compute backside
            R[i][X] = 2 * negNdotL[i] * (-norm[X]) - render->lights[i].direction[X];
            R[i][Y] = 2 * negNdotL[i] * (-norm[Y]) - render->lights[i].direction[Y];
            R[i][Z] = 2 * negNdotL[i] * (-norm[Z]) - render->lights[i].direction[Z];
            NormVector(R[i]);
            testN[i] = 1;
        }
        else {
            //skip
            testN[i] = 2;
        }
    }
    //compute Spectical light part
    GzColor specSum = { 0, 0, 0 };
    for (int i = 0; i < render->numlights; i++) {
        RdotE[i] = dotvector(R[i], E);
        if (testN[i] != 2) {
            assert(abs(dotvector(R[i], R[i]) - 1) < 0.00001);
            if (RdotE[i] < 0)
                RdotE[i] = 0;
            if (RdotE[i] > 1)
                RdotE[i] = 1;
            specSum[RED] += render->lights[i].color[RED] * pow(RdotE[i], render->spec);
            specSum[GREEN] += render->lights[i].color[GREEN] * pow(RdotE[i], render->spec);
            specSum[BLUE] += render->lights[i].color[BLUE] * pow(RdotE[i], render->spec);
        }
    }
    GzColor specpart;
    specpart[RED] = render->Ks[RED] * specSum[RED];
    specpart[GREEN] = render->Ks[GREEN] * specSum[GREEN];
    specpart[BLUE] = render->Ks[BLUE] * specSum[BLUE];

    //compute diffusion part
    GzColor diffSum = { 0, 0, 0 };
    for (int i = 0; i < render->numlights; i++) {
        if (testN[i] == 2)continue;
        if (testN[i] == 0) {
            //both positive
            diffSum[RED] += render->lights[i].color[RED] * NdotL[i];
            diffSum[GREEN] += render->lights[i].color[GREEN] * NdotL[i];
            diffSum[BLUE] += render->lights[i].color[BLUE] * NdotL[i];
        }
        if (testN[i] == 1) {
            //both negative
            diffSum[RED] += render->lights[i].color[RED] * negNdotL[i];
            diffSum[GREEN] += render->lights[i].color[GREEN] * negNdotL[i];
            diffSum[BLUE] += render->lights[i].color[BLUE] * negNdotL[i];
        }

    }
    GzColor diffpart;
    diffpart[RED] = render->Kd[RED] * diffSum[RED];
    diffpart[GREEN] = render->Kd[GREEN] * diffSum[GREEN];
    diffpart[BLUE] = render->Kd[BLUE] * diffSum[BLUE];

    //compute ambient part

    GzColor ambpart;

    ambpart[RED] = render->Ka[RED] * render->ambientlight.color[RED];
    ambpart[GREEN] = render->Ka[GREEN] * render->ambientlight.color[GREEN];
    ambpart[BLUE] = render->Ka[BLUE] * render->ambientlight.color[BLUE];


    //calculate c
    color[RED] = specpart[RED] + diffpart[RED] + ambpart[RED];
    color[GREEN] = specpart[GREEN] + diffpart[GREEN] + ambpart[GREEN];
    color[BLUE] = specpart[BLUE] + diffpart[BLUE] + ambpart[BLUE];

    delete[] testN;
    delete[] NdotL;
    delete[] negNdotL;
    delete[] RdotE;
    delete[] R;

    return GZ_SUCCESS;

}
예제 #23
0
// --------------------------------------------------------------------
//                      add_track_mark
// --------------------------------------------------------------------
void add_track_mark (CControl *ctrl, int *id) {
    TVector3 width_vector;
    TVector3 left_vector;
    TVector3 right_vector;
    double magnitude;
    track_quad_t *q, *qprev, *qprevprev;
    TVector3 vel;
    double speed;
    TVector3 left_wing, right_wing;
    double left_y, right_y;
    double dist_from_surface;
    TPlane surf_plane;
    double comp_depth;
    double tex_end;
    double dist_from_last_mark;
    TVector3 vector_from_last_mark;
	TTerrType *TerrList = Course.TerrList;

    if (param.perf_level < 3) return;

    q = &track_marks.quads[track_marks.current_mark%MAX_TRACK_MARKS];
    qprev = &track_marks.quads[(track_marks.current_mark-1)%MAX_TRACK_MARKS];
    qprevprev = &track_marks.quads[(track_marks.current_mark-2)%MAX_TRACK_MARKS];

    vector_from_last_mark = SubtractVectors (ctrl->cpos, track_marks.last_mark_pos);
    dist_from_last_mark = NormVector (&vector_from_last_mark);
	
	*id = Course.GetTerrainIdx (ctrl->cpos.x, ctrl->cpos.z, 0.5);
	if (*id < 1) {
		break_track_marks();
		return;
	} 

	if (TerrList[*id].trackmarks < 1) {
		break_track_marks();
		return;
	} 
    
	vel = ctrl->cvel;
    speed = NormVector (&vel);
    if (speed < SPEED_TO_START_TRENCH) {
		break_track_marks();
		return;
    }

    width_vector = CrossProduct (ctrl->cdirection, MakeVector (0, 1, 0));
    magnitude = NormVector (&width_vector);
    if  (magnitude == 0) {
		break_track_marks();
		return;
    }

    left_vector = ScaleVector (TRACK_WIDTH/2.0, width_vector);
    right_vector = ScaleVector (-TRACK_WIDTH/2.0, width_vector);
    left_wing =  SubtractVectors (ctrl->cpos, left_vector);
    right_wing = SubtractVectors (ctrl->cpos, right_vector);
    left_y = Course.FindYCoord (left_wing.x, left_wing.z);
    right_y = Course.FindYCoord (right_wing.x, right_wing.z);
    
	if (fabs(left_y-right_y) > MAX_TRACK_DEPTH) {
		break_track_marks();
		return;
    }

    surf_plane = Course.GetLocalCoursePlane (ctrl->cpos);
    dist_from_surface = DistanceToPlane (surf_plane, ctrl->cpos);
	// comp_depth = get_compression_depth(Snow);
	comp_depth = 0.1;
    if  (dist_from_surface >= (2 * comp_depth)) {
		break_track_marks();
		return;
    }

    if (!continuing_track) {
		break_track_marks();
		q->track_type = TRACK_HEAD;
		q->v1 = MakeVector (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z);
		q->v2 = MakeVector (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z);
		q->n1 = Course.FindCourseNormal (q->v1.x, q->v1.z);
		q->n2 = Course.FindCourseNormal (q->v2.x, q->v2.z);
		q->t1 = MakeVector2(0.0, 0.0);
		q->t2 = MakeVector2(1.0, 0.0);
		track_marks.next_mark = track_marks.current_mark + 1;
    } else {
		if  (track_marks.next_mark == track_marks.current_mark) {
		    q->v1 = qprev->v3;
	    	q->v2 = qprev->v4;
		    q->n1 = qprev->n3;
		    q->n2 = qprev->n4;
		    q->t1 = qprev->t3; 
		    q->t2 = qprev->t4;
	    	if (qprev->track_type != TRACK_HEAD) qprev->track_type = TRACK_MARK;
	    	q->track_type = TRACK_MARK;
		}
		q->v3 = MakeVector (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z);
		q->v4 = MakeVector (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z);
		q->n3 = Course.FindCourseNormal (q->v3.x, q->v3.z);
		q->n4 = Course.FindCourseNormal (q->v4.x, q->v4.z);
		tex_end = speed*g_game.time_step/TRACK_WIDTH;
		if (q->track_type == TRACK_HEAD) {
		    q->t3= MakeVector2 (0.0, 1.0);
		    q->t4= MakeVector2 (1.0, 1.0);
		} else {
		    q->t3 = MakeVector2 (0.0, q->t1.y + tex_end);
		    q->t4 = MakeVector2 (1.0, q->t2.y + tex_end);
		}
		track_marks.current_mark++;
		track_marks.next_mark = track_marks.current_mark;
    }
    q->alpha = min ((2*comp_depth-dist_from_surface)/(4*comp_depth), 1.0);
    track_marks.last_mark_time = g_game.time;
    continuing_track = true;
}