Ejemplo n.º 1
0
bool CEditableMesh::Convert( INode *node )
{
	// prepares & checks
	BOOL bDeleteObj;
	bool bResult = true;
	TriObject *obj = ExtractTriObject( node, bDeleteObj );

	if( !obj ){
		ELog.Msg(mtError,"%s -> Can't convert to TriObject", node->GetName() );
		return false; }

	if( obj->mesh.getNumFaces() <=0 ){
		ELog.Msg(mtError,"%s -> There are no faces ?", node->GetName() );
		if (bDeleteObj) delete (obj);
		return false; }

	Mtl *pMtlMain = node->GetMtl();
	DWORD cSubMaterials=0;

	if (pMtlMain){
		// There is at least one material. We're in case 1) or 2)
		cSubMaterials = pMtlMain->NumSubMtls();
		if (cSubMaterials < 1){
			// Count the material itself as a submaterial.
			cSubMaterials = 1;
		}
	}

	// build normals
	obj->mesh.buildRenderNormals();

	// vertices
	m_VertCount = obj->mesh.getNumVerts();
	m_Vertices = xr_alloc<Fvector>(m_VertCount);
	for (int v_i=0; v_i<m_VertCount; v_i++){
		Point3* p = obj->mesh.verts+v_i;
		m_Vertices[v_i].set(p->x,p->y,p->z);
	}

	// set smooth group MAX type
	m_Flags.set(flSGMask,TRUE);

	// faces
	m_FaceCount		= obj->mesh.getNumFaces();
	m_Faces			= xr_alloc<st_Face>	(m_FaceCount);
	m_SmoothGroups	= xr_alloc<u32>		(m_FaceCount);

	m_VMRefs.reserve(m_FaceCount*3);
	if (0==obj->mesh.mapFaces(1))
	{
		bResult = false;
		ELog.Msg(mtError,"'%s' hasn't UV mapping!", node->GetName());
	}
	if (bResult)
	{
		CSurface* surf=0;
		for (int f_i=0; f_i<m_FaceCount; ++f_i)
		{
			Face*	vf = obj->mesh.faces+f_i;
			TVFace* tf = obj->mesh.mapFaces(1) + f_i;
			if (!tf)
			{
				bResult = false;
				ELog.Msg(mtError,"'%s' hasn't UV mapping!", node->GetName());
				break;
			}
			m_SmoothGroups[f_i]					= vf->getSmGroup();
			for (int k=0; k<3; ++k)
			{
				m_Faces[f_i].pv[k].pindex = vf->v[k];
				m_VMRefs.push_back(st_VMapPtLst());
				st_VMapPtLst&	vm_lst = m_VMRefs.back();
				vm_lst.count	= 1;
				vm_lst.pts		= xr_alloc<st_VMapPt>(vm_lst.count);
				for (DWORD vm_i=0; vm_i<vm_lst.count; ++vm_i)
				{
					vm_lst.pts[vm_i].vmap_index	= 0;
					vm_lst.pts[vm_i].index 		= tf->t[k];
				}
				m_Faces[f_i].pv[k].vmref	= m_VMRefs.size()-1;
				if (!bResult) break;
			}
			if (pMtlMain)
			{
				int m_id = obj->mesh.getFaceMtlIndex(f_i);
				if (cSubMaterials == 1)
				{
					m_id = 0;
				}else
				{
					// SDK recommends mod'ing the material ID by the valid # of materials, 
					// as sometimes a material number that's too high is returned.
					m_id %= cSubMaterials;
				}
				surf = m_Parent->CreateSurface(pMtlMain,m_id);
				if (!surf) bResult = false;
			}
			if (!bResult) break;
			m_SurfFaces[surf].push_back(f_i);
		}
	}

	// vmaps
	if( bResult ){
		int vm_cnt = obj->mesh.getNumTVerts();
		m_VMaps.resize(1);
		st_VMap*& VM = m_VMaps.back();
		VM = xr_new<st_VMap>("Texture",vmtUV,false);
		for (int tx_i=0; tx_i<vm_cnt; tx_i++){
			UVVert* tv = obj->mesh.tVerts + tx_i;
			VM->appendUV(tv->x,1-tv->y);
		}
	}

	if ((GetVertexCount()<4)||(GetFaceCount()<2))
	{
		ELog.Msg(mtError,"Invalid mesh: '%s'. Faces<2 or Verts<4");
		bResult = false;
	}

	if (bResult ){
		ELog.Msg(mtInformation,"Model '%s' contains: %d points, %d faces",
			node->GetName(), m_VertCount, m_FaceCount);
	}

	if (bResult)
	{
		RecomputeBBox	();
		OptimizeMesh	(false);
		RebuildVMaps	();
		ELog.Msg(mtInformation,"Model '%s' converted: %d points, %d faces",
			node->GetName(), GetVertexCount(), GetFaceCount());
	}

	if (bDeleteObj) delete (obj);
	return bResult;
}
Ejemplo n.º 2
0
bool CEditableMesh::Convert(CExporter* E)
{
	bool bResult		= true;

	m_Name				= E->m_MeshNode->GetName();

	// maps
	// Weight maps 
	m_VMaps.resize(E->m_Bones.size()+1);
	for (DWORD b_i=0; b_i<E->m_Bones.size(); b_i++)
		m_VMaps[b_i]	= xr_new<st_VMap>(E->m_Bones[b_i]->name.c_str(),vmtWeight,false);;
	// UV map
	int VM_UV_idx		= m_VMaps.size()-1;
	st_VMap*& VM_UV		= m_VMaps[VM_UV_idx];
	VM_UV				= xr_new<st_VMap>("texture",vmtUV,false);

	// points
	{
		m_VertCount		= E->m_ExpVertices.size();
		m_Vertices		= xr_alloc<Fvector>(m_VertCount);
		Fvector* p_it	= m_Vertices;

		for (ExpVertIt ev_it=E->m_ExpVertices.begin(); ev_it!=E->m_ExpVertices.end(); ev_it++,p_it++){
			p_it->set		((*ev_it)->P);
			VM_UV->appendUV	((*ev_it)->uv.x,(*ev_it)->uv.y);
		}
	}
	// faces 
	{
		// set smooth group MAX type
		m_Flags.set(flSGMask,TRUE);
		// reserve space for faces and references
		m_FaceCount		= E->m_ExpFaces.size();
		m_Faces			= xr_alloc<st_Face>	(m_FaceCount);
		m_SmoothGroups	= xr_alloc<u32>		(m_FaceCount);
		m_VMRefs.resize	(m_VertCount);

		int f_id=0;
		for (ExpFaceIt ef_it=E->m_ExpFaces.begin(); ef_it!=E->m_ExpFaces.end(); ef_it++,f_id++){
			// FACES
			m_SmoothGroups[f_id]	= (*ef_it)->sm_group;
			st_Face& F				= m_Faces[f_id];
			for (int k=0; k<3; ++k)
			{
				int v_idx			= (*ef_it)->v[k];
				st_FaceVert& vt		= F.pv[k];
				st_VERT* V			= E->m_ExpVertices[v_idx];
				vt.pindex			= v_idx;
				st_VMapPtLst& vm_lst= m_VMRefs[vt.pindex];
				vm_lst.count		= V->data.size()+1;
				vm_lst.pts			= xr_alloc<st_VMapPt>(vm_lst.count);
				vm_lst.pts[0].vmap_index= VM_UV_idx;
				vm_lst.pts[0].index 	= vt.pindex;
				for (VDIt vd_it=V->data.begin(); vd_it!=V->data.end(); vd_it++){
					DWORD idx		= vd_it-V->data.begin()+1;
					st_VMap* vm		= m_VMaps[vd_it->bone];
					vm->appendW		(vd_it->weight);
					vm_lst.pts[idx].vmap_index	= vd_it->bone;
					vm_lst.pts[idx].index 		= vm->size()-1;
				}
				vt.vmref			= vt.pindex;
			}
			CSurface* surf = m_Parent->CreateSurface(E->m_MtlMain,(*ef_it)->m_id);
			if (!surf){
				bResult = FALSE;
				break;
			}
			m_SurfFaces[surf].push_back(f_id);
		}
	}
	if ((GetVertexCount()<4)||(GetFaceCount()<2))
	{
		Log("!Invalid mesh: '%s'. Faces<2 or Verts<4",*Name());
		bResult = false;
	}
	if (bResult)
	{
		RecomputeBBox	();
		OptimizeMesh	(true);//false);
		RebuildVMaps	();
	}
	return bResult;
}
Ejemplo n.º 3
0
	std::shared_ptr<Mesh> MeshUtil::CreateCylinder(const std::string &name, float topR, float bottomR, float height, int segH, int segV)
	{
		if (segH < 2 || segV < 3)
		{
			LOGW << "SegH or SegV tooooo small!";
			return nullptr;
		}

		Mesh::Ptr mesh = Mesh::Create(name);

		// allocate some space.
		mesh->Positions.Data.reserve((segV * segH + 2) * 3);
		mesh->Indices.Data.reserve((segV * segH * 2) * 3);

		float avgRadian = Angle::PI * 2.0f / segV;

		/*if (inclusive)
		{
		topR = topR / std::cos(avgRadian * 0.5f);
		bottomR = bottomR / std::cos(avgRadian * 0.5f);
		}*/

		float currentHeight = height / 2.0f;
		float currentRadius = topR;

		float heightStep = height / (segH - 1);
		float radiusSetp = (topR - bottomR) / (segH - 1);

		std::vector<unsigned int> previousRing;
		previousRing.reserve(segV * 3);

		std::vector<unsigned int> currentRing;
		currentRing.reserve(segV * 3);

		unsigned int index = 0;
		auto AddVertex = [&currentRing, &mesh, &index](float x, float y, float z) -> unsigned int
		{
			mesh->Positions.Data.insert(mesh->Positions.Data.end(), { x, y, z });
			return index++;
		};

		for (int h = 0; h < segH; h++)
		{
			// fill current ring
			for (int v = 0; v < segV; v++)
			{
				float radian = avgRadian * v;
				currentRing.push_back(AddVertex(
					cos(radian) * currentRadius, currentHeight, sin(radian) * currentRadius));
			}

			if (previousRing.size() > 0)
			{
				// has previous ring, we connect them to triangles.
				for (unsigned int i = 0; i < currentRing.size() - 1; i++)
				{
					mesh->Indices.Data.insert(mesh->Indices.Data.end(), {
						previousRing[i], previousRing[i + 1], currentRing[i + 1],
						currentRing[i + 1], currentRing[i], previousRing[i]
					});
				}
				mesh->Indices.Data.insert(mesh->Indices.Data.end(), {
					previousRing.back(), previousRing.front(), currentRing.front(),
					currentRing.front(), currentRing.back(), previousRing.back()
				});
			}
			else
			{
				// don't have previous ring, then we're on top.
				// close this ring.
				unsigned int center = AddVertex(0, currentHeight, 0);
				for (unsigned int i = 0; i < currentRing.size() - 1; i++)
				{
					mesh->Indices.Data.insert(mesh->Indices.Data.end(), { center, currentRing[i + 1], currentRing[i] });
				}
				mesh->Indices.Data.insert(mesh->Indices.Data.end(), { center, currentRing.front(), currentRing.back() });
			}

			previousRing = currentRing;
			currentRing.erase(currentRing.begin(), currentRing.end());
			currentHeight -= heightStep;
			currentRadius -= radiusSetp;
		}

		// close bottom ring
		unsigned int center = AddVertex(0, -height / 2.0f, 0);
		for (unsigned int i = 0; i < previousRing.size() - 1; i++)
		{
			mesh->Indices.Data.insert(mesh->Indices.Data.end(), { center, previousRing[i], previousRing[i + 1] });
		}
		mesh->Indices.Data.insert(mesh->Indices.Data.end(), { center, previousRing.back(), previousRing.front() });

		LOGD << mesh->GetName() << " [vtx: " << mesh->Positions.Data.size() / 3 << " tris: " << mesh->Indices.Data.size() / 3 << "]";

		if (topR == 0 || bottomR == 0)
			OptimizeMesh(mesh);

		mesh->CalculateAABB();

		return mesh;
	}
Ejemplo n.º 4
0
bool CEditableMesh::LoadMesh(IReader& F){
    u32 version=0;

    R_ASSERT(F.r_chunk(EMESH_CHUNK_VERSION,&version));
    if (version!=EMESH_CURRENT_VERSION){
        ELog.DlgMsg( mtError, "CEditableMesh: unsuported file version. Mesh can't load.");
        return false;
    }

    R_ASSERT(F.find_chunk(EMESH_CHUNK_MESHNAME));
	F.r_stringZ		(m_Name);

    R_ASSERT(F.r_chunk(EMESH_CHUNK_BBOX,&m_Box));
    R_ASSERT(F.r_chunk(EMESH_CHUNK_FLAGS,&m_Flags));
    F.r_chunk(EMESH_CHUNK_BOP,&m_Ops);

    R_ASSERT(F.find_chunk(EMESH_CHUNK_VERTS));
	m_VertCount			= F.r_u32();
    if (m_VertCount<3){
        Log				("! CEditableMesh: Vertices<3.");
     	return false;
    }
    m_Vertices			= xr_alloc<Fvector>(m_VertCount);
	F.r					(m_Vertices, m_VertCount*sizeof(Fvector));

    R_ASSERT(F.find_chunk(EMESH_CHUNK_FACES));
    m_FaceCount			= F.r_u32();
    m_Faces				= xr_alloc<st_Face>(m_FaceCount);
    if (m_FaceCount==0){
        Log				("! CEditableMesh: Faces==0.");
     	return false;
    }
	F.r					(m_Faces, m_FaceCount*sizeof(st_Face));

	m_SmoothGroups		= xr_alloc<u32>(m_FaceCount);
    Memory.mem_fill32	(m_SmoothGroups,m_Flags.is(flSGMask)?0:u32(-1),m_FaceCount);
	u32 sg_chunk_size	= F.find_chunk(EMESH_CHUNK_SG);
	if (sg_chunk_size){
		VERIFY			(m_FaceCount*sizeof(u32)==sg_chunk_size);
		F.r				(m_SmoothGroups, m_FaceCount*sizeof(u32));
	}

    R_ASSERT(F.find_chunk(EMESH_CHUNK_VMREFS));
    m_VMRefs.resize		(F.r_u32());
    int sz_vmpt			= sizeof(st_VMapPt);
    for (VMRefsIt r_it=m_VMRefs.begin(); r_it!=m_VMRefs.end(); r_it++){
    	r_it->count		= F.r_u8();          
	    r_it->pts		= xr_alloc<st_VMapPt>(r_it->count);
        F.r				(r_it->pts, sz_vmpt*r_it->count);
    }

    R_ASSERT(F.find_chunk(EMESH_CHUNK_SFACE));
    string128 surf_name;
    u32 sface_cnt		= F.r_u16(); // surface-face count
    for (u32 sp_i=0; sp_i<sface_cnt; sp_i++){
        F.r_stringZ		(surf_name,sizeof(surf_name));
        int surf_id;
        CSurface* surf	= m_Parent->FindSurfaceByName(surf_name, &surf_id); VERIFY(surf);
        IntVec&			face_lst = m_SurfFaces[surf];
        face_lst.resize	(F.r_u32());
        if (face_lst.empty()){
	        Log			("! Empty surface found: %s",surf->_Name());
    	 	return false;
        }
        F.r				(&*face_lst.begin(), face_lst.size()*sizeof(int));
        std::sort		(face_lst.begin(),face_lst.end());
    }

    if(F.find_chunk(EMESH_CHUNK_VMAPS_2)){
		m_VMaps.resize	(F.r_u32());
		for (VMapIt vm_it=m_VMaps.begin(); vm_it!=m_VMaps.end(); vm_it++){
			*vm_it		= new st_VMap();
			F.r_stringZ	((*vm_it)->name);
			(*vm_it)->dim 	= F.r_u8();
			(*vm_it)->polymap=F.r_u8();
			(*vm_it)->type	= F.r_u8();
			(*vm_it)->resize(F.r_u32());
			F.r			((*vm_it)->getVMdata(), (*vm_it)->VMdatasize());
			F.r			((*vm_it)->getVIdata(), (*vm_it)->VIdatasize());
			if ((*vm_it)->polymap)
				F.r		((*vm_it)->getPIdata(), (*vm_it)->PIdatasize());
		}
	}else{
		if(F.find_chunk(EMESH_CHUNK_VMAPS_1)){
			m_VMaps.resize	(F.r_u32());
			for (VMapIt vm_it=m_VMaps.begin(); vm_it!=m_VMaps.end(); vm_it++){
				*vm_it		= new st_VMap();
				F.r_stringZ	((*vm_it)->name);
				(*vm_it)->dim 	= F.r_u8();
				(*vm_it)->type	= F.r_u8();
				(*vm_it)->resize(F.r_u32());
				F.r			((*vm_it)->getVMdata(), (*vm_it)->VMdatasize() );
			}
		}else{
			R_ASSERT(F.find_chunk(EMESH_CHUNK_VMAPS_0));
			m_VMaps.resize	(F.r_u32());
			for (VMapIt vm_it=m_VMaps.begin(); vm_it!=m_VMaps.end(); vm_it++){
				*vm_it		= new st_VMap();
				F.r_stringZ	((*vm_it)->name);
				(*vm_it)->dim 	= 2;
				(*vm_it)->type	= vmtUV;
				(*vm_it)->resize(F.r_u32());
				F.r			((*vm_it)->getVMdata(), (*vm_it)->VMdatasize() );
			}
		}
		// update vmaps
		RebuildVMaps();
	}

#ifdef _EDITOR
    if (!EPrefs->object_flags.is(epoDeffLoadRB)){
        GenerateFNormals	();
        GenerateAdjacency	();
	    GenerateVNormals	(0);
		GenerateRenderBuffers();
        UnloadFNormals		();
        UnloadAdjacency		();
	    UnloadVNormals		();
    }
    if (!EPrefs->object_flags.is(epoDeffLoadCF)) GenerateCFModel();       
#endif
	OptimizeMesh(false);
    RebuildVMaps();

	return true;
}
Ejemplo n.º 5
0
	std::shared_ptr<Mesh> MeshUtil::CreateSphere(const std::string &name, float radius, int segH, int segV)
	{
		if (segH < 2 || segV < 3)
		{
			LOGW << "SegH or SegV tooooo small!";
			return nullptr;
		}

		Mesh::Ptr mesh = Mesh::Create(name);

		float avgRadianH = Angle::PI / (segH - 1);
		float avgRadianV = Angle::PI * 2.0f / segV;

		float currentHeight = radius;
		float currentRadius = 0.0f;

		std::vector<unsigned int> previousRing;
		previousRing.reserve(segV * 3);

		std::vector<unsigned int> currentRing;
		currentRing.reserve(segV * 3);

		/*if (inclusive)
			radius = radius / std::cos(avgRadianH * 0.5f);*/

		unsigned int index = 0;
		auto AddVertex = [&currentRing, &mesh, &index](float x, float y, float z) -> unsigned int
		{
			mesh->Positions.Data.insert(mesh->Positions.Data.end(), { x, y, z });
			return index++;
		};

		for (int h = 0; h < segH; h++)
		{
			currentRadius = std::sin(h * avgRadianH) * radius;
			currentHeight = std::cos(h * avgRadianH) * radius;

			// fill current ring
			for (int v = 0; v < segV; v++)
			{
				float radian = avgRadianV * v;
				currentRing.push_back(AddVertex(
					cos(radian) * currentRadius, currentHeight, sin(radian) * currentRadius));
			}

			if (previousRing.size() > 0)
			{
				// has previous ring, we connect them to triangles.
				for (unsigned int i = 0; i < currentRing.size() - 1; i++)
				{
					mesh->Indices.Data.insert(mesh->Indices.Data.end(), {
						previousRing[i], previousRing[i + 1], currentRing[i + 1],
						currentRing[i + 1], currentRing[i], previousRing[i]
					});
				}
				mesh->Indices.Data.insert(mesh->Indices.Data.end(), {
					previousRing.back(), previousRing.front(), currentRing.front(),
					currentRing.front(), currentRing.back(), previousRing.back()
				});
			}
			else
			{
				// don't have previous ring, then we're on top.
				// close this ring.
				unsigned int center = AddVertex(0, currentHeight, 0);
				for (unsigned int i = 0; i < currentRing.size() - 1; i++)
				{
					mesh->Indices.Data.insert(mesh->Indices.Data.end(), { center, currentRing[i + 1], currentRing[i] });
				}
				mesh->Indices.Data.insert(mesh->Indices.Data.end(), { center, currentRing.front(), currentRing.back() });
			}

			previousRing = currentRing;
			currentRing.erase(currentRing.begin(), currentRing.end());
		}

		// close bottom ring
		unsigned int center = AddVertex(0, -radius, 0);
		for (unsigned int i = 0; i < previousRing.size() - 1; i++)
		{
			mesh->Indices.Data.insert(mesh->Indices.Data.end(), { center, previousRing[i], previousRing[i + 1] });
		}
		mesh->Indices.Data.insert(mesh->Indices.Data.end(), { center, previousRing.back(), previousRing.front() });

		LOGD << mesh->GetName() << " [vtx: " << mesh->Positions.Data.size() / 3 << " tris: " << mesh->Indices.Data.size() / 3 << "]";

		OptimizeMesh(mesh);

		mesh->CalculateAABB();

		return mesh;
	}