Vector ClosestPointPoly ( Vector const & V, VertexList const & vertices ) { if(vertices.size() == 0) return V; if(vertices.size() == 1) return vertices[0]; if(vertices.size() == 2) return ClosestPointSeg( V, Segment3d(vertices[0],vertices[1]) ); // ---------- Vector closest = ClosestPointTri( V, Triangle3d(vertices[0],vertices[1],vertices[2]) ); int nTris = vertices.size() - 2; for(int i = 1; i < nTris; i++) { Triangle3d tri( vertices[0], vertices[i+1], vertices[i+2] ); Vector temp = ClosestPointTri(V,tri); closest = selectCloser(V,closest,temp); } return closest; }
void Cylinder::buildTopCap(VertexList& vertices, IndexList& indices) { UINT baseIndex = (UINT)vertices.size(); // Duplicate cap vertices because the texture coordinates and normals differ. float y = 0.5f*mHeight; // vertices of ring float dTheta = 2.0f*PI/mNumSlices; for(UINT i = 0; i <= mNumSlices; ++i) { float x = mTopRadius*cosf(i*dTheta); float z = mTopRadius*sinf(i*dTheta); // Map [-1,1]-->[0,1] for planar texture coordinates. float u = +0.5f*x/mTopRadius + 0.5f; float v = -0.5f*z/mTopRadius + 0.5f; vertices.push_back( Vertex(x, y, z, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, u, v) ); } // cap center vertex vertices.push_back( Vertex(0.0f, y, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f) ); // index of center vertex UINT centerIndex = (UINT)vertices.size()-1; for(UINT i = 0; i < mNumSlices; ++i) { indices.push_back(centerIndex); indices.push_back(baseIndex + i+1); indices.push_back(baseIndex + i); } }
void Mesh::construct() { if (!m_material || !m_geometry) { return; } destruct(); glGenVertexArrays(1, &m_vertexArray); glBindVertexArray(m_vertexArray); // Fill vertex position data glGenBuffers(1, &m_vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); VertexList vertices = m_geometry->vertices(); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW); glVertexAttribPointer((GLint)ShaderAttribute::VertexPosition, 3, GL_FLOAT, GL_FALSE, 0, bufferOffset(0)); glEnableVertexAttribArray((GLint)ShaderAttribute::VertexPosition); // Fill UV vertex data if (m_geometry->uvCount()) { glGenBuffers(1, &m_textureCoordinatesBuffer); glBindBuffer(GL_ARRAY_BUFFER, m_textureCoordinatesBuffer); UVList uvs = m_geometry->uvs(); glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), uvs.data(), GL_STATIC_DRAW); glVertexAttribPointer((GLint)ShaderAttribute::VertexTextureCoordinates, 2, GL_FLOAT, GL_FALSE, 0, bufferOffset(0)); glEnableVertexAttribArray((GLint)ShaderAttribute::VertexTextureCoordinates); } // Fill vertex normal data if (m_geometry->normalCount()) { glGenBuffers(1, &m_vertexNormalsBuffer); glBindBuffer(GL_ARRAY_BUFFER, m_vertexNormalsBuffer); VertexList normals = m_geometry->normals(); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), GL_STATIC_DRAW); glVertexAttribPointer((GLint)ShaderAttribute::VertexNormals, 3, GL_FLOAT, GL_FALSE, 0, bufferOffset(0)); glEnableVertexAttribArray((GLint)ShaderAttribute::VertexNormals); } // Fill index buffer glGenBuffers(1, &m_indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer); IndexList indices = m_geometry->indices(); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint32_t), indices.data(), GL_STATIC_DRAW); glBindVertexArray(0); m_dirty = false; }
NodePtr KDTree::makeTree(size_t depth, const size_t& cellSize, VertexLists& t, const Domain& domain){ /* * Tuple contains x, y, z Dimensions Vertex list * */ const size_t k = depth % m_K; VertexList vertices = t.at(k); if(vertices.size() == 0){ return nullptr; } if(vertices.size() <= cellSize){ return NodePtr(new Node(vertices, domain)); } size_t median = (int) (vertices.size()-1)/2; VertexPtr& posElement = vertices.at(median); //Split lists by median element std::vector< ListPair > pairs; for(size_t i=0; i<m_K; ++i){ pairs.push_back(splitListBy(k, t.at(i), posElement)); } VertexLists left; VertexLists right; for(ListPair pair: pairs){ left.push_back(std::get<0>(pair)); right.push_back(std::get<1>(pair)); } Domain leftBounds = domain; Domain rightBounds = domain; leftBounds.updateMax((*posElement)[k], k); rightBounds.updateMin((*posElement)[k], k); NodePtr leftNode; NodePtr rightNode; if(depth < 2){ thread lT([&] { leftNode = makeTree(depth+1, cellSize, left, leftBounds); }); thread rT([&] { rightNode = makeTree(depth+1, cellSize, right, rightBounds); }); lT.join(); rT.join(); }else{ leftNode = makeTree(depth+1, cellSize, left, leftBounds); rightNode = makeTree(depth+1, cellSize, right, rightBounds); } return NodePtr(new Node(leftNode, rightNode, domain)); };
Mesh::Mesh(VertexList const& vertices) : m_id(afth::UUID::v4()) { size_t size = vertices.size() * 3; float* arr = new float[size]; VertexList::const_iterator it = vertices.begin(), end = vertices.end(); for (size_t i = 0; it != end; ++it, i += 3) { std::memcpy(arr + i, (*it).coordinates().arr().data(), 3 * sizeof(float)); } //glGenVertexArrays(1, &m_vertexArray); //glGenBuffers(1, &m_vertexBuffer); //glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); //glBufferData(GL_ARRAY_BUFFER, size * sizeof(float), arr, GL_STATIC_DRAW); //glBindVertexArray(m_vertexArray); //GLint positionIndex = glGetAttribLocation(glProgramUniform1, "position"); //glEnableVertexAttribArray(0); //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); //glBindBuffer(GL_ARRAY_BUFFER, 0); //glBindVertexArray(0); delete [] arr; }
Drawable RenderingEngine::CreateDrawable(const ParametricSurface& surface, int flags) const { // Create the VBO for the vertices. VertexList vertices; surface.GenerateVertices(vertices, flags); GLuint vertexBuffer; glGenBuffers(1, &vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertices[0]), &vertices[0], GL_STATIC_DRAW); // Create a new VBO for the indices if needed. int indexCount = surface.GetTriangleIndexCount(); GLuint indexBuffer; IndexList indices(indexCount); surface.GenerateTriangleIndices(indices); glGenBuffers(1, &indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLushort), &indices[0], GL_STATIC_DRAW); // Fill in a descriptive struct and return it. Drawable drawable; drawable.IndexBuffer = indexBuffer; drawable.VertexBuffer = vertexBuffer; drawable.IndexCount = indexCount; drawable.Flags = flags; return drawable; }
void VertexListToBufP(std::vector<float> &dst,const VertexList &list){ dst.clear(); dst.reserve(list.size()*3); for(VertexList::const_iterator i = list.begin();i!=list.end();i++){ dst.push_back((*i).pos.x); dst.push_back((*i).pos.y); dst.push_back((*i).pos.z); } }
// copyVertexListToPointList a vector for Vec3 into a vector of Point's. void copyVertexListToPointList(const VertexList& in,PointList& out) { out.reserve(in.size()); for(VertexList::const_iterator itr=in.begin(); itr!=in.end(); ++itr) { out.push_back(Point(0,*itr)); } }
void StaticGeometryBuffer::_generateIndices() { _indexList.clear(); VertexList newVertList; //DebugText debugText; for( uint i = 0; i < _vertexList.size(); ++i ) { bool repeated = false; ///FLip uv's for openGL _vertexList[ i ].texCoord.y = 1 - _vertexList[ i ].texCoord.y; for( uint j = 0; j < newVertList.size(); ++j ) { repeated = _isSameVertex( _vertexList[ i ], newVertList[ j ] ); if( repeated ) { _indexList.push_back( j ); break; } } if( !repeated ) { newVertList.push_back( _vertexList[ i ] ); _indexList.push_back( newVertList.size() - 1 ); } } _vertexList = newVertList; }
//*************************************************************************************** // Name: BuildGeoSphere // Desc: Function approximates a sphere by tesselating an icosahedron. //*************************************************************************************** void BuildGeoSphere(UINT numSubdivisions, float radius, VertexList& vertices, IndexList& indices) { // Put a cap on the number of subdivisions. numSubdivisions = Min(numSubdivisions, UINT(5)); // Approximate a sphere by tesselating an icosahedron. const float X = 0.525731f; const float Z = 0.850651f; D3DXVECTOR3 pos[12] = { D3DXVECTOR3(-X, 0.0f, Z), D3DXVECTOR3(X, 0.0f, Z), D3DXVECTOR3(-X, 0.0f, -Z), D3DXVECTOR3(X, 0.0f, -Z), D3DXVECTOR3(0.0f, Z, X), D3DXVECTOR3(0.0f, Z, -X), D3DXVECTOR3(0.0f, -Z, X), D3DXVECTOR3(0.0f, -Z, -X), D3DXVECTOR3(Z, X, 0.0f), D3DXVECTOR3(-Z, X, 0.0f), D3DXVECTOR3(Z, -X, 0.0f), D3DXVECTOR3(-Z, -X, 0.0f) }; DWORD k[60] = { 1,4,0, 4,9,0, 4,5,9, 8,5,4, 1,8,4, 1,10,8, 10,3,8, 8,3,5, 3,2,5, 3,7,2, 3,10,7, 10,6,7, 6,11,7, 6,0,11, 6,1,0, 10,1,6, 11,0,9, 2,11,9, 5,2,9, 11,2,7 }; vertices.resize(12); indices.resize(60); for(int i = 0; i < 12; ++i) vertices[i] = pos[i]; for(int i = 0; i < 60; ++i) indices[i] = k[i]; for(UINT i = 0; i < numSubdivisions; ++i) Subdivide(vertices, indices); // Project vertices onto sphere and scale. for(size_t i = 0; i < vertices.size(); ++i) { D3DXVec3Normalize(&vertices[i], &vertices[i]); vertices[i] *= radius; } }
void ConvexPlanarPolygon::write(DataOutputStream* out) { // Write ConvexPlanarPolygon's identification. out->writeInt(IVECONVEXPLANARPOLYGON); // If the osg class is inherited by any other class we should also write this to file. //osg::Object* obj = dynamic_cast<osg::Object*>(this); //if(obj){ // ((ive::Object*)(obj))->write(out); //} //else // in_THROW_EXCEPTION("ConvexPlanarPolygon::write(): Could not cast this osg::ConvexPlanarPolygon to an osg::Object."); // Write ConvexPlanarPolygon's properties. // Write Vertex list VertexList vertexList = getVertexList(); int size = vertexList.size(); out->writeInt(size); for(int i=0; i<size; i++) { out->writeVec3(vertexList[i]); } }
void GeometryExportFile::writeSprite( Object *o, ofstream &out ) { // out << "OBJECT poly"<<endl; out << " WORLD (" << endl; out << " TEXTURES (" << endl; out << " MAX_TEXTURES (10)" << endl; out << " TEXTURE 'abstract_a032.gif' ()" << endl; out << " TEXTURE 'andrew_wood.gif' ()" << endl; out << " TEXTURE 'sydney.gif' ()" << endl; out << " TEXTURE 'bla.png' ()" << endl; out << " TEXTURE 'bla2.gif' ()" << endl; out << " )" << endl; // Don't know how to get the name. out << "SPRITE 'sydney'(" << endl; // Add the texture. // We also need to add the texture to the top of the world file. TextureMaterial *tm = o->getTextureMaterial(); if(tm != 0 && tm->texture != 0) { // Need to get the file name that the image will be in CS's VFS. // out << "TEXNR('"<<tm->texture->getFilename()->ascii()\ // << "')" <<endl; out << "TEXNR('bla2.gif')" << endl; } // Write the frames. err... "frame". We done needs verts, and // uv coordinates. // We are going to waste some vertices here. // // We are going to add an extra set of vertices // // for each face: // add to the new vertex list, the vertices in the face. // add to the new uv coords list, the uvs for the face. // // The triangle list will be made by consecutively using three vertices // from the list of vertices. VertexList *vlist = o->getVerts(); UVList *uvlist = o->getUVs(); vector<Vector4> new_vert_list; vector<Vector4> new_uv_list; int num_verts = ( int ) vlist->size(); int num_uvs = ( int ) uvlist->size(); //DEBUG // out << "num_verts is:" << num_verts << " num_uvs is:" << num_uvs <<endl; int num_faces = ( int ) o->numFaces(); int tris = -1; for(int i = 0; i < num_faces; i++) { Face *face = o->getFace( i ); vector<int> *face_vlist = face->getVerts(); vector<int> *face_uvlist = face->getUVs(); int v_size = ( int ) face_vlist->size(); int uv_size = ( int ) face_uvlist->size(); for(int ii = 0; ii < uv_size; ii++) { new_uv_list.push_back( face->getParentObject() ->getUVCoord( ( *face_uvlist ) [ ii ] ) ->getPosition() ); } for(int ii = 0; ii < v_size; ii++) { new_vert_list.push_back( face->getParentObject() ->getVertex( ( *face_vlist ) [ ii ] ) ->getPosition() ); } } // write out the frames... er just one frame for now. // DEBUG // out << "new_vert_list size:" << new_vert_list.size() << endl; // out << "new_uv_list size:" << new_uv_list.size() << endl; // Just place the name of the frame for now. out << "FRAME 'stand1' ("; for(uint i = 0; i < new_vert_list.size(); i++) { out << "V(" << new_vert_list[ i ].x << "," << new_vert_list[ i ].y << ","; // The z axis are oposite for I3D and CS. out << new_vert_list[ i ].z * -1 << ":"; // Have to convert systems, as cs uses x = 0, y = 0 at top left. // Inovation 3d uses bottom left. out << new_uv_list[ i ].x << "," << ( 1.0 - new_uv_list[ i ].y ) << ")"; out << endl; } out << ")" << endl; // write out the list of triangles. for(int i = 0; i < new_vert_list.size(); i += 3) { out << "TRIANGLE(" << i + 2 << "," << i + 1 << "," << i << ")" << endl; } }
void GeometryExportFile::writeModel( Object *o, ofstream &out ) { out << "{ 'MODL'\n" " { 'SRC' \"Innovation 3D exported by WF geometry exporter V0.11\"" " }\n" " { 'TRGT' \"World Foundy Game Engine (www.worldfoundry.org)\"\n" " }\n" << endl; out << " { 'NAME' \"" << o->getName() << "\"\n" " }\n"; out.setf(std::ios::showpoint); //Vector4 pos; float texturex=0; float texturey=0; float color=0; //pos = o->getPosition(); int oldWidth = out.width(8); char oldFill = out.fill('0'); // kts i3d is a left handed coordinate system with positive y up, WF is left handed with positive z up // so I rotate -90 degrees around x putting y up (swap y&z, negate the new y) VertexList *vlist = o->getVerts(); int size = (int)vlist->size(); Vector4 vertpos; Vector4 uv; for(int i=0; i<size; i++) { vertpos = (*vlist)[i]->getPosition(); VertexAndUV vuv; vuv.position = vertpos; } CreateVertUVList(o); WriteVertexList(out); out << " { 'MATL' //flags: [FLAT_SHADED=0, GOURAUD_SHADED=1] [SOLID_COLOR=0, TEXTURE_MAPPED=2] [SINGLE_SIDED=0, TWO_SIDED=8]" << endl; //save materials here. ObjectDB *odb = I3D::getDB(); TextureMaterial *m; for(int materialIndex=0; materialIndex<odb->numMaterials(); materialIndex++) { m = odb->getMaterial(materialIndex); _MaterialOnDisk mod; mod._materialFlags = 0; if(m->enable_texture) mod._materialFlags |= TEXTURE_MAPPED; for(int temp=0;temp<MATERIAL_NAME_LEN;temp++) mod.textureName[temp] = 0; if(m->texture) strncpy(mod.textureName, m->texture->getFilename()->ascii(), MATERIAL_NAME_LEN); mod.textureName[MATERIAL_NAME_LEN-1] = 0; // make sure it is 0 terminated mod._color = ((((unsigned int)m->cDiffuse.r)<<16) | (((unsigned int)m->cDiffuse.g)<<8) | ((unsigned int)m->cDiffuse.b)); out << " //Material " << materialIndex << ": flags: " << mod._materialFlags << ", color: " << hex << mod._color << dec << ", texturename: \"" << mod.textureName << "\"" << endl; out << " "; for(int index=0;index<sizeof(_MaterialOnDisk);index++) { out << (unsigned int)(((unsigned char*)&mod)[index]) << "y "; } out << " // #" << materialIndex << endl; } out << " }" << endl; // faces size = (int)o->numFaces(); out << " { 'FACE' // count = " << size << endl; for(int faceIndex=0; faceIndex<size; faceIndex++) { Face* face = o->getFace(faceIndex); vector<int> *vlist = face->getVerts(); vector<int> *uvlist = face->getUVs(); assert(vlist->size() >= 3); // must be at least a triangle // output list of triangles for this face // make a fan of triangles, first vertex is the same for all polys int vert1 = LookupVertUVEntry(CreateVUV(*face,vlist, 0, o->getTextureMaterial())); // second point int vert2 = LookupVertUVEntry(CreateVUV(*face,vlist, 1, o->getTextureMaterial())); for(int vertexIndex=2;vertexIndex<vlist->size();vertexIndex++) { VertexAndUV vuv3 = CreateVUV(*face,vlist, vertexIndex, o->getTextureMaterial()); int vert3 = LookupVertUVEntry(vuv3); int materialIndex = -1; if(o->getTextureMaterial() != 0) { materialIndex = I3D::getDB()->getMaterialIndex(o->getTextureMaterial()); } else cerr << "material not set!" << endl; out << " " << vert1 << "w " << vert2 << "w " << vert3 << "w " << materialIndex << "w // face #" << faceIndex << ", poly #" << vertexIndex << endl; // vert2 on next fan is vert3 from this fan vert2 = vert3; } } out << " }" << endl; out << "}" << endl; }
void FastMassSpring::initEdgeGraph( FaceList& face_list, VertexList& vertex_list, AdjList& vertex_share_faces) { this->P_Num = vertex_list.size() / 3; // building edge graph this->strech_edges.clear(); { int ptid[3] = {0, 0, 0}; for (decltype(face_list.size()) i = 0; i < face_list.size() / 3; ++i) { ptid[0] = face_list[3 * i + 0]; ptid[1] = face_list[3 * i + 1]; ptid[2] = face_list[3 * i + 2]; // the order of start point and end point doesn't matter this->strech_edges.push_back( ptid[0] < ptid[1] ? Edge(ptid[0], ptid[1]) : Edge(ptid[1], ptid[0])); this->strech_edges.push_back( ptid[1] < ptid[2] ? Edge(ptid[1], ptid[2]) : Edge(ptid[2], ptid[1])); this->strech_edges.push_back( ptid[2] < ptid[0] ? Edge(ptid[2], ptid[0]) : Edge(ptid[0], ptid[2])); } std::sort(this->strech_edges.begin(), this->strech_edges.end()); std::vector<Edge>::iterator iter = std::unique(this->strech_edges.begin(), this->strech_edges.end()); this->strech_edges.erase(iter, strech_edges.end()); this->strech_edges.shrink_to_fit(); // store rest length float cur_r = 0.0; this->strech_r_length.clear(); for (auto& i : this->strech_edges) { cur_r = 0.0; for (int j = 0; j < 3; ++j) { cur_r += pow(vertex_list[3 * i.first + j] - vertex_list[ 3 * i.second + j], 2); } this->strech_r_length.push_back(sqrt(cur_r)); } } this->bending_edges.clear(); { for (auto& i : this->strech_edges) { int cross_pi = -1; int cross_pj = -1; if (findShareVertex( cross_pi, cross_pj, i.first, i.second, vertex_share_faces, face_list)) { this->bending_edges.push_back( cross_pi < cross_pj ? Edge(cross_pi, cross_pj) : Edge(cross_pj, cross_pi)); } } // store rest length float cur_r = 0.0; this->bending_r_length.clear(); for (auto& i : this->bending_edges) { cur_r = 0.0; for (int j = 0; j < 3; ++j) { cur_r += pow(vertex_list[3 * i.first + j] - vertex_list[ 3 * i.second + j], 2); } this->bending_r_length.push_back(sqrt(cur_r)); } } // init d vector this->computedVector(); }
void Sphere::buildStacks(VertexList& vertices, IndexList& indices) { float phiStep = PI/mNumStacks; // do not count the poles as rings UINT numRings = mNumStacks-1; // Compute vertices for each stack ring. for(UINT i = 1; i <= numRings; ++i) { float phi = i*phiStep; // vertices of ring float thetaStep = 2.0f*PI/mNumSlices; for(UINT j = 0; j <= mNumSlices; ++j) { float theta = j*thetaStep; Vertex v; // spherical to cartesian v.pos.x = mRadius*sinf(phi)*cosf(theta); v.pos.y = mRadius*cosf(phi); v.pos.z = mRadius*sinf(phi)*sinf(theta); // partial derivative of P with respect to theta v.tangent.x = -mRadius*sinf(phi)*sinf(theta); v.tangent.y = 0.0f; v.tangent.z = mRadius*sinf(phi)*cosf(theta); D3DXVec3Normalize(&v.normal, &v.pos); v.texC.x = theta / (2.0f*PI); v.texC.y = phi / PI; vertices.push_back( v ); } } // poles: note that there will be texture coordinate distortion vertices.push_back( Vertex(0.0f, -mRadius, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f) ); vertices.push_back( Vertex(0.0f, mRadius, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f) ); UINT northPoleIndex = (UINT)vertices.size()-1; UINT southPoleIndex = (UINT)vertices.size()-2; UINT numRingVertices = mNumSlices+1; // Compute indices for inner stacks (not connected to poles). for(UINT i = 0; i < mNumStacks-2; ++i) { for(UINT j = 0; j < mNumSlices; ++j) { indices.push_back(i*numRingVertices + j); indices.push_back(i*numRingVertices + j+1); indices.push_back((i+1)*numRingVertices + j); indices.push_back((i+1)*numRingVertices + j); indices.push_back(i*numRingVertices + j+1); indices.push_back((i+1)*numRingVertices + j+1); } } // Compute indices for top stack. The top stack was written // first to the vertex buffer. for(UINT i = 0; i < mNumSlices; ++i) { indices.push_back(northPoleIndex); indices.push_back(i+1); indices.push_back(i); } // Compute indices for bottom stack. The bottom stack was written // last to the vertex buffer, so we need to offset to the index // of first vertex in the last ring. UINT baseIndex = (numRings-1)*numRingVertices; for(UINT i = 0; i < mNumSlices; ++i) { indices.push_back(southPoleIndex); indices.push_back(baseIndex+i); indices.push_back(baseIndex+i+1); } }
void ProgressiveTriangleGeometry::FindEdgeToCollapse(VertexList& /*org_vertex_list*/, TriangleList& /*org_triangle_list*/, VertexList& vertex_list, TriangleList& triangle_list, Edge& edge) { if (triangle_list.empty()) return; float current_error = 0.0f; float current_max_error = 0.0f; edge.v1_ = 0; edge.v2_ = 0; edge.triangle_list_.clear(); // Calculate mean error. VertexList::iterator v_iter; for (v_iter = vertex_list.begin(); v_iter != vertex_list.end(); ++v_iter) { if (v_iter == vertex_list.begin()) { current_max_error = (*v_iter)->error_; } else if((*v_iter)->error_ > current_max_error) { current_max_error = (*v_iter)->error_; } current_error += (*v_iter)->error_; } current_error /= (float)vertex_list.size(); float min_error = 0.0f; float min_error1 = 0.0f; // Temporary error value storage for _edge->v1_. float min_error2 = 0.0f; // Temporary error value storage for _edge->v2_. bool first = true; // Test vertex collaps on all triangles. TriangleList::iterator tri_iter; for (tri_iter = triangle_list.begin(); tri_iter != triangle_list.end(); ++tri_iter) { Triangle* triangle = *tri_iter; vec3 diff1; vec3 diff2; Vertex mid; // Test V1 and V2. mid.x() = (triangle->v1_->x() + triangle->v2_->x()) * 0.5f; mid.y() = (triangle->v1_->y() + triangle->v2_->y()) * 0.5f; mid.z() = (triangle->v1_->z() + triangle->v2_->z()) * 0.5f; // Calculate the distance between the new, merged position, // and the original vertex position. diff1.Set(mid.x() - triangle->v1_->twin_->x(), mid.y() - triangle->v1_->twin_->y(), mid.z() - triangle->v1_->twin_->z()); diff2.Set(mid.x() - triangle->v2_->twin_->x(), mid.y() - triangle->v2_->twin_->y(), mid.z() - triangle->v2_->twin_->z()); float error1 = diff1.GetLength() + triangle->v1_->error_; float error2 = diff2.GetLength() + triangle->v2_->error_; float error = (error1 + error2 + current_error) / 3.0f; if (first == true || error < min_error) { edge.v1_ = triangle->v1_; edge.v2_ = triangle->v2_; min_error1 = error1; min_error2 = error2; min_error = error; first = false; } // Test V2 and V3. mid.x() = (triangle->v2_->x() + triangle->v3_->x()) * 0.5f; mid.y() = (triangle->v2_->y() + triangle->v3_->y()) * 0.5f; mid.z() = (triangle->v2_->z() + triangle->v3_->z()) * 0.5f; // Calculate the distance between the new, merged position, // and the original vertex position. diff1.Set(mid.x() - triangle->v2_->twin_->x(), mid.y() - triangle->v2_->twin_->y(), mid.z() - triangle->v2_->twin_->z()); diff2.Set(mid.x() - triangle->v3_->twin_->x(), mid.y() - triangle->v3_->twin_->y(), mid.z() - triangle->v3_->twin_->z()); error1 = diff1.GetLength() + triangle->v1_->error_; error2 = diff2.GetLength() + triangle->v2_->error_; error = (error1 + error2 + current_error) / 3.0f; if (error < min_error) { edge.v1_ = triangle->v1_; edge.v2_ = triangle->v2_; min_error = error; min_error1 = error1; min_error2 = error2; } // Test V3 and V1. mid.x() = (triangle->v3_->x() + triangle->v1_->x()) * 0.5f; mid.y() = (triangle->v3_->y() + triangle->v1_->y()) * 0.5f; mid.z() = (triangle->v3_->z() + triangle->v1_->z()) * 0.5f; // Calculate the distance between the new, merged position, // and the original vertex position. diff1.Set(mid.x() - triangle->v3_->twin_->x(), mid.y() - triangle->v3_->twin_->y(), mid.z() - triangle->v3_->twin_->z()); diff2.Set(mid.x() - triangle->v1_->twin_->x(), mid.y() - triangle->v1_->twin_->y(), mid.z() - triangle->v1_->twin_->z()); error1 = diff1.GetLength() + triangle->v1_->error_; error2 = diff2.GetLength() + triangle->v2_->error_; error = (error1 + error2 + current_error) / 3.0f; if (error < min_error) { edge.v1_ = triangle->v1_; edge.v2_ = triangle->v2_; min_error = error; min_error1 = error1; min_error2 = error2; } if (min_error == 0.0f && edge.v1_ != 0 && edge.v2_ != 0) break; } edge.v1_->error_ = min_error1; edge.v2_->error_ = min_error2; // Now add all triangles to _edge that share the two vertices // _edge->v1_ and _edge->v2_. for (tri_iter = triangle_list.begin(); tri_iter != triangle_list.end(); ++tri_iter) { Triangle* triangle = *tri_iter; if (triangle->HaveVertex(edge.v1_) && triangle->HaveVertex(edge.v2_)) { edge.triangle_list_.push_back(triangle); } } }
//bool MeshXMLExporter::streamSubmesh(std::ostream &of, IGameNode *node, std::string &mtlName) { bool MeshXMLExporter::streamSubmesh(std::ostream &of, IGameObject *obj, std::string &mtlName) { //IGameObject* obj = node->GetIGameObject(); if (obj->GetIGameType() != IGameMesh::IGAME_MESH) return false; // InitializeData() is important -- it performs all of the WSM/time eval for us; no face data without it // obj->InitializeData(); IGameMesh* mesh = (IGameMesh*) obj; int vertCount = mesh->GetNumberOfVerts(); int faceCount = mesh->GetNumberOfFaces(); Tab<int> matIds = mesh->GetActiveMatIDs(); Tab<DWORD> smGrpIds = mesh->GetActiveSmgrps(); Tab<int> texMaps = mesh->GetActiveMapChannelNum(); of << "\t\t<submesh "; if (mtlName.length() > 0) of << "material=\"" << mtlName << "\" "; of << "usesharedvertices=\"false\" use32bitindexes=\""; of << (vertCount > 65535); of << "\">" << std::endl; // *************** Export Face List *************** of << "\t\t\t<faces count=\"" << faceCount << "\">" << std::endl; //std::vector<UVVert // iterate the face list, putting vertices in the list for this submesh VertexList vertexList; for (int i=0; i<faceCount; i++) { of << "\t\t\t\t<face"; FaceEx* face = mesh->GetFace(i); // do this for each vertex on the face for (int vi=0; vi<3; vi++) { Point3 p = mesh->GetVertex(face->vert[vi]); Vertex v(p.x, p.y, p.z); if (m_config.getExportVertexColours()) { Point3 c = mesh->GetColorVertex(face->vert[vi]); float a = mesh->GetAlphaVertex(face->vert[vi]); v.setColour(c.x, c.y, c.z, a); } Point3 n = mesh->GetNormal(face, vi); v.setNormal(n.x, n.y, n.z); // get each set of texcoords for this vertex for (int ch=0; ch < texMaps.Count(); ch++) { Point3 tv; DWORD indices[3]; if (mesh->GetMapFaceIndex(texMaps[ch], i, indices)) tv = mesh->GetMapVertex(texMaps[ch], indices[vi]); else tv = mesh->GetMapVertex(texMaps[ch], face->vert[vi]); v.addTexCoord(texMaps[ch], tv.x, tv.y, tv.z); } int actualVertexIndex = vertexList.add(v); of << " v" << vi + 1 << "=\"" << actualVertexIndex << "\""; } of << " />" << std::endl; } of << "\t\t\t</faces>" << std::endl; // *************** End Export Face List *************** // *************** Export Geometry *************** of << "\t\t\t<geometry vertexcount=\"" << vertexList.size() << "\">" << std::endl; // *************** Export Vertex Buffer *************** bool exportNormals = true; of << std::boolalpha; of << "\t\t\t\t<vertexbuffer positions=\"true\" normals=\"" << exportNormals << "\" colours_diffuse=\"" << m_config.getExportVertexColours() << "\" texture_coords=\"" << texMaps.Count() << "\""; for (int i=0; i<texMaps.Count(); i++) of << " texture_coords_dimensions_" << i << "=\"2\""; of << ">" << std::endl; int numVerts = vertexList.size(); for (int i=0; i < numVerts; i++) { const Vertex& v = vertexList.front(); of << "\t\t\t\t\t<vertex>" << std::endl; of << std::showpoint; const Ogre::Vector3& p = v.getPosition(); float x = p.x; float y = p.y; float z = p.z; of << "\t\t\t\t\t\t<position x=\"" << x << "\" y=\"" << y << "\" z=\"" << z << "\" />" << std::endl; if (m_config.getExportVertexColours()) { float r = v.getColour().r; float g = v.getColour().g; float b = v.getColour().b; of << "\t\t\t\t\t\t<colour_diffuse value=\"\t" << r << "\t" << g << "\t" << b << "\" />" << std::endl; } if (exportNormals) { const Ogre::Vector3& n = v.getNormal(); float x = n.x; float y = n.y; float z = n.z; of << "\t\t\t\t\t\t<normal x=\"" << x << "\" y=\"" << y << "\" z=\"" << z << "\" />" << std::endl; } // output the tex coords for each map used for (int ti=0; ti<texMaps.Count(); ti++) { int texMap = texMaps[ti]; const Ogre::Vector3& uvw = v.getUVW(texMap); switch (m_config.getTexCoord2D()) { case OgreMax::UV: of << "\t\t\t\t\t\t<texcoord u=\"" << uvw.x << "\" v=\"" << (1.0 - uvw.y) << "\" />" << std::endl; break; case OgreMax::VW: of << "\t\t\t\t\t\t<texcoord v=\"" << uvw.y << "\" w=\"" << (1.0 - uvw.z) << "\" />" << std::endl; break; case OgreMax::WU: of << "\t\t\t\t\t\t<texcoord w=\"" << uvw.z << "\" u=\"" << (1.0 - uvw.x) << "\" />" << std::endl; break; } } of << std::noshowpoint; of << "\t\t\t\t\t</vertex>" << std::endl; vertexList.pop(); } of << "\t\t\t\t</vertexbuffer>" << std::endl; // *************** End Export Vertex Buffer *************** of << "\t\t\t</geometry>" << std::endl; // *************** End Export Geometry *********** of << "\t\t</submesh>" << std::endl; // this skin extraction code based on an article found here: // http://www.cfxweb.net/modules.php?name=News&file=article&sid=1029 /* Object *oRef = node->GetObjectRef(); if (oRef->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject *dObj = (IDerivedObject *)oRef; Modifier *oMod = dObj->GetModifier(0); if (oMod->ClassID() == SKIN_CLASSID) { // flag the export of a skeleton link element m_createSkeletonLink = true; // stream the boneassignments element streamBoneAssignments(of, oMod, node); } } of << "\t\t</submesh>" << std::endl; if (obj != tri) delete tri; */ // node->ReleaseIGameObject(); return true; }