⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lwo2mesh.cpp

📁 使用stl技术,(还没看,是听说的)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		for (unsigned int j = 0; j < point->polygons.size(); j++)
		{
			lwPolygon *polygon = point->polygons[j];
			if (polygon->type == polygontype)
				if (surfaceIndex == -1 || surfaceIndex == polygon->surfidx)
				{
					destpoints.push_back(point);
					break;
				}
		}
	}
}

void Lwo2MeshWriter::copyPolygons(int surfaceIndex, unsigned long polygontype, vpolygons &sourcepolygons, vpolygons &destpolygons)
{
	for (unsigned int i = 0; i < sourcepolygons.size(); i++)
	{
		lwPolygon *polygon = sourcepolygons[i];
		if (polygon->type == polygontype)
			if (surfaceIndex == -1 || surfaceIndex == polygon->surfidx)
				destpolygons.push_back(polygon);
	}
}

void Lwo2MeshWriter::copyDataToVertexData(vpoints &points,
										vpolygons &polygons,
										vvmaps &vmaps,
										IndexData *indexData,
										VertexData *vertexData,
										unsigned short vertexDataOffset)
{
	lwVMap *vmap = 0;
	unsigned int ni;
	
	HardwareVertexBufferSharedPtr pbuf = vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);
	HardwareVertexBufferSharedPtr nbuf = vertexData->vertexBufferBinding->getBuffer(NORMAL_BINDING);
	HardwareVertexBufferSharedPtr tbuf = vertexData->vertexBufferBinding->getBuffer(TEXCOORD_BINDING);
	HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;

	Real* pPos = static_cast<Real*>(pbuf->lock(HardwareBuffer::HBL_DISCARD));
	Real* pNor = static_cast<Real*>(nbuf->lock(HardwareBuffer::HBL_DISCARD));
	Real* pTex = static_cast<Real*>(tbuf->lock(HardwareBuffer::HBL_DISCARD));
	unsigned short *pIdx = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_DISCARD));

	for (unsigned int p = 0; p < polygons.size(); p++)
	{
		lwPolygon *polygon = polygons[p];
		
		if (polygon->vertices.size() != 3) continue; // only copy triangles;

		for (unsigned int v = 0; v < polygon->vertices.size(); v++)
		{
			lwVertex *vertex = polygon->vertices[v];
			lwPoint *point = vertex->point;
			unsigned short i = getPointIndex(point, points);

			pIdx[p*3 + v] = vertexDataOffset + i;
			
			ni = (vertexDataOffset + i) * 3;
			
			pPos[ni] = vertex->point->x;
			pPos[ni + 1] = vertex->point->y;
			pPos[ni + 2] = vertex->point->z;
			
			pNor[ni] = vertex->normal.x;
			pNor[ni + 1] = vertex->normal.y;
			pNor[ni + 2] = vertex->normal.z;
			
			bool found = false;
			
			ni = (vertexDataOffset + i) * 2;
			
			for (unsigned int v = 0; v < point->vmaps.size(); v++)
			{
				for (unsigned int vr = 0; vr < vmaps.size(); vr++)
				{
					vmap = vmaps[vr];
					if (point->vmaps[v].vmap == vmap)
					{
						int n = point->vmaps[v].index;
						
						pTex[ni] = vmap->val[n][0];
						pTex[ni + 1] = 1.0f - vmap->val[n][1];
						found = true;
						break;
					}
				}
				if (found) break;
			}
		}
	}
    pbuf->unlock();
    nbuf->unlock();
    tbuf->unlock();
	ibuf->unlock();
}

void Lwo2MeshWriter::prepLwObject(void)
{
	unsigned int l, p;
	
	for (l = 0; l < object->layers.size(); l++)
	{
		lwLayer *layer = object->layers[l];
		
#ifdef _DEBUG
		cout << "Triangulating layer " << l << ", Polygons before: " << layer->polygons.size();
#endif
		layer->triangulatePolygons();
#ifdef _DEBUG
		cout << ", Polygons after: " << layer->polygons.size() << endl;
#endif
		
		// Mirror x-coord for Ogre;
		for (p = 0; p < layer->points.size(); p++)
		{
			layer->points[p]->x *= -1.0f;
			layer->points[p]->polygons.clear();
		}
		// Unscrew the bounding box
		float x = layer->bboxmin.x * -1.0f;
		layer->bboxmin.x = layer->bboxmax.x * -1.0f;
		layer->bboxmax.x = x;
		
		for ( p = 0; p < layer->polygons.size(); p++ )
		{
			lwPolygon *polygon = layer->polygons[ p ];
			for (unsigned int j = 0; j < polygon->vertices.size(); j++ )
				polygon->vertices[ j ]->point->polygons.push_back(polygon);
		}	
		
		for (p = 0; p < layer->polygons.size(); p++)
			layer->polygons[p]->flip();
		
		layer->calculatePolygonNormals();
		layer->calculateVertexNormals();
	}
}

inline int Lwo2MeshWriter::getPointIndex(lwPoint *point, vpoints &points)
{
	for (unsigned int i = 0; i < points.size(); ++i)
		if (points[i] == point) return i;
		
	return -1;
}

inline String Lwo2MeshWriter::makeLayerFileName(char* dest, unsigned int l, char *layername)
{
	char
		drive[ _MAX_DRIVE ],
		dir[ _MAX_DIR ],
		node[ _MAX_FNAME ],
		ext[ _MAX_EXT ],
		buf[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 5 ];

	String LayerFileName;
	String TempName;

	_splitpath( dest, drive, dir, node, ext );

	TempName = String( node );
   
	if (layername) {
		TempName += ".";
		TempName += layername;
	} else {
		TempName += ".layer" + StringConverter::toString(l);
	}

	_makepath( buf, drive, dir, TempName.c_str(), ext );
	LayerFileName = String( buf );

	return LayerFileName;
}

inline String Lwo2MeshWriter::makeMaterialFileName(char* dest)
{
	char
		drive[ _MAX_DRIVE ],
		dir[ _MAX_DIR ],
		node[ _MAX_FNAME ],
		ext[ _MAX_EXT ],
		buf[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 5 ];

	String MaterialFileName;

	_splitpath( dest, drive, dir, node, ext );
	_makepath( buf, drive, dir, node, ".material" );
 
	const char *test = MaterialFileName.c_str();
	MaterialFileName = String( buf );

	return MaterialFileName;
}

inline void Lwo2MeshWriter::getTextureVMaps(vtextures &textures, vvmaps &svmaps, vvmaps &dvmaps)
{
	for (unsigned int i = 0; i < textures.size(); i++)
	{
		lwTexture *texture = textures[i];
		
		if (texture->type == ID_IMAP && texture->param.imap)
		{
			char *mapname = texture->param.imap->vmap_name;
			if (mapname)
				for (unsigned int v = 0; v < svmaps.size(); v++)
				{
					lwVMap *vmap = svmaps[v];
					if (strcmp(mapname, vmap->name) == 0) dvmaps.push_back(vmap);
				}
		}
	}
	return;
}

bool Lwo2MeshWriter::writeLwo2Mesh(lwObject *nobject, char *ndest)
{
	object = nobject;
	dest = ndest;
	
	if (!object) return false;
	if (!object->layers.size()) return false;
	
	LogManager::getSingleton().createLog("Lwo2MeshWriter.log");
	
	prepLwObject();
	
	vpoints points;
	vpolygons polygons;
	vvmaps vmaps;
	
	MeshSerializer meshserializer;

	if (flags[ExportMaterials])
	{
		doExportMaterials();
		materialSerializer->exportQueued(makeMaterialFileName(dest));
	}

	unsigned int ml = object->layers.size();

	bool SeparateLayers = flags[UseSeparateLayers] && ml > 1;

	if (!SeparateLayers) ogreMesh = new Mesh(ndest);

	Ogre::Vector3 boundingBoxMin(FLT_MAX, FLT_MAX, FLT_MAX);
	Ogre::Vector3 boundingBoxMax(FLT_MIN, FLT_MIN, FLT_MIN);


	for( unsigned int ol = 0; ol < ml; ++ol )
	{
		if (!object->layers[ol]->polygons.size())
			continue;

		Ogre::Vector3 currentMin(object->layers[ol]->bboxmin.x,
								 object->layers[ol]->bboxmin.y,
								 object->layers[ol]->bboxmin.z);
		Ogre::Vector3 currentMax(object->layers[ol]->bboxmax.x,
								 object->layers[ol]->bboxmax.y,
								 object->layers[ol]->bboxmax.z);

		if (SeparateLayers)
		{	
			ogreMesh = new Mesh(ndest);
			ogreMesh->_setBounds(Ogre::AxisAlignedBox(currentMin, currentMax));
			ogreMesh->_setBoundingSphereRadius(Ogre::Math::Sqrt(std::max(currentMin.squaredLength(), currentMax.squaredLength())));
		}
		else
		{
			boundingBoxMin.makeFloor(currentMin);
			boundingBoxMax.makeCeil(currentMax);
		}
		
		for (unsigned int s = 0; s < object->surfaces.size(); s++)
		{
			lwSurface *surface = object->surfaces[s];
			
			points.clear();
			polygons.clear();
			vmaps.clear();
			
			unsigned int l = ol;

			for( unsigned int il = 0; il < ml; ++il )
			{
				if (!SeparateLayers) l = il;

				copyPoints(s, ID_FACE, object->layers[l]->points, points);
				copyPolygons(s, ID_FACE, object->layers[l]->polygons, polygons);
				getTextureVMaps(surface->color.textures, object->layers[l]->vmaps, vmaps);

				if (SeparateLayers) break;
			}

			if (!polygons.size()) continue; 			
			
			SubMesh *ogreSubMesh = ogreMesh->createSubMesh();
			ogreSubMesh->useSharedVertices = flags[UseSharedVertexData] && points.size() < POINTLIMIT;

			ogreSubMesh->indexData->indexCount = polygons.size() * 3;
			ogreSubMesh->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, ogreSubMesh->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
			ogreSubMesh->setMaterialName(surface->name);
			

			if (ogreSubMesh->useSharedVertices)
			{
				unsigned short vertexDataOffset = 0;
				if (ogreMesh->sharedVertexData) vertexDataOffset = ogreMesh->sharedVertexData->vertexCount;
				ogreMesh->sharedVertexData = setupVertexData(points.size(), ogreMesh->sharedVertexData);
				copyDataToVertexData(points, polygons, vmaps, ogreSubMesh->indexData, ogreMesh->sharedVertexData, vertexDataOffset);
			}
			else
			{
				ogreSubMesh->vertexData = setupVertexData(points.size());
				copyDataToVertexData(points, polygons, vmaps, ogreSubMesh->indexData, ogreSubMesh->vertexData);
			}
		}

		if (!SeparateLayers)
		{	
			ogreMesh->_setBounds(Ogre::AxisAlignedBox(boundingBoxMin, boundingBoxMax));
			ogreMesh->_setBoundingSphereRadius(Ogre::Math::Sqrt(std::max(boundingBoxMin.squaredLength(), boundingBoxMax.squaredLength())));
		}
		
		String fname = SeparateLayers ? makeLayerFileName(dest, ol, object->layers[ol]->name) : dest;

		Skeleton *skeleton = 0;

		if (flags[ExportSkeleton])
			if (SeparateLayers)
				skeleton = doExportSkeleton(fname, ol);
			else
				if (!ol) skeleton = doExportSkeleton(fname, -1);

		if (flags[GenerateLOD])
		{
			ProgressiveMesh::VertexReductionQuota quota;

			if (flags[UseFixedMethod])
				quota = ProgressiveMesh::VRQ_CONSTANT;
			else
				quota = ProgressiveMesh::VRQ_PROPORTIONAL;
					
			ogreMesh->generateLodLevels(distanceList, quota, reduction);
		}
		
		try
		{
			meshserializer.exportMesh(ogreMesh, fname);
		}
		catch (...)
		{
			cout << "Could not export to file: " << fname << endl;
		}

		ogreMesh->unload();

		delete ogreMesh;
		if (flags[ExportSkeleton] && skeleton) delete skeleton;

		if (!SeparateLayers) break;
	}

	return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -