Example #1
0
bool Terrain::HeightMapLoad(char* filename, float sx, float sz, float maxy)
{
	//FILE *filePtr;							// Point to the current position in the file
	//BITMAPFILEHEADER bitmapFileHeader;		// Structure which stores information about file
	//BITMAPINFOHEADER bitmapInfoHeader;		// Structure which stores information about image
	int imageSize, index;
	unsigned char height;

	// Open the file
	//filePtr = fopen(filename,"rb");
	//if (filePtr == NULL)
	//	return 0;

	dx = sz;
	dz = sz;
	dy = maxy;

	

	// Get the width and height (width and length) of the image
	hminfo.terrainWidth = 145;// bitmapInfoHeader.biWidth;
	hminfo.terrainHeight = 145;// bitmapInfoHeader.biHeight;


	// Initialize the heightMap array (stores the vertices of our terrain)
	hminfo.heightMap = new IntV3[hminfo.terrainWidth * hminfo.terrainHeight];

	// We use a greyscale image, so all 3 rgb values are the same, but we only need one for the height
	// So we use this counter to skip the next two components in the image data (we read R, then skip BG)
	int k=0;

	// Read the image data into our heightMap array
	for(int j=0; j< hminfo.terrainHeight; j++)
	{
		for(int i=0; i< hminfo.terrainWidth; i++)
		{
			height = rand()%50+1;

			index = ( hminfo.terrainWidth * (hminfo.terrainHeight - 1 - j)) + i;

			hminfo.heightMap[index].x = i - (hminfo.terrainWidth - 1)/2;
			hminfo.heightMap[index].y = height;
			hminfo.heightMap[index].z = j - (hminfo.terrainHeight - 1)/2;

			k+=3;
		}
		k++;
	}


	int cols = hminfo.terrainWidth;
	int rows = hminfo.terrainHeight;

	//Create the grid
	NumVertices = 2 * rows * cols;
	NumFaces  = (rows-1)*(cols-1)*2;

	v = new struct HeightFieldVertex[NumVertices];

	for(DWORD i = 0; i < rows; ++i)
	{
		for(DWORD j = 0; j < cols; ++j)
		{
			v[i*cols+j].pos.x = hminfo.heightMap[i*cols+j].x * dx;
			v[i*cols+j].pos.y = (float(hminfo.heightMap[i*cols+j].y)/255.0) * dy;
			v[i*cols+j].pos.z = hminfo.heightMap[i*cols+j].z * dz;
			v[i*cols+j].texCoord = D3DXVECTOR2(j, i);
		}
	}

	indices = new DWORD[NumFaces * 3];

	k = 0;
	for(DWORD i = 0; i < rows-1; i++)
	{
		for(DWORD j = 0; j < cols-1; j++)
		{
			indices[k]   = i*cols+j;		// Bottom left of quad
			indices[k+1] = i*cols+j+1;		// Bottom right of quad
			indices[k+2] = (i+1)*cols+j;	// Top left of quad
			indices[k+3] = (i+1)*cols+j;	// Top left of quad
			indices[k+4] = i*cols+j+1;		// Bottom right of quad
			indices[k+5] = (i+1)*cols+j+1;	// Top right of quad

			k += 6; // next quad
		}
	}

	//normals & tangents
    std::vector<D3DXVECTOR3> tempNormal;

    //normalized and unnormalized normals
    D3DXVECTOR3 unnormalized(0.0f, 0.0f, 0.0f);

    //tangent stuff
    std::vector<D3DXVECTOR3> tempTangent;

    D3DXVECTOR3 tangent(0.0f, 0.0f, 0.0f);
    float tcU1, tcV1, tcU2, tcV2;

    //Used to get vectors (sides) from the position of the verts
    float vecX, vecY, vecZ;

    //Two edges of our triangle
    D3DXVECTOR3 edge1(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 edge2(0.0f, 0.0f, 0.0f);

    //Compute face normals
    //And Tangents
    for(int i = 0; i < NumFaces; ++i)
    {
        //Get the vector describing one edge of our triangle (edge 0,2)
        vecX = v[indices[(i*3)+1]].pos.x - v[indices[(i*3)]].pos.x;
        vecY = v[indices[(i*3)+1]].pos.y - v[indices[(i*3)]].pos.y;
        vecZ = v[indices[(i*3)+1]].pos.z - v[indices[(i*3)]].pos.z;       
        edge1 = D3DXVECTOR3(vecX, vecY, vecZ);    //Create our first edge

        //Get the vector describing another edge of our triangle (edge 2,1)
        vecX = v[indices[(i*3)+2]].pos.x - v[indices[(i*3)]].pos.x;
        vecY = v[indices[(i*3)+2]].pos.y - v[indices[(i*3)]].pos.y;
        vecZ = v[indices[(i*3)+2]].pos.z - v[indices[(i*3)]].pos.z;     
        edge2 = D3DXVECTOR3(vecX, vecY, vecZ);    //Create our second edge

        //Cross multiply the two edge vectors to get the un-normalized face normal
		D3DXVec3Cross(&unnormalized, &edge1, &edge2);
        tempNormal.push_back(unnormalized);

        //Find first texture coordinate edge 2d vector
        tcU1 = v[indices[(i*3)+1]].texCoord.x - v[indices[(i*3)]].texCoord.x;
        tcV1 = v[indices[(i*3)+1]].texCoord.y - v[indices[(i*3)]].texCoord.y;

        //Find second texture coordinate edge 2d vector
        tcU2 = v[indices[(i*3)+2]].texCoord.x - v[indices[(i*3)]].texCoord.x;
        tcV2 = v[indices[(i*3)+2]].texCoord.y - v[indices[(i*3)]].texCoord.y;

        //Find tangent using both tex coord edges and position edges
        tangent.x = (tcV2 * edge1.x - tcV1 * edge2.x)  / (tcU1 * tcV2 - tcU2 * tcV1);
        tangent.y = (tcV2 * edge1.y - tcV1 * edge2.y)  / (tcU1 * tcV2 - tcU2 * tcV1);
        tangent.z = (tcV2 * edge1.z - tcV1 * edge2.z)  / (tcU1 * tcV2 - tcU2 * tcV1);

        tempTangent.push_back(tangent);
    }

    //Compute vertex normals (normal Averaging)
    D3DXVECTOR4 normalSum(0.0f, 0.0f, 0.0f, 0.0f);
    D3DXVECTOR4 tangentSum(0.0f, 0.0f, 0.0f, 0.0f);
    int facesUsing = 0;
    float tX, tY, tZ;   //temp axis variables

    //Go through each vertex
    for(int i = 0; i < NumVertices; ++i)
    {
        //Check which triangles use this vertex
        for(int j = 0; j < NumFaces; ++j)
        {
            if(indices[j*3] == i ||
                indices[(j*3)+1] == i ||
                indices[(j*3)+2] == i)
            {
                tX = normalSum.x + tempNormal[j].x;
                tY = normalSum.y + tempNormal[j].y;
                tZ = normalSum.z + tempNormal[j].z;

                normalSum = D3DXVECTOR4(tX, tY, tZ, 0.0f);  //If a face is using the vertex, add the unormalized face normal to the normalSum
    
                facesUsing++;
            }
        }
        //Get the actual normal by dividing the normalSum by the number of faces sharing the vertex
        normalSum = normalSum / facesUsing;

		facesUsing = 0;
        //Check which triangles use this vertex
        for(int j = 0; j < NumFaces; ++j)
        {
            if(indices[j*3] == i ||
                indices[(j*3)+1] == i ||
                indices[(j*3)+2] == i)
            {
   
                //We can reuse tX, tY, tZ to sum up tangents
                tX = tangentSum.x + tempTangent[j].x;
                tY = tangentSum.y + tempTangent[j].y;
                tZ = tangentSum.z + tempTangent[j].z;

                tangentSum = D3DXVECTOR4(tX, tY, tZ, 0.0f); //sum up face tangents using this vertex

                facesUsing++;
            }
        }
        //Get the actual normal by dividing the normalSum by the number of faces sharing the vertex
        tangentSum = tangentSum / facesUsing;

        //Normalize the normalSum vector and tangent
		D3DXVec4Normalize(&normalSum, &normalSum);
		D3DXVec4Normalize(&tangentSum, &tangentSum);

        //Store the normal and tangent in our current vertex
        v[i].normal.x = normalSum.x;
        v[i].normal.y = normalSum.y;
        v[i].normal.z = normalSum.z;

        v[i].tangent.x = tangentSum.x;
        v[i].tangent.y = tangentSum.y;
        v[i].tangent.z = tangentSum.z;

		D3DXVECTOR3 bit;

		D3DXVec3Cross(&bit, &v[i].normal, &v[i].tangent);
		v[i].bitangent = -1.0 * bit;

        //Clear normalSum, tangentSum and facesUsing for next vertex
        normalSum = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
        tangentSum = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
        facesUsing = 0;
    }

	////terrain AABB
	//MinX =  -1.0 * dx * (hminfo.terrainWidth - 1)/2;
	//MinY = 0.0;
	//MinZ =  -1.0 * dz * (hminfo.terrainHeight - 1)/2;
	//MaxX =  dx * (hminfo.terrainWidth - 1)/2;
	//MaxY = dy;
	//MaxZ =  dz * (hminfo.terrainHeight - 1)/2;

 	return true;
}
Example #2
0
void DrawSmooth::addVBO(unsigned int currentObject)
{
    // Step 1: Create and fill the four arrays (vertex coords, vertex normals, and face indices)
    // This version:
    //  - each coord/normal will appear one time (one for each corner with unique normal)

    vector<float> vertices; // (x,y,z)    Final size: 3*number of vertices
    vector<float> normals;  // (nx,ny,nz) Final size: 3*number of vertices
    vector<float> st;       // (s,t)      Final size: 2*number of vertices
    vector<float> colors;   // (r,g,b)    Final size: 3*number of vertices
    vector<int> indices;    //            Final size: 3*number of triangles

    const Object& obj = scene()->objects()[currentObject];
    const vector<Face> &faces = obj.faces();
    const vector<Vertex> &verts = obj.vertices();

    vector<Vector> normalSum(verts.size(), Vector(0, 0, 0));
    vector<int> normalCount(verts.size(), 0);

    for (int i = 0; i < (int)faces.size(); ++i)
    {
        const Face &face = faces[i];
        const Vector &N = face.normal().normalized();
        for (int j = 0; j < face.numVertices(); ++j)
        {
            int index = face.vertexIndex(j);
            ++normalCount[index];
            normalSum[index] += N;
            indices.push_back(index);
        }
    }

    for (int i = 0; i < (int)verts.size(); ++i)
    {
        Point P = verts[i].coord();
        vertices.push_back(P.x()); vertices.push_back(P.y()); vertices.push_back(P.z());

        Vector N = normalSum[i]/normalCount[i];
        normals.push_back(N.x()); normals.push_back(N.y()); normals.push_back(N.z());

        float r = obj.boundingBox().radius();
        float s = Vector::dotProduct((1.0/r)*Vector(1, 0, 1), P);
        float t = Vector::dotProduct((1.0/r)*Vector(0, 1, 0), P);
        if (obj.vertices().size() == 81) // plane: special case for /assig models
        {
            s = 0.5f*(P.x() + 1.0);
            t = 0.5f*(P.y() + 1.0);
        }
        if (obj.vertices().size() == 386) // cube: special case for /assig models
        {
            s = Vector::dotProduct((1.0/2.0)*Vector(1, 0, 1), P);
            t = Vector::dotProduct((1.0/2.0)*Vector(0, 1, 0), P);
        }
        st.push_back(s);
        st.push_back(t);

        colors.push_back(abs(N.x()));
        colors.push_back(abs(N.y()));
        colors.push_back(abs(N.z()));
    }

    // Step 2: Create empty buffers (coords, normals, st, indices)
    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    VAOs.push_back(VAO);
    glBindVertexArray(VAO);

    GLuint coordBufferID;
    glGenBuffers(1, &coordBufferID);
    coordBuffers.push_back(coordBufferID);

    GLuint normalBufferID;
    glGenBuffers(1, &normalBufferID);
    normalBuffers.push_back(normalBufferID);

    GLuint colorBufferID;
    glGenBuffers(1, &colorBufferID);
    colorBuffers.push_back(colorBufferID);

    GLuint stBufferID;
    glGenBuffers(1, &stBufferID);
    stBuffers.push_back(stBufferID);

    GLuint indexBufferID;
    glGenBuffers(1, &indexBufferID);
    indexBuffers.push_back(indexBufferID);

    numIndices.push_back(indices.size());

    // Step 3: Define VBO data (coords, normals, indices)
    glBindBuffer(GL_ARRAY_BUFFER, coordBuffers[currentObject]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*vertices.size(), &vertices[0], GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);  // VAO
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, normalBuffers[currentObject]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*normals.size(), &normals[0], GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);  // VAO
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[currentObject]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*colors.size(), &colors[0], GL_STATIC_DRAW);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);  // VAO
    glEnableVertexAttribArray(2);

    glBindBuffer(GL_ARRAY_BUFFER, stBuffers[currentObject]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*st.size(), &st[0], GL_STATIC_DRAW);
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, 0);  // VAO
    glEnableVertexAttribArray(3);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffers[currentObject]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*indices.size(), &indices[0], GL_STATIC_DRAW);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

}
Example #3
0
    void Mesh::generateVertexNormals(const float& smoothingAngle)
    {
        // calculate the cosine of the angle (in degrees)
        float cos_angle = cos(smoothingAngle * M_PI / 180.0);

        // clear any previously cached normals
        _normals.clear();

        int numVerts = _vertices.size()/3;
        int numFaces = _faceIndices.size()/3;

        //Here we create a temporary list of face indices for each vertex
        //That is, a list of lists, where for each vertex, we have a list of
        //indices of the faces it belongs to
        std::vector< std::vector<int> > facesPerVertex;
        std::vector< std::vector<vec3> > faceNormalsPerVertex;
        for(int i=0; i<numVerts; ++i)
        {
            //Create an empty list of face indices
            std::vector<int> faceList;
            facesPerVertex.push_back(faceList);

            //Create an empty list of normals
            std::vector<vec3> normalList;
            faceNormalsPerVertex.push_back(normalList);
        }

        //First we iterate over all the faces and generate face normals
        //for each face in our mesh
        for(int i=0; i<numFaces; ++i)
        {
            int vertIndex1 = _faceIndices[3*i];
            int vertIndex2 = _faceIndices[3*i+1];
            int vertIndex3 = _faceIndices[3*i+2];

            //Register that face with index i, is part of the faceLists
            //for each of the above vertices
            facesPerVertex[vertIndex1].push_back(i);
            facesPerVertex[vertIndex2].push_back(i);
            facesPerVertex[vertIndex3].push_back(i);

            vec3 faceNormal(_faceNormals[3*i+0],
                            _faceNormals[3*i+1],
                            _faceNormals[3*i+2]);
            faceNormalsPerVertex[vertIndex1].push_back(faceNormal);
            faceNormalsPerVertex[vertIndex2].push_back(faceNormal);
            faceNormalsPerVertex[vertIndex3].push_back(faceNormal);
        }

        //Now we have a list of faces per vertex
        //We also have a list of face normals per vertex
        //We can now calculate the average normal
        for(int i=0; i<numVerts; ++i)
        {
            std::vector<vec3> normals = faceNormalsPerVertex[i];
            vec3 normalSum(0.f, 0.f, 0.f);
            for(int j=0; j<normals.size(); ++j)
            {
                normalSum += normals[j];    
            }
            normalSum.normalize();
            float* normCoords = normalSum.data();
            _normals.push_back(normCoords[0]);
            _normals.push_back(normCoords[1]);
            _normals.push_back(normCoords[2]);
        }

    }