示例#1
0
void Cloth::Rebuffer()
{
	int nverts = 0;
	for(vector<SpringNode*>::iterator i = physicsCloth->nodes.begin(); i!=physicsCloth->nodes.end(); i++) {

		vertices[nverts] = (*i)->GetPosition();

		nverts++;

	}

	GenerateNormals();
	GenerateTangents();

	glBindVertexArray(arrayObject);
	glBindBuffer(GL_ARRAY_BUFFER, bufferObject[VERTEX_BUFFER]);
	glBufferSubData(GL_ARRAY_BUFFER,0 ,	numVertices*sizeof(Vector3), vertices);
	
	glBindBuffer(GL_ARRAY_BUFFER, bufferObject[NORMAL_BUFFER]);
	glBufferSubData(GL_ARRAY_BUFFER,0 ,	numVertices*sizeof(Vector3), normals);
	
	glBindBuffer(GL_ARRAY_BUFFER, bufferObject[TANGENT_BUFFER]);
	glBufferSubData(GL_ARRAY_BUFFER,0 ,	numVertices*sizeof(Vector3), tangents);


}
示例#2
0
Cloth::Cloth(PhysicsCloth* pc){

	physicsCloth = pc;
	numVertices = pc->height * pc->width;
	numIndices =  (pc->height-1 )* (pc->width-1 )* 6;

	vertices	  = new Vector3[numVertices];
	textureCoords = new Vector2[numVertices];
	indices		  = new GLuint[numIndices];
	
	for(int i = 0; i < pc->width; i++)
	{
		for(int j = 0;  j < pc->height; j++)
		{
			int index = (i*pc->width) + j;
			textureCoords[index] = Vector2((float)i/(float)pc->width, (float)j/(float)pc->height);
			//textureCoords[index] = Vector2(rand() % 100 / 100.0f,rand() % 100 / 100.0f);
		}
	}

	int nverts = 0;
	for(vector<SpringNode*>::iterator i = pc->nodes.begin(); i!=pc->nodes.end(); i++) {

		vertices[nverts] = (*i)->GetPosition();

		nverts++;

	}
	
	numIndices = 0;

	for(int x = 0; x < pc->width-1; ++x)	{
		for(int z = 0; z < pc->height-1; ++z)	{
			int a = (x		* (pc->width)) + z;
			int b = ((x+1)  * (pc->width)) + z;
			int c = ((x+1)  * (pc->width)) + (z+1);
			int d = (x		* (pc->width)) + (z+1);
		
			indices[numIndices++] = c;
			indices[numIndices++] = b;
			indices[numIndices++] = a;

			indices[numIndices++] = a;
			indices[numIndices++] = d;
			indices[numIndices++] = c;

		}
	}
	GenerateNormals();
	GenerateTangents();
	GenerateColours();
	BufferData();

}
示例#3
0
void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubMeshes, bool exportMorphs)
{
    File meshFileSource(context_);
    meshFileSource.Open(inputFileName);
    if (!meshFile_->Load(meshFileSource))
        ErrorExit("Could not load input file " + inputFileName);

    XMLElement root = meshFile_->GetRoot("mesh");
    XMLElement subMeshes = root.GetChild("submeshes");
    XMLElement skeletonLink = root.GetChild("skeletonlink");
    if (root.IsNull())
        ErrorExit("Could not load input file " + inputFileName);

    String skeletonName = skeletonLink.GetAttribute("name");
    if (!skeletonName.Empty())
        LoadSkeleton(GetPath(inputFileName) + GetFileName(skeletonName) + ".skeleton.xml");

    // Check whether there's benefit of avoiding 32bit indices by splitting each submesh into own buffer
    XMLElement subMesh = subMeshes.GetChild("submesh");
    unsigned totalVertices = 0;
    unsigned maxSubMeshVertices = 0;
    while (subMesh)
    {
        materialNames_.Push(subMesh.GetAttribute("material"));
        XMLElement geometry = subMesh.GetChild("geometry");
        if (geometry)
        {
            unsigned vertices = geometry.GetInt("vertexcount");
            totalVertices += vertices;
            if (maxSubMeshVertices < vertices)
                maxSubMeshVertices = vertices;
        }
        ++numSubMeshes_;

        subMesh = subMesh.GetNext("submesh");
    }

    XMLElement sharedGeometry = root.GetChild("sharedgeometry");
    if (sharedGeometry)
    {
        unsigned vertices = sharedGeometry.GetInt("vertexcount");
        totalVertices += vertices;
        if (maxSubMeshVertices < vertices)
            maxSubMeshVertices = vertices;
    }

    if (!sharedGeometry && (splitSubMeshes || (totalVertices > 65535 && maxSubMeshVertices <= 65535)))
    {
        useOneBuffer_ = false;
        vertexBuffers_.Resize(numSubMeshes_);
        indexBuffers_.Resize(numSubMeshes_);
    }
    else
    {
        vertexBuffers_.Resize(1);
        indexBuffers_.Resize(1);
    }

    subMesh = subMeshes.GetChild("submesh");
    unsigned indexStart = 0;
    unsigned vertexStart = 0;
    unsigned subMeshIndex = 0;

    PODVector<unsigned> vertexStarts;
    vertexStarts.Resize(numSubMeshes_);

    while (subMesh)
    {
        XMLElement geometry = subMesh.GetChild("geometry");
        XMLElement faces = subMesh.GetChild("faces");

        // If no submesh vertexbuffer, process the shared geometry, but do it only once
        unsigned vertices = 0;
        if (!geometry)
        {
            vertexStart = 0;
            if (!subMeshIndex)
                geometry = root.GetChild("sharedgeometry");
        }

        if (geometry)
            vertices = geometry.GetInt("vertexcount");

        ModelSubGeometryLodLevel subGeometryLodLevel;
        ModelVertexBuffer* vBuf;
        ModelIndexBuffer* iBuf;

        if (useOneBuffer_)
        {
            vBuf = &vertexBuffers_[0];
            if (vertices)
                vBuf->vertices_.Resize(vertexStart + vertices);
            iBuf = &indexBuffers_[0];

            subGeometryLodLevel.vertexBuffer_ = 0;
            subGeometryLodLevel.indexBuffer_ = 0;
        }
        else
        {
            vertexStart = 0;
            indexStart = 0;

            vBuf = &vertexBuffers_[subMeshIndex];
            vBuf->vertices_.Resize(vertices);
            iBuf = &indexBuffers_[subMeshIndex];

            subGeometryLodLevel.vertexBuffer_ = subMeshIndex;
            subGeometryLodLevel.indexBuffer_ = subMeshIndex;
        }

        // Store the start vertex for later use
        vertexStarts[subMeshIndex] = vertexStart;

        // Ogre may have multiple buffers in one submesh. These will be merged into one
        XMLElement bufferDef;
        if (geometry)
            bufferDef = geometry.GetChild("vertexbuffer");

        while (bufferDef)
        {
            if (bufferDef.HasAttribute("positions"))
                vBuf->elementMask_ |= MASK_POSITION;
            if (bufferDef.HasAttribute("normals"))
                vBuf->elementMask_ |= MASK_NORMAL;
            if (bufferDef.HasAttribute("texture_coords"))
            {
                vBuf->elementMask_ |= MASK_TEXCOORD1;
                if (bufferDef.GetInt("texture_coords") > 1)
                    vBuf->elementMask_ |= MASK_TEXCOORD2;
            }

            unsigned vertexNum = vertexStart;
            if (vertices)
            {
                XMLElement vertex = bufferDef.GetChild("vertex");
                while (vertex)
                {
                    XMLElement position = vertex.GetChild("position");
                    if (position)
                    {
                        // Convert from right- to left-handed
                        float x = position.GetFloat("x");
                        float y = position.GetFloat("y");
                        float z = position.GetFloat("z");
                        Vector3 vec(x, y, -z);

                        vBuf->vertices_[vertexNum].position_ = vec;
                        boundingBox_.Merge(vec);
                    }
                    XMLElement normal = vertex.GetChild("normal");
                    if (normal)
                    {
                        // Convert from right- to left-handed
                        float x = normal.GetFloat("x");
                        float y = normal.GetFloat("y");
                        float z = normal.GetFloat("z");
                        Vector3 vec(x, y, -z);

                        vBuf->vertices_[vertexNum].normal_ = vec;
                    }
                    XMLElement uv = vertex.GetChild("texcoord");
                    if (uv)
                    {
                        float x = uv.GetFloat("u");
                        float y = uv.GetFloat("v");
                        Vector2 vec(x, y);

                        vBuf->vertices_[vertexNum].texCoord1_ = vec;

                        if (vBuf->elementMask_ & MASK_TEXCOORD2)
                        {
                            uv = uv.GetNext("texcoord");
                            if (uv)
                            {
                                float x = uv.GetFloat("u");
                                float y = uv.GetFloat("v");
                                Vector2 vec(x, y);

                                vBuf->vertices_[vertexNum].texCoord2_ = vec;
                            }
                        }
                    }

                    vertexNum++;
                    vertex = vertex.GetNext("vertex");
                }
            }

            bufferDef = bufferDef.GetNext("vertexbuffer");
        }

        unsigned triangles = faces.GetInt("count");
        unsigned indices = triangles * 3;

        XMLElement triangle = faces.GetChild("face");
        while (triangle)
        {
            unsigned v1 = triangle.GetInt("v1");
            unsigned v2 = triangle.GetInt("v2");
            unsigned v3 = triangle.GetInt("v3");
            iBuf->indices_.Push(v3 + vertexStart);
            iBuf->indices_.Push(v2 + vertexStart);
            iBuf->indices_.Push(v1 + vertexStart);
            triangle = triangle.GetNext("face");
        }

        subGeometryLodLevel.indexStart_ = indexStart;
        subGeometryLodLevel.indexCount_ = indices;
        if (vertexStart + vertices > 65535)
            iBuf->indexSize_ = sizeof(unsigned);

        XMLElement boneAssignments = subMesh.GetChild("boneassignments");
        if (bones_.Size())
        {
            if (boneAssignments)
            {
                XMLElement boneAssignment = boneAssignments.GetChild("vertexboneassignment");
                while (boneAssignment)
                {
                    unsigned vertex = boneAssignment.GetInt("vertexindex") + vertexStart;
                    unsigned bone = boneAssignment.GetInt("boneindex");
                    float weight = boneAssignment.GetFloat("weight");

                    BoneWeightAssignment assign;
                    assign.boneIndex_ = bone;
                    assign.weight_ = weight;
                    // Source data might have 0 weights. Disregard these
                    if (assign.weight_ > 0.0f)
                    {
                        subGeometryLodLevel.boneWeights_[vertex].Push(assign);

                        // Require skinning weight to be sufficiently large before vertex contributes to bone hitbox
                        if (assign.weight_ > 0.33f)
                        {
                            // Check distance of vertex from bone to get bone max. radius information
                            Vector3 bonePos = bones_[bone].derivedPosition_;
                            Vector3 vertexPos = vBuf->vertices_[vertex].position_;
                            float distance = (bonePos - vertexPos).Length();
                            if (distance > bones_[bone].radius_)
                            {
                                bones_[bone].collisionMask_ |= 1;
                                bones_[bone].radius_ = distance;
                            }
                            // Build the hitbox for the bone
                            bones_[bone].boundingBox_.Merge(bones_[bone].inverseWorldTransform_ * (vertexPos));
                            bones_[bone].collisionMask_ |= 2;
                        }
                    }
                    boneAssignment = boneAssignment.GetNext("vertexboneassignment");
                }
            }

            if ((subGeometryLodLevel.boneWeights_.Size()) && bones_.Size())
            {
                vBuf->elementMask_ |= MASK_BLENDWEIGHTS | MASK_BLENDINDICES;
                bool sorted = false;

                // If amount of bones is larger than supported by HW skinning, must remap per submesh
                if (bones_.Size() > maxBones_)
                {
                    HashMap<unsigned, unsigned> usedBoneMap;
                    unsigned remapIndex = 0;
                    for (HashMap<unsigned, PODVector<BoneWeightAssignment> >::Iterator i =
                                subGeometryLodLevel.boneWeights_.Begin(); i != subGeometryLodLevel.boneWeights_.End(); ++i)
                    {
                        // Sort the bone assigns by weight
                        Sort(i->second_.Begin(), i->second_.End(), CompareWeights);

                        // Use only the first 4 weights
                        for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j)
                        {
                            unsigned originalIndex = i->second_[j].boneIndex_;
                            if (!usedBoneMap.Contains(originalIndex))
                            {
                                usedBoneMap[originalIndex] = remapIndex;
                                remapIndex++;
                            }
                            i->second_[j].boneIndex_ = usedBoneMap[originalIndex];
                        }
                    }

                    // If still too many bones in one subgeometry, error
                    if (usedBoneMap.Size() > maxBones_)
                        ErrorExit("Too many bones (limit " + String(maxBones_) + ") in submesh " + String(subMeshIndex + 1));

                    // Write mapping of vertex buffer bone indices to original bone indices
                    subGeometryLodLevel.boneMapping_.Resize(usedBoneMap.Size());
                    for (HashMap<unsigned, unsigned>::Iterator j = usedBoneMap.Begin(); j != usedBoneMap.End(); ++j)
                        subGeometryLodLevel.boneMapping_[j->second_] = j->first_;

                    sorted = true;
                }

                for (HashMap<unsigned, PODVector<BoneWeightAssignment> >::Iterator i = subGeometryLodLevel.boneWeights_.Begin();
                        i != subGeometryLodLevel.boneWeights_.End(); ++i)
                {
                    // Sort the bone assigns by weight, if not sorted yet in bone remapping pass
                    if (!sorted)
                        Sort(i->second_.Begin(), i->second_.End(), CompareWeights);

                    float totalWeight = 0.0f;
                    float normalizationFactor = 0.0f;

                    // Calculate normalization factor in case there are more than 4 blend weights, or they do not add up to 1
                    for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j)
                        totalWeight += i->second_[j].weight_;
                    if (totalWeight > 0.0f)
                        normalizationFactor = 1.0f / totalWeight;

                    for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j)
                    {
                        vBuf->vertices_[i->first_].blendIndices_[j] = i->second_[j].boneIndex_;
                        vBuf->vertices_[i->first_].blendWeights_[j] = i->second_[j].weight_ * normalizationFactor;
                    }

                    // If there are less than 4 blend weights, fill rest with zero
                    for (unsigned j = i->second_.Size(); j < 4; ++j)
                    {
                        vBuf->vertices_[i->first_].blendIndices_[j] = 0;
                        vBuf->vertices_[i->first_].blendWeights_[j] = 0.0f;
                    }

                    vBuf->vertices_[i->first_].hasBlendWeights_ = true;
                }
            }
        }
        else if (boneAssignments)
            PrintLine("No skeleton loaded, skipping skinning information");

        // Calculate center for the subgeometry
        Vector3 center = Vector3::ZERO;
        for (unsigned i = 0; i < iBuf->indices_.Size(); i += 3)
        {
            center += vBuf->vertices_[iBuf->indices_[i]].position_;
            center += vBuf->vertices_[iBuf->indices_[i + 1]].position_;
            center += vBuf->vertices_[iBuf->indices_[i + 2]].position_;
        }
        if (iBuf->indices_.Size())
            center /= (float)iBuf->indices_.Size();
        subGeometryCenters_.Push(center);

        indexStart += indices;
        vertexStart += vertices;

        OptimizeIndices(&subGeometryLodLevel, vBuf, iBuf);

        PrintLine("Processed submesh " + String(subMeshIndex + 1) + ": " + String(vertices) + " vertices " +
                  String(triangles) + " triangles");
        Vector<ModelSubGeometryLodLevel> thisSubGeometry;
        thisSubGeometry.Push(subGeometryLodLevel);
        subGeometries_.Push(thisSubGeometry);

        subMesh = subMesh.GetNext("submesh");
        subMeshIndex++;
    }

    // Process LOD levels, if any
    XMLElement lods = root.GetChild("levelofdetail");
    if (lods)
    {
        try
        {
            // For now, support only generated LODs, where the vertices are the same
            XMLElement lod = lods.GetChild("lodgenerated");
            while (lod)
            {
                float distance = M_EPSILON;
                if (lod.HasAttribute("fromdepthsquared"))
                    distance = sqrtf(lod.GetFloat("fromdepthsquared"));
                if (lod.HasAttribute("value"))
                    distance = lod.GetFloat("value");
                XMLElement lodSubMesh = lod.GetChild("lodfacelist");
                while (lodSubMesh)
                {
                    unsigned subMeshIndex = lodSubMesh.GetInt("submeshindex");
                    unsigned triangles = lodSubMesh.GetInt("numfaces");

                    ModelSubGeometryLodLevel newLodLevel;
                    ModelSubGeometryLodLevel& originalLodLevel = subGeometries_[subMeshIndex][0];

                    // Copy all initial values
                    newLodLevel = originalLodLevel;

                    ModelVertexBuffer* vBuf;
                    ModelIndexBuffer* iBuf;

                    if (useOneBuffer_)
                    {
                        vBuf = &vertexBuffers_[0];
                        iBuf = &indexBuffers_[0];
                    }
                    else
                    {
                        vBuf = &vertexBuffers_[subMeshIndex];
                        iBuf = &indexBuffers_[subMeshIndex];
                    }

                    unsigned indexStart = iBuf->indices_.Size();
                    unsigned indexCount = triangles * 3;
                    unsigned vertexStart = vertexStarts[subMeshIndex];

                    newLodLevel.distance_ = distance;
                    newLodLevel.indexStart_ = indexStart;
                    newLodLevel.indexCount_ = indexCount;

                    // Append indices to the original index buffer
                    XMLElement triangle = lodSubMesh.GetChild("face");
                    while (triangle)
                    {
                        unsigned v1 = triangle.GetInt("v1");
                        unsigned v2 = triangle.GetInt("v2");
                        unsigned v3 = triangle.GetInt("v3");
                        iBuf->indices_.Push(v3 + vertexStart);
                        iBuf->indices_.Push(v2 + vertexStart);
                        iBuf->indices_.Push(v1 + vertexStart);
                        triangle = triangle.GetNext("face");
                    }

                    OptimizeIndices(&newLodLevel, vBuf, iBuf);

                    subGeometries_[subMeshIndex].Push(newLodLevel);
                    PrintLine("Processed LOD level for submesh " + String(subMeshIndex + 1) + ": distance " + String(distance));

                    lodSubMesh = lodSubMesh.GetNext("lodfacelist");
                }
                lod = lod.GetNext("lodgenerated");
            }
        }
        catch (...) {}
    }

    // Process poses/morphs
    // First find out all pose definitions
    if (exportMorphs)
    {
        try
        {
            Vector<XMLElement> poses;
            XMLElement posesRoot = root.GetChild("poses");
            if (posesRoot)
            {
                XMLElement pose = posesRoot.GetChild("pose");
                while (pose)
                {
                    poses.Push(pose);
                    pose = pose.GetNext("pose");
                }
            }

            // Then process animations using the poses
            XMLElement animsRoot = root.GetChild("animations");
            if (animsRoot)
            {
                XMLElement anim = animsRoot.GetChild("animation");
                while (anim)
                {
                    String name = anim.GetAttribute("name");
                    float length = anim.GetFloat("length");
                    HashSet<unsigned> usedPoses;
                    XMLElement tracks = anim.GetChild("tracks");
                    if (tracks)
                    {
                        XMLElement track = tracks.GetChild("track");
                        while (track)
                        {
                            XMLElement keyframes = track.GetChild("keyframes");
                            if (keyframes)
                            {
                                XMLElement keyframe = keyframes.GetChild("keyframe");
                                while (keyframe)
                                {
                                    float time = keyframe.GetFloat("time");
                                    XMLElement poseref = keyframe.GetChild("poseref");
                                    // Get only the end pose
                                    if (poseref && time == length)
                                        usedPoses.Insert(poseref.GetInt("poseindex"));

                                    keyframe = keyframe.GetNext("keyframe");
                                }
                            }
                            track = track.GetNext("track");
                        }
                    }

                    if (usedPoses.Size())
                    {
                        ModelMorph newMorph;
                        newMorph.name_ = name;

                        if (useOneBuffer_)
                            newMorph.buffers_.Resize(1);
                        else
                            newMorph.buffers_.Resize(usedPoses.Size());

                        unsigned bufIndex = 0;

                        for (HashSet<unsigned>::Iterator i = usedPoses.Begin(); i != usedPoses.End(); ++i)
                        {
                            XMLElement pose = poses[*i];
                            unsigned targetSubMesh = pose.GetInt("index");
                            XMLElement poseOffset = pose.GetChild("poseoffset");

                            if (useOneBuffer_)
                                newMorph.buffers_[bufIndex].vertexBuffer_ = 0;
                            else
                                newMorph.buffers_[bufIndex].vertexBuffer_ = targetSubMesh;

                            newMorph.buffers_[bufIndex].elementMask_ = MASK_POSITION;

                            ModelVertexBuffer* vBuf = &vertexBuffers_[newMorph.buffers_[bufIndex].vertexBuffer_];

                            while (poseOffset)
                            {
                                // Convert from right- to left-handed
                                unsigned vertexIndex = poseOffset.GetInt("index") + vertexStarts[targetSubMesh];
                                float x = poseOffset.GetFloat("x");
                                float y = poseOffset.GetFloat("y");
                                float z = poseOffset.GetFloat("z");
                                Vector3 vec(x, y, -z);

                                if (vBuf->morphCount_ == 0)
                                {
                                    vBuf->morphStart_ = vertexIndex;
                                    vBuf->morphCount_ = 1;
                                }
                                else
                                {
                                    unsigned first = vBuf->morphStart_;
                                    unsigned last = first + vBuf->morphCount_ - 1;
                                    if (vertexIndex < first)
                                        first = vertexIndex;
                                    if (vertexIndex > last)
                                        last = vertexIndex;
                                    vBuf->morphStart_ = first;
                                    vBuf->morphCount_ = last - first + 1;
                                }

                                ModelVertex newVertex;
                                newVertex.position_ = vec;
                                newMorph.buffers_[bufIndex].vertices_.Push(MakePair(vertexIndex, newVertex));
                                poseOffset = poseOffset.GetNext("poseoffset");
                            }

                            if (!useOneBuffer_)
                                ++bufIndex;
                        }
                        morphs_.Push(newMorph);
                        PrintLine("Processed morph " + name + " with " + String(usedPoses.Size()) + " sub-poses");
                    }

                    anim = anim.GetNext("animation");
                }
            }
        }
        catch (...) {}
    }

    // Check any of the buffers for vertices with missing blend weight assignments
    for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
    {
        if (vertexBuffers_[i].elementMask_ & MASK_BLENDWEIGHTS)
        {
            for (unsigned j = 0; j < vertexBuffers_[i].vertices_.Size(); ++j)
                if (!vertexBuffers_[i].vertices_[j].hasBlendWeights_)
                    ErrorExit("Found a vertex with missing skinning information");
        }
    }

    // Tangent generation
    if (generateTangents)
    {
        for (unsigned i = 0; i < subGeometries_.Size(); ++i)
        {
            for (unsigned j = 0; j < subGeometries_[i].Size(); ++j)
            {
                ModelVertexBuffer& vBuf = vertexBuffers_[subGeometries_[i][j].vertexBuffer_];
                ModelIndexBuffer& iBuf = indexBuffers_[subGeometries_[i][j].indexBuffer_];
                unsigned indexStart = subGeometries_[i][j].indexStart_;
                unsigned indexCount = subGeometries_[i][j].indexCount_;

                // If already has tangents, do not regenerate
                if (vBuf.elementMask_ & MASK_TANGENT || vBuf.vertices_.Empty() || iBuf.indices_.Empty())
                    continue;

                vBuf.elementMask_ |= MASK_TANGENT;

                if ((vBuf.elementMask_ & (MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1)) != (MASK_POSITION | MASK_NORMAL |
                        MASK_TEXCOORD1))
                    ErrorExit("To generate tangents, positions normals and texcoords are required");

                GenerateTangents(&vBuf.vertices_[0], sizeof(ModelVertex), &iBuf.indices_[0], sizeof(unsigned), indexStart,
                                 indexCount, offsetof(ModelVertex, normal_), offsetof(ModelVertex, texCoord1_), offsetof(ModelVertex,
                                         tangent_));

                PrintLine("Generated tangents");
            }
        }
    }
}
示例#4
0
HeightMap::HeightMap(const std::string& name)
{
	std::ifstream file(name.c_str(), ios::binary);

	if (!file) return;

	numVertices = RAW_WIDTH * RAW_HEIGHT;
	numIndices = (RAW_WIDTH-1) * (RAW_HEIGHT-1)*6;

	vertices = new Vector3[numVertices];
	textureCoords = new Vector2[numVertices];
	colours = new Vector4[numVertices]; //NEW
	indices = new GLuint[numIndices];

	//Load in all char data from file
	unsigned char* data = new unsigned char[numVertices];
	file.read((char*) data, numVertices*sizeof(unsigned char));
	file.close();

	//Create our vertices and texture data from file
	for (int x = 0; x < RAW_WIDTH; ++x){
		for (int z=0; z < RAW_HEIGHT; ++z){
			int offset = (x * RAW_WIDTH) + z;

			//Scaled by a pre determined factor (modifying the terrain loaded 
			//from file)
			vertices[offset] = Vector3(x * HEIGHTMAP_X - (HEIGHTMAP_X * RAW_WIDTH * 0.5f), 
				data[offset] * HEIGHTMAP_Y, z * HEIGHTMAP_Z - (HEIGHTMAP_Z * RAW_HEIGHT * 0.5f));

			/*if (vertices[offset].y < 100.0f)
				colours[offset] = Vector4(0.2f, 0.2f, 0.2f, 0.2f);
			else 
				colours[offset] = Vector4(1.0f, 1.0f, 1.0f, 1.0f);*/

			colours[offset] = Vector4(vertices[offset].y / 200.0f,
				vertices[offset].y / 200.0f, vertices[offset].y / 200.0f,
				vertices[offset].y / 200.0f);

			textureCoords[offset] = Vector2(
				x * HEIGHTMAP_TEX_X, z * HEIGHTMAP_TEX_Z);
		}
	}

	delete data;

	numIndices = 0;

	for (int x = 0; x < RAW_WIDTH-1; ++x){
		for (int z = 0; z < RAW_HEIGHT-1; ++z){
			int a = (x * (RAW_WIDTH)) + z;
			int b = ((x+1) * RAW_WIDTH) + z;
			int c = ((x+1) * RAW_WIDTH) + (z+1);
			int d = (x * RAW_WIDTH) + (z+1);

			indices[numIndices++] = c;
			indices[numIndices++] = b;
			indices[numIndices++] = a;

			indices[numIndices++] = a;
			indices[numIndices++] = d;
			indices[numIndices++] = c;
		}
	}


	GenerateNormals(); //For lighting calculations!
	GenerateTangents(); //For bump mapping! :D
	BufferData();
}
HeightMap::HeightMap(std::string name) {

	std::ifstream file(name.c_str(), ios::binary);
	if(!file) {
		return;
	}

	type = GL_TRIANGLES ;

	numVertices = RAW_WIDTH*RAW_HEIGHT;
	numIndices = (RAW_WIDTH-1)*(RAW_HEIGHT-1)*6;
	vertices = new Vector3[numVertices];
	textureCoords = new Vector2[numVertices];
	indices = new GLuint[numIndices];

	unsigned char* data = new unsigned char[numVertices];
	file.read((char*)data,numVertices*sizeof(unsigned char));
	file.close();

	// Adding some
	float Min = 1096162876;
	float Max = FLT_MIN;
	//int flag = 0;
	// Min = 0 --- Max = 66048
	for(int x = 0; x < RAW_WIDTH; ++x){
		for(int z = 0; z < RAW_HEIGHT; ++z) {
			int offset = (x * RAW_WIDTH) +z;

			//if(flag == 0){Min = offset;flag++;}


			float height =  data[offset] * HEIGHT_Y;

			vertices[offset] = Vector3(x * HEIGHT_X, data[offset] * HEIGHT_Y, z * HEIGHT_Z);
			//cout << height << endl;
			//if(height < 90){
				//colour[offset] = 
			textureCoords[offset] = Vector2(x * HEIGHTMAP_TEX_X, z * HEIGHTMAP_TEX_Z);


			if (height > Max)
				Max = height;
			
			if (height < Min)	
				Min = height;
			

		}

	}

	//cout << "MIN : " << Min << "\t MAX: " << Max << endl;

	delete data;

	numIndices = 0;

	for(int x = 0; x < RAW_WIDTH-1; ++x){
		for(int z =0; z < RAW_HEIGHT-1; ++z){
			int a = (x * (RAW_WIDTH)) + z;
			int b = ((x+1) * (RAW_WIDTH)) + z;
			int c = ((x+1) * (RAW_WIDTH)) + (z+1);
			int d = (x * (RAW_WIDTH)) + (z+1);

			indices[numIndices++] = c;
			indices[numIndices++] = b;
			indices[numIndices++] = a;

			indices[numIndices++] = a;
			indices[numIndices++] = d;
			indices[numIndices++] = c;

		}
	}
	//Tutorial 11 A - Lighting
	GenerateNormals();
	GenerateTangents();
	BufferData();
}
HeightMap::HeightMap(std::string name){
	//Temp Variable
	Vector3 maxXYZ = Vector3(0);
	Vector3 minXYZ = Vector3(0);

	////Setup Perlin noise Generater
	//srand((unsigned int) time(NULL)); //Reseed Random Seed....
	//int randomSeed = rand();
	//PerlinNoise* perlinNoiseF1 = new PerlinNoise(0.45,0.05,300,6,randomSeed);	

	//Physics Particle Construction
	//particleNode = new PhysicsNode*[RAW_WIDTH];
	//for(int i = 0; i < RAW_WIDTH;i++){ particleNode[i] = new PhysicsNode[RAW_HEIGHT]; }
	
	//HeightMap Generation
	std::ifstream file (name.c_str(),ios::binary);
	if (! file ) { return ; }

	numVertices = RAW_WIDTH*RAW_HEIGHT;
	numIndices = (RAW_WIDTH-1)*(RAW_HEIGHT-1)*6;
	vertices = new Vector3[numVertices];
	textureCoords = new Vector2[numVertices];
	indices = new GLuint[numIndices];
	unsigned char * data = new unsigned char [numVertices];
	file.read((char*)data,numVertices*sizeof(unsigned char));
	file.close();

	for (int x = 0; x < RAW_WIDTH ; ++ x ) {
		for (int z = 0; z < RAW_HEIGHT ; ++ z ) {

		//Simple Height Map Reshape
			//float mid = RAW_WIDTH/2 - abs((RAW_WIDTH-x)-(RAW_WIDTH/2));
			//float midz = RAW_WIDTH/2 - abs((RAW_WIDTH-z)-(RAW_WIDTH/2));
			//mid = mid/(RAW_WIDTH/2);
			//midz = midz/(RAW_WIDTH/2);
			//mid = mid* midz;
			//mid += 0.2;
			//mid *= 3;

		//Buffer Data into array 
			int offset = ( x * RAW_WIDTH ) + z ;
			
			//if(!usePerlinNoise) {
				vertices[offset] = Vector3(x*HEIGHTMAP_X , data [ offset ] * HEIGHTMAP_Y /** mid*/ , z * HEIGHTMAP_Z );
			//} else {
			//	double heightNoise = perlinNoiseF1->GetHeight(x,z);
			//	vertices[offset] = Vector3(x*HEIGHTMAP_X ,heightNoise * HEIGHTMAP_Y * mid + 100, z * HEIGHTMAP_Z );
			//}
			textureCoords[offset] = Vector2(x*HEIGHTMAP_TEX_X , z * HEIGHTMAP_TEX_Z );
			
		////Setup ParticleNode
		//	particleNode[x][z].m_position = vertices[offset];			
		//	particleNode[x][z].s1->m_pos = vertices[offset];			
		//	particleNode[x][z].boundingBox->m_pos = vertices[offset];

		//	particleNode[x][z].SetInverseMass(HEIGHTMAP_MASS);

		//	particleNode[x][z].s1->m_radius = 10.0f;
		//	particleNode[x][z].boundingBox->halfdims = 10.0f;
		//	particleNode[x][z].boundingBox->useSubList = false;			
		//	particleNode[x][z].boundingBox->useOctTree = false;			
		//	particleNode[x][z].isSlept = true;
		//	//if(offset%HEIGHTMAP_COLLSION_SEPARATION == 0){particleList.push_back(&particleNode[x][z]);}

		////Max and Min XYZ Detection
		//	if(x == 0 && z == 0){
		//		maxXYZ = particleNode[x][z].m_position;
		//		minXYZ = particleNode[x][z].m_position;
		//	} else {
		//		if(maxXYZ.x < particleNode[x][z].m_position.x){ maxXYZ.x = particleNode[x][z].m_position.x; }
		//		if(maxXYZ.y < particleNode[x][z].m_position.y){	maxXYZ.y = particleNode[x][z].m_position.y; }
		//		if(maxXYZ.z < particleNode[x][z].m_position.z){	maxXYZ.z = particleNode[x][z].m_position.z; }
		//		if(minXYZ.x > particleNode[x][z].m_position.x){ minXYZ.x = particleNode[x][z].m_position.x; }
		//		if(minXYZ.y > particleNode[x][z].m_position.y){ minXYZ.y = particleNode[x][z].m_position.y; }
		//		if(minXYZ.z > particleNode[x][z].m_position.z){ minXYZ.z = particleNode[x][z].m_position.z; }
		//	}
		}
	}
	//delete data ;
	//delete perlinNoiseF1;

	//Indices Bonding Code
	numIndices = 0;
	for (int x = 0; x < RAW_WIDTH -1; ++ x ) {
		for (int z = 0; z < RAW_HEIGHT -1; ++ z ) {
			int a = (x * ( RAW_WIDTH )) + z ;
			int b = ((x +1) * ( RAW_WIDTH )) + z ;
			int c = ((x +1) * ( RAW_WIDTH )) + ( z +1);
			int d = (x * ( RAW_WIDTH )) + ( z +1);
			indices [numIndices ++] = c ;
			indices [numIndices ++] = b ;
			indices [numIndices ++] = a ;

			indices [numIndices ++] = a ;
			indices [numIndices ++] = d ;
			indices [numIndices ++] = c ;
		}
	}
	GenerateTangents();
	GenerateNormals();
	BufferData();

	//Custom Normal Calculation for Collision Impulse
	for (int i = 0; i < RAW_WIDTH -1; ++ i ) {
		for (int j = 0; j < RAW_HEIGHT-1 ; ++ j ) {
			int origin = (i * ( RAW_WIDTH )) + j ; //Origin
			int top = ((i +1) * ( RAW_WIDTH )) + j ; //Top				
			int bottom = ((i -1) * ( RAW_WIDTH )) + j ; //Bottom
			int left = ( i * ( RAW_WIDTH )) + ( j +1); //Left
			int right = ( i * ( RAW_WIDTH )) + ( j -1); //Right
			Vector3 surfaceNormal = normal[origin];
			
			if(top >= 0 && top < numVertices){ surfaceNormal += normal[top];}
			if(bottom >= 0 && bottom < numVertices){ surfaceNormal += normal[bottom];}
			if(left >= 0 && left < numVertices){ surfaceNormal += normal[left]; }
			if(right >= 0 && right < numVertices){ surfaceNormal += normal[right];}
			surfaceNormal.Normalise();
			
			////Set custom facing normal for particle
			//particleNode[i][j].useSelfNormal = true;
			//particleNode[i][j].collisionNormal = surfaceNormal;			
		}
	}

	////HeightMap Done Generation,Structure particle node into Oct Tree
	//mapTree = new OctTree(Vector3(minXYZ+((maxXYZ-minXYZ)/2)),Vector3((maxXYZ-minXYZ)/2),1);
	//for(vector<PhysicsNode*>::iterator i = particleList.begin(); i != particleList.end(); ++i) { mapTree->add((*i));}
	//
	////Create Bounding Box For HeightMap and Set Collision Type
	//physicsBound = new PhysicsNode();	
	//physicsBound-> boundingBox->m_pos = Vector3(minXYZ+((maxXYZ-minXYZ)/2));
	//physicsBound-> boundingBox->halfdims = Vector3((maxXYZ-minXYZ)/2);
	//physicsBound-> boundingBox->useSubList = false;
	//physicsBound-> boundingBox->useOctTree = true;
	//physicsBound-> boundingBox->ListPtr = mapTree;
	//physicsBound-> isSlept = true;

	////Add into Physics System
	//if(HEIGHTMAP_COLLIABLE)PhysicsSystem::GetPhysicsSystem().AddNode(physicsBound);
}
示例#7
0
Trunk::Trunk(GLuint textureInt,GLuint bumpMap, Vector3 topCenterCoord, Vector3 topNormal, float topDiameter, float rootDiameter, float maxHeight, float height) : Mesh(GL_TRIANGLES)
{
	this->topNormal = topNormal;
	this->topDiameter = topDiameter;
	this->rootDiameter = rootDiameter;
	this->topCenterCoord = topCenterCoord;
	this->maxHeight = maxHeight;
	this->height = height;

	float topBottomRate = topDiameter / rootDiameter;
	float textureHeight = height - ((int)height / 100) * 100;

	numVertices = VERTICES_PER_CIRCLE * 2 + 2;
	numIndices = VERTICES_PER_CIRCLE * 3 * 2 + 2;
	vertices = new Vector3[numVertices];
	//colours = new Vector4[numVertices];
	textureCoords = new Vector2[numVertices];
	indices = new GLuint[numIndices];
	//initialize the vertices and their texture coordinate for the root circle
	for (int k = 0; k < VERTICES_PER_CIRCLE; ++k)
	{
		int degree = k * 360 / VERTICES_PER_CIRCLE;
		degree = degree % 360;
		vertices[k] = Trunk::vertexCoordOfCircle(Vector3(0, 1, 0), Vector3(0, 0, 0), rootDiameter / 2, degree);
		//colours[k] = Vector4(1.0f, 1.0f, 1.0f, 1.0f);
		textureCoords[k] = Vector2(((PI * rootDiameter / TEXTURE_SCALE) * degree / 360), textureHeight / TEXTURE_SCALE);
	}
	//initialize the vertices and their texture coordinate for the top circle
	for (int k = VERTICES_PER_CIRCLE; k < VERTICES_PER_CIRCLE * 2 + 1; ++k)
	{
		int degree = k * 360 / VERTICES_PER_CIRCLE;
		degree = degree % 360;
		vertices[k] = Trunk::vertexCoordOfCircle(topNormal, topCenterCoord, topDiameter / 2, degree);
		//colours[k] = Vector4(1.0f, 1.0f, 1.0f, 1.0f);
		textureCoords[k] = Vector2((float)(((PI * topDiameter) / TEXTURE_SCALE / topBottomRate) * degree / 360), (float)((topCenterCoord.y + textureHeight) / TEXTURE_SCALE));
	}
	//put two extra vertices in the end of the cylinder, to better maping the texture.
	vertices[VERTICES_PER_CIRCLE * 2] = vertices[0];
	vertices[VERTICES_PER_CIRCLE * 2 + 1] = vertices[VERTICES_PER_CIRCLE];
	textureCoords[VERTICES_PER_CIRCLE * 2] = Vector2((float)(PI * rootDiameter / TEXTURE_SCALE), textureHeight / TEXTURE_SCALE);
	textureCoords[VERTICES_PER_CIRCLE * 2 + 1] = Vector2((float)(PI * topDiameter / TEXTURE_SCALE / topBottomRate), ((topCenterCoord.y + textureHeight) / TEXTURE_SCALE));
	//initialize the index
	numIndices = 0;
	for (int z = 0; z < VERTICES_PER_CIRCLE - 1; ++z)
	{
		int a = z;
		int b = VERTICES_PER_CIRCLE + z;
		int c = VERTICES_PER_CIRCLE + z + 1;
		int d = z + 1;

		indices[numIndices++] = a;
		indices[numIndices++] = d;
		indices[numIndices++] = b;

		indices[numIndices++] = c;
		indices[numIndices++] = b;
		indices[numIndices++] = d;
	}
	//initialize the last part of the cylinder
	int a = VERTICES_PER_CIRCLE - 1;
	int b = VERTICES_PER_CIRCLE + VERTICES_PER_CIRCLE - 1;
	int c = VERTICES_PER_CIRCLE * 2 + 1;
	int d = VERTICES_PER_CIRCLE * 2;
	indices[numIndices++] = a;
	indices[numIndices++] = d;
	indices[numIndices++] = b;

	indices[numIndices++] = c;
	indices[numIndices++] = b;
	indices[numIndices++] = d;

	GenerateNormals();
	GenerateTangents();
	SetTexture(textureInt);
	SetBumpMap(bumpMap);

	BufferData();
}