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); }
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(); }
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"); } } } }
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); }
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(); }