void addFace(ofMesh& mesh, ofVec3f a, ofVec3f b, ofVec3f c) {
ofVec3f normal = ((b - a).cross(c - a)).normalize();
mesh.addNormal(normal);
mesh.addVertex(a);
mesh.addNormal(normal);
mesh.addVertex(b);
mesh.addNormal(normal);
mesh.addVertex(c);
}
//--------------------------------------------------------------
void addFace(ofMesh& mesh, ofVec3f a, ofVec3f b, ofVec3f c, ofVec3f d) {
addFace(mesh, a, b, c);
addFace(mesh, a, c, d);
}
//--------------------------------------------------------------
void makeTerrainFromImg(const ofImage &img){
mesh.setMode(OF_PRIMITIVE_TRIANGLES);
int skip = 1;
int width = img.getWidth();
int height = img.getHeight();
for(int y = 0; y < height - skip; y += skip) {
for(int x = 0; x < width - skip; x += skip) {
ofVec3f nw = getVertexFromImg(img, x, y);
ofVec3f ne = getVertexFromImg(img, x + skip, y);
ofVec3f sw = getVertexFromImg(img, x, y + skip);
ofVec3f se = getVertexFromImg(img, x + skip, y + skip);
addFace(mesh, nw, ne, se, sw);
}
}
}
void makeFlatMesh(){
int scale = 15;
int w = ofGetWidth()/scale;
int h = ofGetHeight()/scale;
for (int y = 0; y < h; y++){
for (int x = 0; x<w; x++){
// Per pixel we set the position, normal and texCoord
//
float offsetX = 0;
float offsetY = (x%2==1)?0.5:0.0;
terrain.addVertex(ofPoint((x+offsetX)*scale,(y+offsetY)*scale,0));
terrain.addNormal(ofPoint(1,0,0));
terrain.addTexCoord(ofVec2f((float)(x+offsetX)/(float)w,(float)(y+offsetY)/(float)h));
}
}
for (int y = 0; y<h-1; y++){
for (int x=0; x<w-1; x++){
if(x%2==0){
terrain.addIndex(x+y*w); // a
terrain.addIndex((x+1)+y*w); // b
terrain.addIndex(x+(y+1)*w); // d
terrain.addIndex((x+1)+y*w); // b
terrain.addIndex((x+1)+(y+1)*w); // c
terrain.addIndex(x+(y+1)*w); // d
} else {
terrain.addIndex((x+1)+y*w); // b
terrain.addIndex(x+y*w); // a
terrain.addIndex((x+1)+(y+1)*w); // c
terrain.addIndex(x+y*w); // a
terrain.addIndex(x+(y+1)*w); // d
terrain.addIndex((x+1)+(y+1)*w); // c
}
}
}
}
Universal function which sets normals for the triangle mesh
void setNormals( ofMesh &mesh ){
//The number of the vertices
int nV = mesh.getNumVertices();
//The number of the triangles
int nT = mesh.getNumIndices() / 3;
vector<ofPoint> norm( nV ); //Array for the normals
//Scan all the triangles. For each triangle add its
//normal to norm's vectors of triangle's vertices
for (int t=0; t<nT; t++) {
//Get indices of the triangle t
int i1 = mesh.getIndex( 3 * t );
int i2 = mesh.getIndex( 3 * t + 1 );
int i3 = mesh.getIndex( 3 * t + 2 );
//Get vertices of the triangle
const ofPoint &v1 = mesh.getVertex( i1 );
const ofPoint &v2 = mesh.getVertex( i2 );
const ofPoint &v3 = mesh.getVertex( i3 );
//Compute the triangle's normal
ofPoint dir = ( (v2 - v1).crossed( v3 - v1 ) ).normalized();
//Accumulate it to norm array for i1, i2, i3
norm[ i1 ] += dir;
norm[ i2 ] += dir;
norm[ i3 ] += dir;
}
//Normalize the normal's length
for (int i=0; i<nV; i++) {
norm[i].normalize();
}
//Set the normals to mesh
mesh.clearNormals();
mesh.addNormals( norm );
}
{
ofFloatPixels heightMap;
heightMap.allocate( _width, _height, OF_PIXELS_RGBA);
// Put the pixels
ofFloatPixels norms;
norms.allocate( _width, _height, OF_PIXELS_RGBA);
// put the pixels
int width = heightMap.getWidth();
int height = heightMap.getHeight();
float flResolution = 4; // 1-10
float flHeightScale = 300;
float textureScale = 1.0;
// Generate Vertex Field
nVertexCount = (int) ( width * height * 6 / ( flResolution * flResolution ) );
pVertices = new ofVec3f[nVertexCount]; // Allocate Vertex Data
pTexCoords = new ofVec2f[nVertexCount]; // Allocate Tex Coord Data
pNormals = new ofVec3f[nVertexCount]; // Allocate Normals
int nX, nZ, nTri, nIndex=0; // Create Variables
float flX, flZ;
for( nZ = 0; nZ < height-flResolution ; nZ += (int) flResolution ){
for( nX = 0; nX < width-flResolution ; nX += (int) flResolution ){
for( nTri = 0; nTri < 6; nTri++ ){
// Using This Quick Hack, Figure The X,Z Position Of The Point
flX = (float) nX + ( ( nTri == 1 || nTri == 2 || nTri == 5 ) ? flResolution : 0.0f );
flZ = (float) nZ + ( ( nTri == 2 || nTri == 4 || nTri == 5 ) ? flResolution : 0.0f );
// Set The Data, Using PtHeight To Obtain The Y Value
pVertices[nIndex].x = flX - ( width *0.5 );
pVertices[nIndex].y = heightMap.getColor((int)flX, (int)flZ).r * flHeightScale;
pVertices[nIndex].z = flZ - ( height *0.5 );
// 3 0 --- 1 nTri reference
// | \ \ |
// | \ \ |
// 4 --- 5 2
` // Stretch The Texture Across The Entire Mesh
pTexCoords[nIndex].x = flX * textureScale;// / width;
pTexCoords[nIndex].y = flZ * textureScale;// / height;
// Normals by vert
pNormals[nIndex].x = norms.getColor((int)flX, (int)flZ).r;
pNormals[nIndex].y = norms.getColor((int)flX, (int)flZ).b;
pNormals[nIndex].z = norms.getColor((int)flX, (int)flZ).g;
// Increment Our Index
nIndex++;
}
}
}
vbo.setVertexData(pVertices, nVertexCount, GL_STREAM_DRAW);
vbo.setNormalData(pNormals, nVertexCount, GL_STREAM_DRAW);
vbo.setTexCoordData(pTexCoords, nVertexCount, GL_STREAM_DRAW);
// Our Copy Of The Data Is No Longer Necessary, It Is Safe In The Graphics Card
delete [] pVertices; pVertices = NULL;
delete [] pTexCoords; pTexCoords = NULL;
delete [] pNormals; pNormals = NULL;
}