Skip to main content
gamedev.net
🔒 Locked

MD2 problems ... again

Started by Endar Feb 22, 2007 at 4:28 PM 5 replies 900+ views
Original Post
Endar
Endar
Some of you may remember that I had problems in loading and render the md2 format a while ago. Well, I'm having problems again because I'm re-writing my engine (in DX). I'm not going to be using md2 models for anything serious, but just as a quick demo (among others) to show in job interviews. Anyway, md2 loading works on the old version of my engine (in OpenGL), so I've got that to compare with, but let's get to the problem. The texturing seems completely stuffed. It looks like a problem I had before, when the winding of the vertices was in the direction that was set for backfaces, so I would see the back of the model instead of the front, and vice versa. Except that now, it doesn't matter if the backface culling is clockwise, or counter, it's still stuffed, although it seems a little less stuffed when backface culling is set as counter. If I render without textures, the geometry seems fine, and the animation works perfectly. I have checked the texture coordinates against the coordinates from my old version and they match, so that doesn't seem to be the problem. Take a look in a quick 11 second movie. I mean, part of it looks like a problem with backface culling, some of it looks fine, but with the wrong texture overlaid. I'm not really sure what's going on.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Endar
Endar
I haven't as yet made any progress on this.

bump
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
_goat
_goat
I swear that the site isn't working well. I've had problems with textures on MD2 too, but I can't tell if they're the same as yours. My texture just seemed a little "off" in some areas. Most of it seemed fine. It was a frustrating error, too.
Evil Steve
Evil Steve
I can't view that site, it times out for me. I don't know if this is any use, but here's a huge chunk of code from my D3D MD2 loading code. The setting up of vertices and texture coords should be of some help, hopefully:
bool SOMD2Mesh::LoadModelResource(){	// Load the mesh file here	CBinaryResource::SP pRes = (CBinaryResource*)(CResource*)CResourceManager::Get().GetResource(		m_strModelResource, CResource::TYPE_Binary);	if(!pRes)	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Failed to load file \"%s\"\n", m_strModelResource.c_str());		return false;	}	// Validate length, ID and version	if(pRes->GetLen() < sizeof(MD2FileHeader))	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid length (%d bytes, expected at least %d)\n",			pRes->GetLen(), sizeof(MD2FileHeader));		return false;	}	const MD2FileHeader* pHeader = (const MD2FileHeader*)pRes->GetData();	if(pHeader->ident != s_nHeaderID)	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid header (0x%08x, expected 0x%08x)\n",			pHeader->ident, s_nHeaderID);		return false;	}	if(pHeader->version != s_nVersion)	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid version (%d, expected %d)\n",			pHeader->version, s_nVersion);		return false;	}	// Validate skin size against texture, if present	if(m_pTexture)	{		if((pHeader->skinwidth != m_pTexture->GetRealWidth()) ||			(pHeader->skinheight != m_pTexture->GetRealHeight()))		{			CLog::DebugFormat("WARNING: SOMesh::LoadModelResource(): Texture size does not match expected "				"skin size (Texture is %dx%d, skin expected to be %dx%d)\n", m_pTexture->GetRealWidth(),				m_pTexture->GetRealHeight(), m_nExpectedSkinWidth, m_nExpectedSkinHeight);		}	}	// Validate various parts	if((size_t)pHeader->offset_skins + sizeof(MD2Skin)*pHeader->num_skins > pRes->GetLen())	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid skin offset/size\n");		return false;	}	if((size_t)pHeader->offset_st + sizeof(MD2TexCoord)*pHeader->num_st > pRes->GetLen())	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid tex coord offset/size\n");		return false;	}	if((size_t)pHeader->offset_tris + sizeof(MD2Triangle)*pHeader->num_tris > pRes->GetLen())	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid triangle offset/size\n");		return false;	}	if((size_t)pHeader->framesize != sizeof(MD2Frame) + sizeof(MD2Vertex)*pHeader->num_vertices - sizeof(MD2Vertex*))	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Mismatched frame size (%d, expected %d)\n",			pHeader->framesize, sizeof(MD2Frame) + sizeof(MD2Vertex)*pHeader->num_vertices - sizeof(MD2Vertex*));		return false;	}	if(pHeader->num_frames == 0)	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Mesh does not contain any frames!\n");		return false;	}	if((size_t)pHeader->offset_frames + pHeader->framesize*pHeader->num_frames > pRes->GetLen())	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid frame offset/size\n");		return false;	}	if((size_t)pHeader->offset_end > pRes->GetLen())	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid end offset\n");		return false;	}	// Read frames	m_vFrames.resize(pHeader->num_frames);	for(unsigned int nFrame=0; nFrame<pHeader->num_frames; ++nFrame)	{		// Get source and dest frames		const MD2Frame* pFrame = (const MD2Frame*)(pRes->GetData()+pHeader->offset_frames + nFrame*pHeader->framesize);		Frame& rFrame = m_vFrames[nFrame];		// Do a robust name copy		char szName[17];		memcpy(szName, pFrame->name, 16);		szName[16] = '\0';		rFrame.strName = szName;		// Fill in vertices		rFrame.vVertices.resize(pHeader->num_tris*3);		MD2Triangle* pTriangle = (MD2Triangle*)(pRes->GetData() + pHeader->offset_tris);		MD2TexCoord* pTexCoords = (MD2TexCoord*)(pRes->GetData() + pHeader->offset_st);		MeshVertex* pOutVert = &rFrame.vVertices[0];		Vector3 vMin(10000.0f, 10000.0f, 10000.0f);		Vector3 vMax(-10000.0f, -10000.0f, -10000.0f);		for(unsigned int nTri=0; nTri<pHeader->num_tris; ++nTri)		{			for(int i=0; i<3; ++i)			{				// Check indices are valid				if(pTriangle->vertex >= pHeader->num_vertices)				{					m_vFrames.clear();					CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid vertex index (%d) for triangle %d. Only %d vertices in model\n",						pTriangle->vertex, nTri, pHeader->num_vertices);					return false;				}				if(pTriangle->st >= pHeader->num_st)				{					m_vFrames.clear();					CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid tex coord index (%d) for triangle %d. Only %d tex coords in model\n",						pTriangle->st, nTri, pHeader->num_st);					return false;				}				const MD2Vertex* pInVert = &pFrame->verts[0] + pTriangle->vertex;				if((size_t)pInVert->normalIndex >= sizeof(g_vNormals)/sizeof(Vector3))				{					m_vFrames.clear();					CLog::DebugFormat("SOMesh::LoadModelResource(): Invalid normal index (%d) for frame %d, vertex %d\n",						nFrame, pTriangle->vertex, (int)pInVert->normalIndex);					return false;				}				MD2TexCoord* pInTexCoord = pTexCoords + pTriangle->st;				// Setup vertex				pOutVert->vPos.x = pFrame->scale.x * (float)pInVert->v[0] + pFrame->translate.x;				pOutVert->vPos.z = pFrame->scale.y * (float)pInVert->v[1] + pFrame->translate.y;				pOutVert->vPos.y = pFrame->scale.z * (float)pInVert->v[2] + pFrame->translate.z;				pOutVert->vNormal = g_vNormals[(size_t)pInVert->normalIndex];				pOutVert->tu = (float)pInTexCoord->s / (float)pHeader->skinwidth;				pOutVert->tv = (float)pInTexCoord->t / (float)pHeader->skinheight;				// Update AABB				if(pOutVert->vPos.x > vMax.x) vMax.x = pOutVert->vPos.x;				else if(pOutVert->vPos.x < vMin.x) vMin.x = pOutVert->vPos.x;				if(pOutVert->vPos.y > vMax.y) vMax.y = pOutVert->vPos.y;				else if(pOutVert->vPos.y < vMin.y) vMin.y = pOutVert->vPos.y;				if(pOutVert->vPos.z > vMax.z) vMax.z = pOutVert->vPos.z;				else if(pOutVert->vPos.z < vMin.z) vMin.z = pOutVert->vPos.z;				// Move onto the next vertex				pInVert++;				pOutVert++;			}			++pTriangle;		}	}	// Extract animations from frame names	for(size_t i=0; i<m_vFrames.size(); ++i)	{		// Trim numbers off this frame name		std::string strName(m_vFrames.strName);		while(!strName.empty() && (strName.end()[-1] >= '0') && (strName.end()[-1] <= '9'))			strName.erase(strName.end()-1);		if(m_vAnimations.empty() || (m_vAnimations.back().strName != strName))		{			// New animation			Animation theAnim;			theAnim.strName = strName;			theAnim.nStartFrame = i;			theAnim.nFrames = 0;			if(!m_vAnimations.empty())				m_vAnimations.back().nFrames = i-m_vAnimations.back().nStartFrame;			m_vAnimations.push_back(theAnim);		}	}	m_vAnimations.back().nFrames = m_vFrames.size()-m_vAnimations.back().nStartFrame;	// Create vertex declaration	if(m_bSpecular)		m_pDecl = CVertexDecl().AppendPosition().AppendNormal().AppendDiffuse().AppendSpecular().AppendTextureCoords().GetDecl();	else		m_pDecl = CVertexDecl().AppendPosition().AppendNormal().AppendDiffuse().AppendTextureCoords().GetDecl();	if(!m_pDecl)	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Failed to create vertex declaration\n");		m_vAnimations.clear();		m_vFrames.clear();		return false;	}	// Create vertex buffer	DWORD dwNumVerts = s_bDrawGroundPlane ? pHeader->num_tris*6 + 4 : pHeader->num_tris*6;	DWORD dwStride = m_bSpecular ? sizeof(InternalSpecularMeshVertex) : sizeof(InternalMeshVertex);	m_pVB = CD3DDevice::Get().CreateDynamicVertexBuffer(dwNumVerts, dwStride, 0);	if(!m_pVB)	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Failed to create vertex buffer\n");		m_vAnimations.clear();		m_vFrames.clear();		m_pDecl->Release();		m_pDecl = NULL;		return false;	}	// Create index buffer	const WORD wNumIndices = (WORD)(s_bDrawGroundPlane ? pHeader->num_tris*3 + 6 : pHeader->num_tris*3);	m_pIB = CD3DDevice::Get().CreateIndexBuffer(wNumIndices);	if(!m_pIB)	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Failed to create index buffer\n");		m_vAnimations.clear();		m_vFrames.clear();		m_pVB->Release();		m_pVB = NULL;		m_pDecl->Release();		m_pDecl = NULL;		return false;	}	// Fill IB	WORD* pIndices = m_pIB->Lock(0, 0);	if(!pIndices)	{		CLog::DebugFormat("SOMesh::LoadModelResource(): Failed to lock index buffer\n");		Destroy();		return false;	}	WORD wIndex = 0;	for(unsigned int i=0; i<pHeader->num_tris; ++i)	{		*pIndices++ = wIndex++;		*pIndices++ = wIndex++;		*pIndices++ = wIndex++;	}	if(s_bDrawGroundPlane)	{		*pIndices++ = wIndex+0;		*pIndices++ = wIndex+2;		*pIndices++ = wIndex+1;		*pIndices++ = wIndex+1;		*pIndices++ = wIndex+2;		*pIndices++ = wIndex+3;	}	m_pIB->Unlock();	// Save info	m_nExpectedSkinWidth = pHeader->skinwidth;	m_nExpectedSkinHeight = pHeader->skinheight;	m_nTriangles = pHeader->num_tris;	m_fTime = 0.0f;	m_nFrame = 0;	m_nNextFrame = (m_vFrames.size() < 2) ? 0 : 1;	m_nAnim = 0;	CLog::DebugFormat("Loaded \"%s\", %d triangles\n", m_strModelResource.c_str(), m_nTriangles);	// Calculate AABB and bounding sphere radius	Vector3 vSphere;	m_vAABBMin = m_vFrames[0].vMin;	m_vAABBMax = m_vFrames[0].vMax;	vSphere.x = max(abs(m_vAABBMin.x), abs(m_vAABBMax.x));	vSphere.y = max(abs(m_vAABBMin.y), abs(m_vAABBMax.y));	vSphere.z = max(abs(m_vAABBMin.z), abs(m_vAABBMax.z));	m_fSphereRadius = vSphere.Length();	// Done	return true;}
Black Knight
Black Knight
Hmm Im not sure about this but isn't the texture coordinates in OGL and D3D different?
Like one having 1,1 on upper right corner and the other having 1,1 on lower right corner.
Evil Steve
Evil Steve
Quote:
Original post by Black Knight
Hmm Im not sure about this but isn't the texture coordinates in OGL and D3D different?
Like one having 1,1 on upper right corner and the other having 1,1 on lower right corner.
I don't know about OGL, but D3D texture coords range from (0, 0) [top left] to (1, 1) [bottom right].

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.