// returns the normalized direction from 2 points (p1, p2) // projected on the surface // in direction from p1 -> p2 Vector3 Terrain::GetDirection(Vector3 p1, Vector3 p2) { Vector3 dir; GetTerrainPoint(&p1, p1.x, p1.z); GetTerrainPoint(&p2, p2.x, p2.z); dir = Subtract(p2, p1); dir.normalize(); return dir; }
void Terrain::ReInit( Vector3 *v0P, Vector3 *v1P, Vector3 *v2P, Vector3 *v3P ) { int i, j, k; v0 = *v0P; v1 = *v1P; v2 = *v2P; v3 = *v3P; dv = Subtract(v2, v0); dv.x /= float(widthVertices - 1); dv.y /= 1; dv.z /= float(heightVertices - 1); for (j=0, k=0; j<heightVertices; j++) { for (i=0; i<widthVertices; i++, k++) { GetTerrainPoint(&(vertices[k]), float(v0.x + i * dv.x), float(v0.z + j * dv.z)); GetTerrainNormal(&(normals[k]), &(vertices[k])); //vertices[k].u = float(i); //vertices[k].v = float(j); //vertices[k].color = D3DCOLOR_ARGB(0,255,255,255); } } }
void Terrain::GetTerrainNormal( Vector3 *n, Vector3 *pt) { Vector3 a, b; Vector3 temp; float dx, dz; // make deltas 1% of each cell dx = (v2.x - v0.x) / maxWidthVertices / 100; dz = (v2.z - v0.z) / maxHeightVertices / 100; GetTerrainPoint(&temp, pt->x, pt->z); GetTerrainPoint(&a, pt->x + dx, pt->z); a = Subtract(a, temp); GetTerrainPoint(&b, pt->x, pt->z + dz); b = Subtract(b, temp); *n = CrossProduct(a, b); n->normalize(); }
fix GetAvgTerrainLight (int i, int j) { vmsVector pp, p [6]; fix light, totalLight; int n; GetTerrainPoint (&pp, i, j); GetTerrainPoint (p, i - 1, j); GetTerrainPoint (p + 1, i, j - 1); GetTerrainPoint (p + 2, i + 1, j - 1); GetTerrainPoint (p + 3, i + 1, j); GetTerrainPoint (p + 4, i, j + 1); GetTerrainPoint (p + 5, i - 1, j + 1); for (n = 0, totalLight = 0; n < 6; n++) { light = abs (GetTerrainFaceLight (&pp, p + n, p + (n + 1) % 6)); if (light > 0) totalLight += light; } return totalLight / 6; }
fix GetAvgTerrainLight (int i, int j) { vms_vector pp, p [6]; fix sum, light; int f; GetTerrainPoint (&pp, i, j); GetTerrainPoint (p, i-1, j); GetTerrainPoint (p + 1, i, j-1); GetTerrainPoint (p + 2, i+1, j-1); GetTerrainPoint (p + 3, i+1, j); GetTerrainPoint (p + 4, i, j+1); GetTerrainPoint (p + 5, i-1, j+1); for (f = 0, sum = 0; f < 6; f++) { light = GetTerrainFaceLight (&pp, p + f, p + (f + 1) % 5); if (light < 0) sum -= light; else sum += light; } return sum / 6; }
// given a point, this method will return a translation vector // that will move the point back inside the terrain boundary // including vertical y direction (above the surface) Vector3 Terrain::GetCorrection(Vector3 pt) { Vector3 result; Vector3 surfacePt; result.set(0, 0, 0); // check all 4 sides of pool table: +x, -x, +z, -z if (pt.x >= v2.x) { result.x = v2.x - pt.x; } if (pt.x <= v0.x) { result.x = v0.x - pt.x; } if (pt.z >= v0.z) { result.z = v0.z - pt.z; } if (pt.z <= v2.z) { result.z = v2.z - pt.z; } // check vertical y direction GetTerrainPoint(&surfacePt, pt.x, pt.z); if (pt.y < surfacePt.y) { result.y = surfacePt.y - pt.y; } return result; }
Terrain::Terrain( int maxWidthVerticesP, int maxHeightVerticesP, Vector3 *v0P, Vector3 *v1P, Vector3 *v2P, Vector3 *v3P ) { int i, j, k; maxWidthVertices = maxWidthVerticesP; maxHeightVertices = maxHeightVerticesP; widthVertices = maxWidthVertices; heightVertices = maxHeightVertices; numVertices = widthVertices * heightVertices; widthFaces = widthVertices - 1; heightFaces = heightVertices - 1; numFaces = widthFaces * heightFaces * 2; // 2 triangles in each Terrain cell v0 = *v0P; v1 = *v1P; v2 = *v2P; v3 = *v3P; dv = Subtract(v2, v0); dv.x /= float(widthVertices - 1); dv.y /= 1; dv.z /= float(heightVertices - 1); // set up the vertex and normal and texture data vertices = new Vector3[numVertices]; normals = new Vector3[numVertices]; for (j=0, k=0; j<heightVertices; j++) { for (i=0; i<widthVertices; i++, k++) { GetTerrainPoint(&(vertices[k]), float(v0.x + i * dv.x), float(v0.z + j * dv.z)); GetTerrainNormal(&(normals[k]), &(vertices[k])); //vertices[k].u = float(i); //vertices[k].v = float(j); //vertices[k].color = D3DCOLOR_ARGB(0,255,255,255); } } // set up the index data faceData = new int[numFaces * 3]; // note opengl uses a CCW winding order // vertices 0, 1, 2, 3 are now in the following configuration // 2 3 // // // 0 1 for (j=0, k=0; j < heightFaces; j++) { for (i=0; i < widthFaces; i++) { faceData[k++] = j*widthVertices + i; // vertex 0 faceData[k++] = j*widthVertices + i+1; // vertex 1 faceData[k++] = (j+1)*widthVertices + i+1; // vertex 3 faceData[k++] = j*widthVertices + i; // vertex 0 faceData[k++] = (j+1)*widthVertices + i+1; // vertex 3 faceData[k++] = (j+1)*widthVertices + i; // vertex 2 } } }