GLfloat getHeight(TextureData *tex,GLfloat x, GLfloat z) { GLfloat xmin = floor(x); GLfloat xmax = ceil(x); GLfloat zmin = floor(z); GLfloat zmax = ceil(z); GLfloat xdec = x - xmin; GLfloat zdec = z - zmin; GLfloat ybl = tex->imageData[((int)xmin + (int)zmin * tex->width) * (tex->bpp/8)] / 10.0; GLfloat ytl = tex->imageData[((int)xmin + (int)zmax * tex->width) * (tex->bpp/8)] / 10.0; GLfloat ybr = tex->imageData[((int)xmax + (int)zmin * tex->width) * (tex->bpp/8)] / 10.0; GLfloat ytr = tex->imageData[((int)xmax + (int)zmax * tex->width) * (tex->bpp/8)] / 10.0; vec3 pbl = SetVector(xmin,ybl,zmin); vec3 ptl = SetVector(xmin,ytl,zmax); vec3 pbr = SetVector(xmax,ybr,zmin); vec3 ptr = SetVector(xmax,ytr,zmax); vec3 NV; if ( (xdec + zdec) > 1) { vec3 p1 = SetVector(xmin,ytl,zmax); vec3 p2 = SetVector(xmax,ytr,zmax); vec3 p3 = SetVector(xmax,ybr,zmin); NV = Normalize(CalcNormalVector(p1,p2,p3)); } else { vec3 p1 = SetVector(xmin,ytl,zmax); vec3 p2 = SetVector(xmin,ybl,zmin); vec3 p3 = SetVector(xmax,ybr,zmin); NV = Normalize(CalcNormalVector(p1,p2,p3)); } //Use plane equation. Find D with one of the points. //Why is ptl better than pbl? GLfloat D = NV.x * ptl.x + NV.y * ptl.y + NV.z * ptl.z; GLfloat yint = (D - NV.x * x - NV.z * z) / NV.y; return yint; }
GLfloat GetMapHeight(Model* tm, int texWidth, int texHeight, GLfloat x, GLfloat z) { if (x < 0 || z < 0 || z > texHeight - 1 || x > texWidth - 1) return 0; GLfloat height; // Find quad int x1 = (int) (x * X_SCALE); int x2 = x1 + 1; int z1 = (int) (z * Z_SCALE); int z2 = z1 + 1; GLfloat x1f = x1/X_SCALE; GLfloat x2f = x2/X_SCALE; GLfloat z1f = z1/Z_SCALE; GLfloat z2f = z2/Z_SCALE; // Find triangle GLfloat D; vec3 p1,p2,p3,n; if ( (x - x1f) + (z - z1f) > 1) { p1 = (vec3){x2f, tm->vertexArray[(x2 + z1 * texWidth)*3 + 1], z1f}; p2 = (vec3){x1f, tm->vertexArray[(x1 + z2 * texWidth)*3 + 1], z2f}; p3 = (vec3){x2f, tm->vertexArray[(x2 + z2 * texWidth)*3 + 1], z2f}; n = CalcNormalVector(p1,p2,p3); D = DotProduct(p1,n); height = - (n.x * x + n.z * z - D) / n.y; } else { p1 = (vec3){x1f, tm->vertexArray[(x1 + z1 * texWidth)*3 + 1], z1f}; p2 = (vec3){x1f, tm->vertexArray[(x1 + z2 * texWidth)*3 + 1], z2f}; p3 = (vec3){x2f, tm->vertexArray[(x2 + z1 * texWidth)*3 + 1], z1f}; n = CalcNormalVector(p1,p2,p3); D = DotProduct(p1,n); height = - (n.x * x + n.z * z - D) / n.y; } //printf("x, x1: %f, %d z, z1: %f, %d, h=%f\n", x, x1, z, z1, height); return height; }
Model* GenerateTerrain(TextureData *tex) { int vertexCount = tex->width * tex->height; int triangleCount = (tex->width-1) * (tex->height-1) * 2; int x, z; GLfloat *vertexArray = malloc(sizeof(GLfloat) * 3 * vertexCount); GLfloat *normalArray = malloc(sizeof(GLfloat) * 3 * vertexCount); GLfloat *texCoordArray = malloc(sizeof(GLfloat) * 2 * vertexCount); GLuint *indexArray = malloc(sizeof(GLuint) * triangleCount*3); printf("bpp %d\n", tex->bpp); for (x = 0; x < tex->width; x++) for (z = 0; z < tex->height; z++) { // Vertex array. You need to scale this properly vertexArray[(x + z * tex->width)*3 + 0] = x / 1.0; vertexArray[(x + z * tex->width)*3 + 1] = tex->imageData[(x + z * tex->width) * (tex->bpp/8)] / 20.0; vertexArray[(x + z * tex->width)*3 + 2] = z / 1.0; // Normal vectors. You need to calculate these. normalArray[(x + z * tex->width)*3 + 0] = 0.0; normalArray[(x + z * tex->width)*3 + 1] = 1.0; normalArray[(x + z * tex->width)*3 + 2] = 0.0; // Texture coordinates. You may want to scale them. texCoordArray[(x + z * tex->width)*2 + 0] = x; // (float)x / tex->width; texCoordArray[(x + z * tex->width)*2 + 1] = z; // (float)z / tex->height; } // Normal vector calculation pass // p3 // p2 p1 p4 // p5 // T1: v(x,z) -> v(x,z-1) -> v(x-1,z) = p1 -> p3 -> p2 // T2: v(x,z) -> v(x+1,z) -> v(x,z-1) = p1 -> p4 -> p3 // T3: v(x,z) -> v(x,z+1) -> v(x+1,z) = p1 -> p5 -> p4 // T4: v(x,z) -> v(x-1,z) -> v(x,z+1) = p1 -> p2 -> p5 vec3 n1, n2, n3, n4, p1, p2, p3, p4, p5; for (x = 0; x < tex->width-1; x++) for (z = 0; z < tex->height-1; z++) { if (z == 0 || x == 0) continue; // leave edges untouched for now p1.x = vertexArray[(x + z * tex->width)*3 + 0]; p1.y = vertexArray[(x + z * tex->width)*3 + 1]; p1.z = vertexArray[(x + z * tex->width)*3 + 2]; p2.x = vertexArray[((x-1) + z * tex->width)*3 + 0]; p2.y = vertexArray[((x-1) + z * tex->width)*3 + 1]; p2.z = vertexArray[((x-1) + z * tex->width)*3 + 2]; p3.x = vertexArray[(x + (z-1) * tex->width)*3 + 0]; p3.y = vertexArray[(x + (z-1) * tex->width)*3 + 1]; p3.z = vertexArray[(x + (z-1) * tex->width)*3 + 2]; p4.x = vertexArray[((x+1) + z * tex->width)*3 + 0]; p4.y = vertexArray[((x+1) + z * tex->width)*3 + 1]; p4.z = vertexArray[((x+1) + z * tex->width)*3 + 2]; p5.x = vertexArray[(x + (z+1) * tex->width)*3 + 0]; p5.y = vertexArray[(x + (z+1) * tex->width)*3 + 1]; p5.z = vertexArray[(x + (z+1) * tex->width)*3 + 2]; /*printf("p1: "); printVec3(p1); printf("p2: "); printVec3(p2); printf("p3: "); printVec3(p3); printf("p4: "); printVec3(p4); printf("p5: "); printVec3(p5); */ n1 = Normalize(CalcNormalVector(p1,p3,p2)); n2 = Normalize(CalcNormalVector(p1,p4,p3)); n3 = Normalize(CalcNormalVector(p1,p5,p4)); n4 = Normalize(CalcNormalVector(p1,p2,p5)); /*printf("n1: "); printVec3(n1); printf("n2: "); printVec3(n2); printf("n3: "); printVec3(n3); printf("n4: "); printVec3(n4); */ // Average the 4 triangle normals n1 = VectorAdd(VectorAdd(n1,n2), VectorAdd(n3,n4)); n1 = Normalize(n1); normalArray[(x + z * tex->width)*3 + 0] = n1.x; normalArray[(x + z * tex->width)*3 + 1] = n1.y; normalArray[(x + z * tex->width)*3 + 2] = n1.z; //printf("result: "); printVec3(n1); } for (x = 0; x < tex->width-1; x++) for (z = 0; z < tex->height-1; z++) { // Triangle 1 indexArray[(x + z * (tex->width-1))*6 + 0] = x + z * tex->width; indexArray[(x + z * (tex->width-1))*6 + 1] = x + (z+1) * tex->width; indexArray[(x + z * (tex->width-1))*6 + 2] = x+1 + z * tex->width; // Triangle 2 indexArray[(x + z * (tex->width-1))*6 + 3] = x+1 + z * tex->width; indexArray[(x + z * (tex->width-1))*6 + 4] = x + (z+1) * tex->width; indexArray[(x + z * (tex->width-1))*6 + 5] = x+1 + (z+1) * tex->width; } // End of terrain generation // Create Model and upload to GPU: Model* model = LoadDataToModel( vertexArray, normalArray, texCoordArray, NULL, indexArray, vertexCount, triangleCount*3); return model; }
Model* GenerateTerrain(TextureData *tex) { int vertexCount = tex->width * tex->height; int triangleCount = (tex->width-1) * (tex->height-1) * 2; int x, z; vertexArray = malloc(sizeof(GLfloat) * 3 * vertexCount); GLfloat *normalArray = malloc(sizeof(GLfloat) * 3 * vertexCount); GLfloat *texCoordArray = malloc(sizeof(GLfloat) * 2 * vertexCount); GLuint *indexArray = malloc(sizeof(GLuint) * triangleCount*3); printf("bpp %d\n", tex->bpp); for (x = 0; x < tex->width; x++) for (z = 0; z < tex->height; z++) { GLfloat y = tex->imageData[(x + z * tex->width) * (tex->bpp/8)] / 10.0; // Vertex array. You need to scale this properly vertexArray[(x + z * tex->width)*3 + 0] = x / 1.0; vertexArray[(x + z * tex->width)*3 + 1] = y; vertexArray[(x + z * tex->width)*3 + 2] = z / 1.0; // CalcNormalVector // Normal vectors. You need to calculate these. vec3 NV; //Can't access elements outside the array if ((x==0) || (x==tex->width) || (z==0) || (z==tex->width)) { NV.x = 0.0; NV.y = 1.0; NV.z = 0.0; } else { vec3 p1,p2,p3; GLfloat xmx1 = vertexArray[( (x-1) + z * tex->width)*3 + 0]; GLfloat ymx1 = vertexArray[( (x-1) + z * tex->width)*3 + 1]; GLfloat zmx1 = vertexArray[( (x-1) + z * tex->width)*3 + 2]; GLfloat xpx1 = vertexArray[( x + (z+1) * tex->width)*3 + 0]; GLfloat ypx1 = vertexArray[( x + (z+1) * tex->width)*3 + 1]; GLfloat zpx1 = vertexArray[( x + (z+1) * tex->width)*3 + 2]; p1 = SetVector(x,y,z); //Consider using x+1 x-1 instead p2 = SetVector(xmx1,ymx1,zmx1); p3 = SetVector(xpx1,ypx1,zpx1); NV = Normalize(CalcNormalVector(p1,p2,p3)); } normalArray[(x + z * tex->width)*3 + 0] = NV.x; normalArray[(x + z * tex->width)*3 + 1] = NV.y; normalArray[(x + z * tex->width)*3 + 2] = NV.z; // Texture coordinates. You may want to scale them. texCoordArray[(x + z * tex->width)*2 + 0] = x; // (float)x / tex->width; texCoordArray[(x + z * tex->width)*2 + 1] = z; // (float)z / tex->height; } for (x = 0; x < tex->width-1; x++) for (z = 0; z < tex->height-1; z++) { // Triangle 1 indexArray[(x + z * (tex->width-1))*6 + 0] = x + z * tex->width; indexArray[(x + z * (tex->width-1))*6 + 1] = x + (z+1) * tex->width; indexArray[(x + z * (tex->width-1))*6 + 2] = x+1 + z * tex->width; // Triangle 2 indexArray[(x + z * (tex->width-1))*6 + 3] = x+1 + z * tex->width; indexArray[(x + z * (tex->width-1))*6 + 4] = x + (z+1) * tex->width; indexArray[(x + z * (tex->width-1))*6 + 5] = x+1 + (z+1) * tex->width; } // End of terrain generation // Create Model and upload to GPU: Model* model = LoadDataToModel( vertexArray, normalArray, texCoordArray, NULL, indexArray, vertexCount, triangleCount*3); return model; }
GLfloat getHeight(TextureData *tex,GLfloat x, GLfloat z) { GLfloat xmin = floor(x); GLfloat xmax = ceil(x); GLfloat zmin = floor(z); GLfloat zmax = ceil(z); GLfloat xdec = x - xmin; GLfloat zdec = z - zmin; // GLfloat yll = tex->imageData[(xmin + zmin * tex->width) * (tex->bpp/8)] / 10.0;//gives y as in GenerateTerrain // GLfloat yhl = tex->imageData[(xmax + zmin * tex->width) * (tex->bpp/8)] / 10.0; // GLfloat ylr = tex->imageData[(xmin + zmax * tex->width) * (tex->bpp/8)] / 10.0; // GLfloat yhr = tex->imageData[(xmax + zmax * tex->width) * (tex->bpp/8)] / 10.0; // vec3 phr = SetVector(xmax,yhr,zmax); //points in square // vec3 plr = SetVector(xmin,ylr,zmax); // vec3 phl = SetVector(xmax,yhl,zmin); // vec3 pll = SetVector(xmin,yll,zmin); GLfloat ybl = tex->imageData[((int)xmin + (int)zmin * tex->width) * (tex->bpp/8)] / 10.0; GLfloat ytl = tex->imageData[((int)xmin + (int)zmax * tex->width) * (tex->bpp/8)] / 10.0; GLfloat ybr = tex->imageData[((int)xmax + (int)zmin * tex->width) * (tex->bpp/8)] / 10.0; GLfloat ytr = tex->imageData[((int)xmax + (int)zmax * tex->width) * (tex->bpp/8)] / 10.0; vec3 pbl = SetVector(xmin,ybl,zmin); vec3 ptl = SetVector(xmin,ytl,zmax); vec3 pbr = SetVector(xmax,ybr,zmin); vec3 ptr = SetVector(xmax,ytr,zmax); vec3 NV; if ( (xdec + zdec) > 1) { vec3 p1 = SetVector(xmin,ytl,zmax); vec3 p2 = SetVector(xmax,ytr,zmax); vec3 p3 = SetVector(xmax,ybr,zmin); NV = Normalize(CalcNormalVector(p1,p2,p3)); } else { vec3 p1 = SetVector(xmin,ytl,zmax); vec3 p2 = SetVector(xmin,ybl,zmin); vec3 p3 = SetVector(xmax,ybr,zmin); NV = Normalize(CalcNormalVector(p1,p2,p3)); } //Use plane equation. Find D with one of the points. //Why is ptl better than pbl? GLfloat D = NV.x * ptl.x + NV.y * ptl.y + NV.z * ptl.z; GLfloat yint = (D - NV.x * x - NV.z * z) / NV.y; //Linjär interpolation - funkar ej bra. /* if ( (xdec+zdec) > 1) */ /* { */ /* yint = ytr + (ytr-ytl)*xdec + (ytr-ybl)*zdec; */ /* } */ /* else */ /* { */ /* yint = ybl + (ybl-ybr)*xdec + (ybl-ytl)*zdec; */ /* } */ return yint; }