void Mesh::generateNormals() { _normals.clear(); _normals = std::vector<Vector3>(_vertices.size(), Vector3(0.0,1.0,0.0)); for (unsigned int i=0; i!=_triangles.size(); ++i) { unsigned int* vindex = _triangles[i].vertexIndices; Point3 vertex0 = _vertices[vindex[0]]; Point3 vertex1 = _vertices[vindex[1]]; Point3 vertex2 = _vertices[vindex[2]]; Vector3 a(vertex1 - vertex0); Vector3 b(vertex2 - vertex1); Vector3 c(vertex0 - vertex2); Vector3 n0 = cross(c, a).normalized(); Vector3 n1 = cross(a, b).normalized(); Vector3 n2 = cross(b, c).normalized(); _normals[vindex[0]] += n0; _triangles[i].vertexIndices[0] = vindex[0]; _normals[vindex[1]] += n1; _triangles[i].vertexIndices[1] = vindex[1]; _normals[vindex[2]] += n2; _triangles[i].vertexIndices[2] = vindex[2]; } normalizeNormals(); }
Geometry& subdivide(Geometry& geo, int amount) { while (amount--) { Geometry subdivided; subdivided.positions.reserve(geo.positions.size() * 4); subdivided.texcoords.reserve(geo.texcoords.size() * 4); subdivided.normals.reserve(geo.normals.size() * 4); subdivided.quads.reserve(geo.quads.size() * 4); for (const auto& quad : geo.quads) { uint base = subdivided.positions.size(); subdiv(quad, subdivided.positions, geo.positions); subdiv(quad, subdivided.texcoords, geo.texcoords); subdiv(quad, subdivided.normals, geo.normals); subdivided.quads.emplace_back(base + 0, base + 1, base + 8, base + 7); subdivided.quads.emplace_back(base + 1, base + 2, base + 3, base + 8); subdivided.quads.emplace_back(base + 8, base + 3, base + 4, base + 5); subdivided.quads.emplace_back(base + 7, base + 8, base + 5, base + 6); } geo = std::move(subdivided); normalizeNormals(geo); } return geo; }
void Terrain::makeTerrain() { DsChunkPtr ch = world->generateChunk(0, 0); double* map = ch->getMap(); side = static_cast<int>(pow(2, DsWorld::CHUNK_SIZE)) + 1; geom = new Geometry(); //Pass 1: Fill vertex and texcoord data. Normals will be accumulated on step 2 and normalized on step 3. fillGeometry(map); //Pass 2: Make faces and accumulate per-vertex normals /* v1-------v2 | even / | | / | | / odd | v3-------v4 */ makeFacesAndNormals(); //Pass 3: Normalize normals normalizeNormals(); vbo = new TerrainVbo(*geom); delete[] map; }
void Mesh::transform(const Matrix& matrix, bool normalizeNormalVectors) { // vertices for (unsigned int i=0; i!=_vertices.size(); ++i) { _vertices[i] = matrix * _vertices[i]; } // normals for (unsigned int i=0; i!=_normals.size(); ++i) { _normals[i] = matrix * _normals[i]; } // for interleaved data if (_interleavedAttributes.size()) { // size of one interleaved vertex + attributes int indexStepWidth = _interleavedInfo.interleavedPackageSize; int vertexPos = _interleavedInfo.interleavedVertexOffset; int normalPos = _interleavedInfo.interleavedNormalOffset;; // positions for (unsigned int i=vertexPos; i<_interleavedAttributes.size(); ) { gloost::Point3 vertex(_interleavedAttributes[i], // x _interleavedAttributes[i+1], // y _interleavedAttributes[i+2]); // z vertex = matrix * vertex; _interleavedAttributes[i] = vertex[0]; _interleavedAttributes[i+1] = vertex[1]; _interleavedAttributes[i+2] = vertex[2]; i += indexStepWidth; } if (normalPos) { // normals for (unsigned int i=normalPos; i<_interleavedAttributes.size(); ) { gloost::Vector3 normal(_interleavedAttributes[i], // x _interleavedAttributes[i+1], // y _interleavedAttributes[i+2]); // z normal = matrix * normal; _interleavedAttributes[i] = normal[0]; _interleavedAttributes[i+1] = normal[1]; _interleavedAttributes[i+2] = normal[2]; i += indexStepWidth; } } } // bounding box recalcBoundingBox(); // normalize normals if (normalizeNormalVectors) { normalizeNormals(); } }