Пример #1
0
// Calculate T&B
void OGF::CalculateTB()
{
	remove_isolated_verts( data.vertices, data.faces );
		// ************************************* Declare inputs
	Status						( "Declarator..." );
	u32 v_count_reserve			= iFloor( float( data.vertices.size() )*1.33f );
	u32 i_count_reserve			= 3*data.faces.size();


	mender_mapping_out_to_in_vert	.clear( );

	mender_mapping_out_to_in_vert	.reserve( v_count_reserve );
	mender_in_out_verts				.reserve( v_count_reserve );
	mender_in_out_indices			.reserve( i_count_reserve );

	mender_in_out_verts				.clear( );
	mender_in_out_indices			.clear( );
	fill_mender_input( data.vertices, data.faces, mender_in_out_verts, mender_in_out_indices );

	u32			v_was	= data.vertices.size();
	u32			v_become= mender_in_out_verts.size();
	clMsg		("duplication: was[%d] / become[%d] - %2.1f%%",v_was,v_become,100.f*float(v_become-v_was)/float(v_was));

	// ************************************* Perform mungle
	Status			("Calculating basis...");
	
	MeshMender	mender	;
	if (	!mender.Mend		(
		  mender_in_out_verts,
		  mender_in_out_indices,
		  mender_mapping_out_to_in_vert,
		  1,
		  0.5,
		  0.5,
		  0.0f,
		  MeshMender::DONT_CALCULATE_NORMALS,
		  MeshMender::RESPECT_SPLITS,
		  MeshMender::DONT_FIX_CYLINDRICAL
		)
	)
	{
		xrDebug::Fatal	(DEBUG_INFO, "NVMeshMender failed " );
		//xrDebug::Fatal	(DEBUG_INFO,"NVMeshMender failed (%s)",mender.GetLastError().c_str());
	}

	// ************************************* Bind declarators
	// bind

	retrive_data_from_mender_otput( data.vertices, data.faces, mender_in_out_verts, mender_in_out_indices, mender_mapping_out_to_in_vert  );
	remove_isolated_verts( data.vertices, data.faces );

	mender_in_out_verts				.clear( );
	mender_in_out_indices			.clear( );
	mender_mapping_out_to_in_vert	.clear( );
}
Пример #2
0
        //-------------------------------------------------------------------------------------------------------
        bool Exporter::computeTangentSpace()
        {
                uint32_t numFaces = faces_.getSize();

                std::vector<unsigned int> newFaces;
                newFaces.reserve(3 * numFaces);

                vertices_.reserve(numVertices_);
                for(uint32_t i = 0; i < numVertices_; ++i)
                        vertices_.push_back(MeshMender::Vertex());

                for(uint32_t i = 0; i < numFaces; ++i)
                {
                        const RawMesh::Face& face = rawMesh_->faces_[i];
                        const RawMesh::Face& normalFace  = rawMesh_->normalFaces_[i];
                        const RawMesh::Face& textureFace = rawMesh_->textureFaces_[i];

                        for(uint8_t j = 0; j < 3; ++j)
                        {
                                uint32_t vertexIndex = faces_[i].indices[j];

                                newFaces.push_back(vertexIndex);
                                MeshMender::Vertex& vertex = vertices_[vertexIndex];

                                const auto& position = rawMesh_->positions_[face.indices[j]];
                                const auto& normal = rawMesh_->normals_[normalFace.indices[j]];
                                const auto& textureCoordinates =
                                        rawMesh_->textureCoordinates_[textureFace.indices[j]];

                                vertex.pos = position;
                                vertex.normal = normal;
                                vertex.s = textureCoordinates.x;
                                vertex.t = textureCoordinates.y;
                        }
                }

                MeshMender meshMender;
                if(!meshMender.Mend(vertices_, newFaces, newToOldVertexMapping_,
                                    0.0f, 0.0f, 0.0f, 1.0f, MeshMender::DONT_CALCULATE_NORMALS))
                        return false;

                numVertices_ = vertices_.size();
                for(uint32_t i = 0; i < numFaces; ++i)
                {
                        for(uint8_t j = 0; j < 3; ++j)
                                faces_[i].indices[j] = newFaces[3 * i + j];
                }

                return true;
        }
void TriBaseSurface::prepare(TangentSpaceMode tangentSpaceMode)
{
	if (tangentSpaceMode == TangentSpaceMode_MeshMender)
	{
		std::vector<MeshMender::Vertex> vertices;
		
		const uint vertexCount = m_mesh->vertexCount();
		vertices.resize(vertexCount);
		
		for (uint i = 0; i < vertexCount; i++)
		{
			const TriMesh::Vertex & vertex = m_mesh->vertexAt(i);

			vertices[i].pos = vertex.pos;
			vertices[i].normal = vertex.nor;
			vertices[i].s = vertex.tex.x();
			vertices[i].t = vertex.tex.y();
			vertices[i].tangent = Vector3(zero);
			vertices[i].binormal = Vector3(zero);
		}

		std::vector<unsigned int> indices;
		
		const uint faceCount = m_mesh->faceCount();
		indices.resize(3 * faceCount);

		for (uint i = 0; i < faceCount; i++)
		{
			const TriMesh::Face & face = m_mesh->faceAt(i);

			indices[3 * i + 0] = face.v[0];
			indices[3 * i + 1] = face.v[1];
			indices[3 * i + 2] = face.v[2];
		}

		std::vector<unsigned int> xrefs;

		// Default options.
		float minNormalsCreaseCosAngle = 0.0f;
		float minTangentsCreaseCosAngle = 0.0f;
		float minBinormalsCreaseCosAngle = 0.0f;
		float weightNormalsByArea = 1.0f;

		MeshMender::NormalCalcOption computeNormals = MeshMender::CALCULATE_NORMALS;
		MeshMender::ExistingSplitOption respectExistingSplits = MeshMender::DONT_RESPECT_SPLITS;
		MeshMender::CylindricalFixOption fixCylindricalWrapping = MeshMender::DONT_FIX_CYLINDRICAL;

		MeshMender mender;
		mender.Mend(vertices, indices, xrefs,
			minNormalsCreaseCosAngle,
			minTangentsCreaseCosAngle,
			minBinormalsCreaseCosAngle,
			weightNormalsByArea,
			computeNormals,
			respectExistingSplits,
			fixCylindricalWrapping);

		// Create new triMesh.
		const uint newFaceCount = indices.size() / 3;
		const uint newVertexCount = vertices.size();

		TriMesh * triMesh = new TriMesh(newFaceCount, newVertexCount);
		triMesh->faces().resize(newFaceCount);
		triMesh->vertices().resize(newVertexCount);
		m_basisArray.resize(newVertexCount);

		for (uint i = 0; i < newVertexCount; i++)
		{
			TriMesh::Vertex & vertex = triMesh->vertexAt(i);

			vertex.pos = vertices[i].pos;
			vertex.nor = vertices[i].normal;
			vertex.tex = Vector2(vertices[i].s, vertices[i].t);

			m_basisArray[i].normal = vertices[i].normal;
			m_basisArray[i].tangent = vertices[i].tangent;
			m_basisArray[i].bitangent = vertices[i].binormal;
		}

		for (uint i = 0; i < newFaceCount; i++)
		{
			TriMesh::Face & face = triMesh->faceAt(i);

			face.v[0] = indices[3 * i + 0];
			face.v[1] = indices[3 * i + 1];
			face.v[2] = indices[3 * i + 2];
		}
	}
	else if (tangentSpaceMode == TangentSpaceMode_Lengyel)
	{
		if (!MeshNormals::hasNormals(m_mesh.ptr()))
		{
			MeshNormals::computeNormals(m_mesh.ptr(), WeightFaceArea);
		}

		geometry::computeMeshTangents(m_mesh.ptr(), m_basisArray);

		foreach(i, m_basisArray)
		{
			Basis & basis = m_basisArray[i];
		//	basis.orthonormalize();
			UE3_CreateOrthonormalBasis(basis);
		}
	}
Пример #4
0
void C3DMeshModelBuilder::CalculateTangentSpace()
{
	std::vector< MeshMender::Vertex > theVerts;
	std::vector< unsigned int > theIndices;
	std::vector< unsigned int > mappingNewToOld;

	// put indexed triangle polygons into a single index array
	std::vector<IndexedPolygon>& polygon_buffer = m_vecTriangulatedPolygon;

	size_t i, iNumTriangles = polygon_buffer.size();
	theIndices.reserve( iNumTriangles * 3 );
	for( i=0; i<iNumTriangles; i++ )
	{
		IndexedPolygon& triangle = polygon_buffer[i];
		assert( triangle.m_index.size() == 3 );

		theIndices.push_back( triangle.m_index[0] );
		theIndices.push_back( triangle.m_index[1] );
		theIndices.push_back( triangle.m_index[2] );
	}


	// fill up the vectors with your mesh's data
	std::vector<General3DVertex>& vert_buffer = *m_pMesh->GetVertexBuffer().get();
    size_t iNumVertices = vert_buffer.size();
	for( i = 0; i < iNumVertices; ++i )
	{
		MeshMender::Vertex v;
		v.pos = vert_buffer[i].m_vPosition;
		v.s   = vert_buffer[i].m_TextureCoord[0].u;
		v.t   = vert_buffer[i].m_TextureCoord[0].v;

		v.normal = vert_buffer[i].m_vNormal;
		// meshmender will computer normals, tangents, and binormals, no need to fill those in.
		// however, if you do not have meshmender compute the normals, you _must_ pass in valid
		// normals to meshmender
		theVerts.push_back(v);
	}

	MeshMender mender;

	size_t iNumIndices = theIndices.size();

    // pass it in to the mender to do it's stuff
	bool res = mender.Mend(
		         theVerts,
		         theIndices,
				 mappingNewToOld,
				 -1.0f,						// minNormalCreaseCos
				 -1.0f,						// minTangentCreaseCos
				 -1.0f,						// minBinormalCreaseCos
				 0.0f,						// weightNormalsByArea
		         MeshMender::DONT_CALCULATE_NORMALS,
				 MeshMender::RESPECT_SPLITS );

	if( !res )
		LOG_PRINT_WARNING( "MeshMender::Mend() failed." );


	// check indices
	assert( iNumIndices == theIndices.size() );

	// update vertices
	// new vertices may have been created and added to 'theVerts' by mesh mender
	size_t iNumUpdatedVertices = theVerts.size();

	vector<General3DVertex> vecNewVertexBuffer;	// temporary vertex buffer to hold new vertices
	vecNewVertexBuffer.resize( iNumUpdatedVertices );

	for( i=0; i<iNumUpdatedVertices; ++i )
	{
		vecNewVertexBuffer[i] = vert_buffer[ mappingNewToOld[i] ];

		vecNewVertexBuffer[i].m_vNormal   = theVerts[i].normal;
		vecNewVertexBuffer[i].m_vBinormal = theVerts[i].binormal;
		vecNewVertexBuffer[i].m_vTangent  = theVerts[i].tangent;
	}

	// copy vertices to the original vertex buffer
	vert_buffer.clear();
	vert_buffer.reserve( iNumUpdatedVertices );
	vert_buffer = vecNewVertexBuffer;


	// update indices
	int vertex_index = 0;
	for( i=0; i<iNumTriangles; ++i )
	{
		IndexedPolygon& triangle = polygon_buffer[i];

		triangle.m_index[0] = theIndices[vertex_index++];
		triangle.m_index[1] = theIndices[vertex_index++];
		triangle.m_index[2] = theIndices[vertex_index++];
	}
}
Пример #5
0
int main(int argc, char* argv[])
{
	if (argc < 3)
	{
		puts("Usage: MeshConv meshfile rdffile");
		return 1;
	}

	// Initialize DirectDraw
	pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	if (pD3D == NULL)
	{
		puts("Cannot init D3D");
		return 1;
	}

	MeshMender mender;
	std::vector<MeshMender::Vertex> MendVerts;
	std::vector<unsigned int> MendIndices;
	std::vector<unsigned int> mappingNewToOld;

	HRESULT hr;
	D3DDISPLAYMODE dispMode;
	D3DPRESENT_PARAMETERS presentParams;

	pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode);

	ZeroMemory(&presentParams, sizeof(presentParams));
	presentParams.Windowed = TRUE;
	presentParams.hDeviceWindow = GetConsoleWindow();
	presentParams.SwapEffect = D3DSWAPEFFECT_COPY;
	presentParams.BackBufferWidth = 8;
	presentParams.BackBufferHeight = 8;
	presentParams.BackBufferFormat = dispMode.Format;

	hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &pD3DDevice);
	if (FAILED(hr))
	{
		printf("Cannot init D3D device: %08x\n", hr);
		pD3D->Release();
		return 1;
	}

	printf("Loading mesh %s: ", argv[1]);

	LPD3DXBUFFER pAdjacency, pMaterials, pEffects;
	DWORD n;
	LPD3DXMESH pLoadMesh;
	hr = D3DXLoadMeshFromX(argv[1], D3DXMESH_SYSTEMMEM, pD3DDevice, &pAdjacency, &pMaterials, &pEffects, &n, &pLoadMesh);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	pEffects->Release();
	pMaterials->Release();
	printf("%d faces, %d verts\n", pLoadMesh->GetNumFaces(), pLoadMesh->GetNumVertices());

	LPD3DXMESH pMesh;
	if (pLoadMesh->GetFVF() != MESHFVF)
	{
		hr = pLoadMesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, MESHFVF, pD3DDevice, &pMesh);
		pLoadMesh->Release();
		if (FAILED(hr))
		{
			printf("CloneMesh error: %08x\n", hr);
			goto mesherror;
		}
	}
	else
		pMesh = pLoadMesh;

	printf("Welding verts: ");

	DWORD* pAdj = new DWORD[pAdjacency->GetBufferSize() / 4];

	D3DXWELDEPSILONS Eps;
	memset(&Eps, 0, sizeof(Eps));
	hr = D3DXWeldVertices(pMesh, D3DXWELDEPSILONS_WELDPARTIALMATCHES, &Eps, (DWORD*)pAdjacency->GetBufferPointer(), pAdj, NULL, NULL);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	
	hr = pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, pAdj, (DWORD*)pAdjacency->GetBufferPointer(), NULL, NULL);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	
	pAdjacency->Release();
	delete [] pAdj;

	printf("%d faces, %d verts\n", pMesh->GetNumFaces(), pMesh->GetNumVertices());

	printf("Mending mesh: ");

	DWORD NumVerts = pMesh->GetNumVertices();
	DWORD NumFaces = pMesh->GetNumFaces();

	MESHVERT* MeshVert;
	pMesh->LockVertexBuffer(0, (LPVOID*)&MeshVert);

	//fill up Mend vectors with your mesh's data
	MendVerts.reserve(NumVerts);
	for(DWORD i = 0; i < NumVerts; ++i)
	{
		MeshMender::Vertex v;
		v.pos = MeshVert[i].pos;
		v.s = MeshVert[i].s;
		v.t = MeshVert[i].t;
		v.normal = MeshVert[i].norm;
		MendVerts.push_back(v);
	}
	pMesh->UnlockVertexBuffer();

	WORD* MeshIdx;
	pMesh->LockIndexBuffer(0, (LPVOID*)&MeshIdx);

	MendIndices.reserve(NumFaces * 3);
	for(DWORD i = 0; i < NumFaces * 3; ++i)
	{
		MendIndices.push_back(MeshIdx[i]);
	}
	pMesh->UnlockIndexBuffer();

	pMesh->Release();
	pMesh = 0;

	//pass it in to Mend mender to do it's stuff
	mender.Mend(MendVerts, MendIndices, mappingNewToOld, 0.9f, 0.9f, 0.9f, 1.0f, MeshMender::DONT_CALCULATE_NORMALS, MeshMender::RESPECT_SPLITS);
	
	mappingNewToOld.clear();

	printf("%d faces, %d verts\n", MendIndices.size() / 3, MendVerts.size());

	printf("Saving data: ");

	FILE* fp = fopen("meshdata.bin", "wb");
	n = MendIndices.size() / 3;
	fwrite(&n, 4, 1, fp);
	n = MendVerts.size();
	fwrite(&n, 4, 1, fp);
	fclose(fp);

	// Load existing file
	HANDLE hFile = CreateFile(argv[2], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("ERROR: %08x\n", GetLastError());
		goto mesherror;
	}
	DWORD Size = GetFileSize(hFile, 0);
	char* FileData = (char*)VirtualAlloc(0, 64*1024*1024, MEM_RESERVE, PAGE_NOACCESS);
	VirtualAlloc(FileData, Size, MEM_COMMIT, PAGE_READWRITE);
	ReadFile(hFile, FileData, Size, &n, 0);
	FileData[n] = 0;
	Size = n;

	char *p, *q;
	// Find vertex data
	p = strstr(FileData, "VertexBuffer");
	if (!p)
	{
		printf("ERROR: Invalid output file\n");
		goto mesherror;
	}
	p = strchr(p, '{');
	q = p+1;
	int depth = 1;
	do {
		if (*q == '}')
			--depth;
		else if (*q == '{')
			++depth;
		++q;
	} while (depth > 0);

	// move post-vertex data to temp buffer
	Size = (FileData + Size) - q;
	char* TempData = (char*)VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(TempData, q, Size);

	// write vertex data
	strcpy(p, "{\r\n    VertexFormat {D3DVSDT_FLOAT3 D3DVSDT_NORMPACKED3 D3DVSDT_FLOAT2 D3DVSDT_NORMPACKED3 D3DVSDT_NORMPACKED3}\r\n    VertexData\r\n    {\r\n");
	p += strlen(p);

	for (std::vector<MeshMender::Vertex>::iterator i = MendVerts.begin(); i != MendVerts.end(); ++i)
	{
		VirtualAlloc(p, 500, MEM_COMMIT, PAGE_READWRITE);
		p += sprintf(p, "        %12f %12f %12f  %12f %12f %12f  %12f %12f  %12f %12f %12f  %12f %12f %12f\r\n",
			i->pos.x, i->pos.y, i->pos.z, i->normal.x, i->normal.y, i->normal.z,
			i->s, i->t,
			i->tangent.x, i->tangent.y, i->tangent.z, i->binormal.x, i->binormal.y, i->binormal.z);
	}

	strcpy(p, "    }\r\n}");
	p += strlen(p);

	VirtualAlloc(p, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(p, TempData, Size);
	Size += p - FileData;
	VirtualFree(TempData, 0, MEM_RELEASE);

	// Find index data
	p = strstr(FileData, "IndexBuffer");
	if (!p)
	{
		printf("ERROR: Invalid output file\n");
		goto mesherror;
	}
	p = strchr(p, '{');
	q = p+1;
	depth = 1;
	do {
		if (*q == '}')
			--depth;
		else if (*q == '{')
			++depth;
		++q;
	} while (depth > 0);

	// move post-index data to temp buffer
	Size = (FileData + Size) - q;
	TempData = (char*)VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(TempData, q, Size);

	// write index data
	strcpy(p, "{\r\n    IndexData\r\n    {\r\n        ");
	p += strlen(p);

	n = 0;
	for (std::vector<unsigned>::iterator i = MendIndices.begin(); i != MendIndices.end(); ++i)
	{
		VirtualAlloc(p, 20, MEM_COMMIT, PAGE_READWRITE);
		p += sprintf(p, " %5hu", *i);
		if (n++ == 2)
		{
			p += sprintf(p, "\r\n       ");
			n = 0;
		}
	}

	strcpy(p-3, "}\r\n}");
	p += strlen(p);

	VirtualAlloc(p, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(p, TempData, Size);
	Size += p - FileData;
	VirtualFree(TempData, 0, MEM_RELEASE);

	SetFilePointer(hFile, 0, 0, FILE_BEGIN);
	WriteFile(hFile, FileData, Size, &n, 0);
	SetEndOfFile(hFile);

	CloseHandle(hFile);
	VirtualFree(FileData, 0, MEM_RELEASE);

	printf("Done\n");

	pD3D->Release();
	pD3DDevice->Release();

	return 0;

mesherror:
	pD3D->Release();
	pD3DDevice->Release();
	
	return 1;
}