// // MQO // 面倒なので四角ポリゴンはないものと仮定 // void build_from_mqo( mqo_reader::document_type& doc, float scale, DWORD color, TextureCache& tc ) { clear(); // マテリアル for( mqo_reader::materials_type::const_iterator i = doc.materials.begin() ; i != doc.materials.end() ; ++i ) { SubModel m; m.vb = NULL; m.ib = NULL; m.texture = NULL; if( (*i).texture != "" ) { m.texture = tc.get_texture( (*i).texture ); } submodels_.push_back( m ); } { // default material SubModel m; m.vb = NULL; m.ib = NULL; submodels_.push_back( m ); } // 頂点, 面 for( mqo_reader::objdic_type::const_iterator i = doc.objects.begin() ; i != doc.objects.end() ; ++i ) { const mqo_reader::object_type& obj = (*i).second; // dictionary: // ( source vertex index, uv ) => destination vertex index struct VertexKey { int index; D3DXVECTOR2 uv; VertexKey(){} VertexKey( int aindex, const D3DXVECTOR2& auv ) : index( aindex ), uv( auv ) { } bool operator<( const VertexKey& a ) const { if( index < a.index ) { return true; } if( a.index < index ) { return false; } if( uv.x < a.uv.x ) { return true; } if( a.uv.x < uv.x ) { return false; } return uv.y < a.uv.y; } }; std::vector< std::map< VertexKey, int > > used_vertices; used_vertices.resize( submodels_.size() ); // マテリアルごとに使用頂点を分類 for( mqo_reader::faces_type::const_iterator j = obj.faces.begin() ; j != obj.faces.end() ; ++j ) { const mqo_reader::face_type& face = *j; int material_index = face.material_index; if( material_index == -1 ) { material_index = int( submodels_.size() - 1 ); } int i0 = face.vertex_indices[0]; int i1 = face.vertex_indices[1]; int i2 = face.vertex_indices[2]; D3DXVECTOR2 uv0( face.uv[0].u, face.uv[0].v ); D3DXVECTOR2 uv1( face.uv[1].u, face.uv[1].v ); D3DXVECTOR2 uv2( face.uv[2].u, face.uv[2].v ); std::map< VertexKey, int >& c = used_vertices[material_index]; c[ VertexKey( i0, uv0 ) ] = -1 ; c[ VertexKey( i1, uv1 ) ] = -1 ; c[ VertexKey( i2, uv2 ) ] = -1 ; } // マテリアルごとに使われている頂点を追加 size_t n = submodels_.size(); for( size_t i = 0 ; i < n ; i++ ) { SubModel& m = submodels_[i]; std::map< VertexKey, int >& c = used_vertices[i]; int no = int( m.vertex_source.size() ); for( std::map< VertexKey, int >::iterator j = c.begin(); j != c.end() ; ++j ) { const mqo_reader::vertex_type& src = obj.vertices[(*j).first.index]; model_vertex_type dst; dst.position = D3DXVECTOR3( src.x * scale, src.y * scale, src.z * -scale ); dst.normal = D3DXVECTOR3( 0, 0, 0 ); dst.diffuse = color; dst.uv = (*j).first.uv; m.vertex_source.push_back( dst ); (*j).second = no++; } } // マテリアルごとに面を追加 for( mqo_reader::faces_type::const_iterator j = obj.faces.begin() ; j != obj.faces.end() ; ++j ) { const mqo_reader::face_type& face = *j; int material_index = face.material_index; if( material_index == -1 ) { material_index = int( submodels_.size() - 1 ); } int i0 = face.vertex_indices[0]; int i1 = face.vertex_indices[1]; int i2 = face.vertex_indices[2]; D3DXVECTOR2 uv0( face.uv[0].u, face.uv[0].v ); D3DXVECTOR2 uv1( face.uv[1].u, face.uv[1].v ); D3DXVECTOR2 uv2( face.uv[2].u, face.uv[2].v ); std::map< VertexKey, int >& c = used_vertices[material_index]; int k0 = c[VertexKey( i0, uv0 )]; int k1 = c[VertexKey( i1, uv1 )]; int k2 = c[VertexKey( i2, uv2 )]; SubModel& m = submodels_[material_index]; m.index_source.push_back( k0 ); m.index_source.push_back( k1 ); m.index_source.push_back( k2 ); model_vertex_type& v0 = m.vertex_source[ k0 ]; model_vertex_type& v1 = m.vertex_source[ k1 ]; model_vertex_type& v2 = m.vertex_source[ k2 ]; D3DXVECTOR3 normal = cross( v1.position - v0.position, v2.position - v0.position ); v0.normal += normal; v1.normal += normal; v2.normal += normal; } } // 法線後処理 size_t n = submodels_.size(); for( size_t j = 0 ; j < n ; j++ ) { SubModel& m = submodels_[j]; for( std::vector< model_vertex_type >::iterator i = m.vertex_source.begin() ; i != m.vertex_source.end() ; ++i ) { D3DXVec3Normalize( &(*i).normal, &(*i).normal ); } } build_submodels(); }