Exemplo n.º 1
0
void RebuildMeshTangentSpace(PolygonGroup *group, bool precomputeBinormal/*=true*/)
{
    DVASSERT(group->GetPrimitiveType() == PRIMITIVETYPE_TRIANGLELIST); //only triangle lists for now    
    DVASSERT(group->GetFormat()&EVF_TEXCOORD0);
    DVASSERT(group->GetFormat()&EVF_NORMAL);

    Vector<FaceWork> faces;
    uint32 faceCount = group->GetIndexCount()/3;
    faces.resize(faceCount);
    Vector<VertexWork> verticesOrigin;
    Vector<VertexWork> verticesFull;
    verticesOrigin.resize(group->GetVertexCount());
    verticesFull.resize(group->GetIndexCount());

    for (uint32 i=0, sz = group->GetVertexCount(); i<sz; ++i)
        verticesOrigin[i].refIndex = i;
    //compute tangent for faces
    for (uint32 f=0; f<faceCount; ++f)
    {
        Vector3 pos[3];
        Vector2 texCoord[3];
        for (uint32 i=0; i<3; ++i)
        {
            int32 workIndex = f*3+i;
            int32 originIndex;
            group->GetIndex(workIndex, originIndex);
            faces[f].indexOrigin[i] = originIndex;
            group->GetCoord(originIndex, pos[i]);
            group->GetTexcoord(0, originIndex, texCoord[i]);
            
            verticesOrigin[originIndex].refIndices.push_back(workIndex);
            verticesFull[f*3+i].refIndex = faces[f].indexOrigin[i];
        }                       
        
        float32 x10 = pos[1].x - pos[0].x;
        float32 y10 = pos[1].y - pos[0].y;
        float32 z10 = pos[1].z - pos[0].z;
        float32 u10 = texCoord[1].x-texCoord[0].x;
        float32 v10 = texCoord[1].y-texCoord[0].y;
        
        
        float32 x20 = pos[2].x - pos[0].x;
        float32 y20 = pos[2].y - pos[0].y;
        float32 z20 = pos[2].z - pos[0].z;
        float32 u20 = texCoord[2].x-texCoord[0].x;
        float32 v20 = texCoord[2].y-texCoord[0].y;

        float32 d = u10 * v20 - u20 * v10;

        if(d == 0.0f)
        {
            d = 1.0f;	// this may happen in case of degenerated triangle
        }
        d = 1.0f / d;


        Vector3 tangent = Vector3((v20 * x10 - v10 * x20) * d, (v20 * y10 - v10 * y20) * d, (v20 * z10 - v10 * z20) * d);
        Vector3 binormal = Vector3((x20 * u10 - x10 * u20) * d, (y20 * u10 - y10 * u20) * d, (z20 * u10 - z10 * u20) * d);

         //should we normalize it here or only final result?        
        tangent.Normalize();
        binormal.Normalize();
        
        faces[f].tangent = tangent;
        faces[f].binormal = binormal;
        for (int32 i=0; i<3; ++i)
        {
            verticesFull[f*3+i].tangent = tangent;            
            verticesFull[f*3+i].binormal = binormal;
        }
    }

    /*smooth tangent space preventing mirrored uv's smooth*/
    for (uint32 v = 0, sz = verticesFull.size(); v<sz; ++v)
    {
        int32 faceId = v/3;
        VertexWork& originVert = verticesOrigin[verticesFull[v].refIndex];      
        verticesFull[v].tbRatio = 1;
        for (int32 iRef=0, refSz = originVert.refIndices.size(); iRef<refSz; ++iRef)
        {
            int32 refFaceId = originVert.refIndices[iRef]/3;
            if (refFaceId == faceId) continue;
            
            //check if uv's mirrored;            
            
            //here we use handness to find mirrored UV's - still not sure if it is better then using dot product (upd: experiments show it is really better)
            Vector3 n1 = CrossProduct(verticesFull[v].tangent, verticesFull[v].binormal);
            Vector3 n2 = CrossProduct(faces[refFaceId].tangent, faces[refFaceId].binormal);                        
            
            if (DotProduct(n1, n2)>0.0f)
            {
                verticesFull[v].tangent+=faces[refFaceId].tangent;
                verticesFull[v].binormal+=faces[refFaceId].binormal;
                verticesFull[v].tbRatio++;
            }
            
        }

        //as we use normalized tangent space - we renormalize vertex TB instead of rescaling it - think later if it is ok
        verticesFull[v].tangent.Normalize();
        verticesFull[v].binormal.Normalize();                
        
        /*float32 invScale = 1.0f/(float32)vertices_full[v].tbRatio;
        vertices_full[v].tangent*=invScale;
        vertices_full[v].binormal*=invScale;*/
        
    }


    const float32 EPS = 0.00001f; //should be the same value as in exporter
    Vector<int32> groups;
    //unlock vertices that have different tangent/binormal but same ref
    for (uint32 i=0, sz=verticesOrigin.size(); i<sz; ++i)
    {        
        DVASSERT(verticesOrigin[i].refIndices.size()); //vertex with no reference triangles found?

        verticesOrigin[i].tangent = verticesFull[verticesOrigin[i].refIndices[0]].tangent;
        verticesOrigin[i].binormal = verticesFull[verticesOrigin[i].refIndices[0]].binormal;

        if (verticesOrigin[i].refIndices.size()<=1) //1 and less references do not need unlock test
            continue;
        groups.clear();
        groups.push_back(0);
        verticesFull[verticesOrigin[i].refIndices[0]].resultGroup = 0;
        //if has different refs, check different groups;
        for (int32 refId=1, refSz = verticesOrigin[i].refIndices.size(); refId<refSz; ++refId)
        {
            VertexWork& vertexRef = verticesFull[verticesOrigin[i].refIndices[refId]];
            bool groupFound = false;
            for (int32 groupId = 0, groupSz = groups.size(); groupId<groupSz; ++groupId)
            {
                const VertexWork& groupRef = verticesFull[verticesOrigin[i].refIndices[groups[groupId]]];                
                bool groupEqual = FLOAT_EQUAL_EPS(vertexRef.tangent.x, groupRef.tangent.x, EPS) && FLOAT_EQUAL_EPS(vertexRef.tangent.y, groupRef.tangent.y, EPS) && FLOAT_EQUAL_EPS(vertexRef.tangent.z, groupRef.tangent.z, EPS);
                if (precomputeBinormal)
                    groupEqual &= FLOAT_EQUAL_EPS(vertexRef.binormal.x, groupRef.binormal.x, EPS) && FLOAT_EQUAL_EPS(vertexRef.binormal.y, groupRef.binormal.y, EPS) && FLOAT_EQUAL_EPS(vertexRef.binormal.z, groupRef.binormal.z, EPS);

                if (groupEqual)
                {                    
                    vertexRef.resultGroup = groupId;
                    groupFound = true;
                    break;
                }                
            }
            if (!groupFound) //start new group
            {
                vertexRef.resultGroup = groups.size();
                groups.push_back(refId);
            }
        }

        if (groups.size()>1) //different groups found - unlock vertices and update refs
        {            
            groups[0] = i;
            for (int32 groupId = 1, groupSz = groups.size(); groupId<groupSz; ++groupId)
            {
                verticesOrigin.push_back(verticesOrigin[i]);
                groups[groupId] = verticesOrigin.size()-1;
                verticesOrigin[groups[groupId]].refIndex = i;
            }
            for (int32 refId=1, refSz = verticesOrigin[i].refIndices.size(); refId<refSz; ++refId)
            {
                VertexWork& vertexRef = verticesFull[verticesOrigin[i].refIndices[refId]];
                vertexRef.refIndex = groups[vertexRef.resultGroup];
            }
        }
    }
    
    //copy original polygon group data and fill new tangent/binormal values
    ScopedPtr<PolygonGroup> tmpGroup(new PolygonGroup());        
    tmpGroup->AllocateData(group->GetFormat(), group->GetVertexCount(), group->GetIndexCount());

    Memcpy(tmpGroup->meshData, group->meshData, group->GetVertexCount()*group->vertexStride);
    Memcpy(tmpGroup->indexArray, group->indexArray, group->GetIndexCount()*sizeof(int16));

    int32 vertexFormat = group->GetFormat() | EVF_TANGENT;
    if (precomputeBinormal)
        vertexFormat|=EVF_BINORMAL;
    group->ReleaseData();
    group->AllocateData(vertexFormat, verticesOrigin.size(), verticesFull.size());

    //copy vertices
    for (uint32 i=0, sz = verticesOrigin.size(); i<sz; ++i)
    {
        CopyVertex(tmpGroup, verticesOrigin[i].refIndex, group, i);   
        Vector3 normal;
        group->GetNormal(i, normal);
        
        Vector3 tangent = verticesOrigin[i].tangent;
        tangent -=normal*DotProduct(tangent, normal);        
        tangent.Normalize();
        group->SetTangent(i, tangent);
        if (precomputeBinormal)
        {
            Vector3 binormal = -verticesOrigin[i].binormal;
            binormal -=normal*DotProduct(binormal, normal);            
            binormal.Normalize();
            group->SetBinormal(i, binormal);
        }
    }

    //copy indices
    for (int32 i = 0, sz = verticesFull.size(); i<sz; ++i)
        group->SetIndex(i, verticesFull[i].refIndex);

    group->BuildBuffers();
}
Exemplo n.º 2
0
void Encoder::Encode(DWORD ID, DWORD Class, DWORD CTNumber, DWORD MType)
{
	BOOL bInsertSurfaceNode = FALSE;
	BOOL bInsertTextureNode = FALSE;
	m_pCurrentNode = m_pRootNode;
	
	// COBRA - RED - Missing Last Texture Initialization to INVALID
	DWORD		dwCurrentTexture=-1;
	DWORD		dwCurrentzBias=0;
	NodeType	LastType=ROOT;
	DXFlagsType	LastFlags;

	LastFlags.w=0x00;
	bool		ChangeSurface=false;

	while(m_pCurrentNode != NULL)
	{
		IdleMode();
		NodeType	Type=m_pCurrentNode->Type;
		DXFlagsType	Flags;
		Flags.w=m_pCurrentNode->Flags.w;
	
		// Make all checks here
		ChangeSurface=false;
		if(Type!=LastType || Type==DOF || Type==CLOSEDOF || Type==SLOT ) ChangeSurface = true;
		if(Flags.b.Texture && m_pCurrentNode->Texture!=dwCurrentTexture) ChangeSurface = true;
		if(Flags.b.Texture != LastFlags.b.Texture) ChangeSurface=true;
		if(Flags.b.Alpha != LastFlags.b.Alpha) ChangeSurface=true;
		if(Flags.b.Gouraud != LastFlags.b.Gouraud ) ChangeSurface=true;
		if(Flags.b.Lite != LastFlags.b.Lite ) ChangeSurface=true;
		if((Flags.b.VColor) != (LastFlags.b.VColor)) ChangeSurface=true;
		if(Flags.b.zBias != LastFlags.b.zBias) ChangeSurface=true;
		if(Flags.b.zBias && m_pCurrentNode->dwzBias!=dwCurrentzBias) ChangeSurface=true;
		if(Flags.b.ChromaKey != LastFlags.b.ChromaKey) ChangeSurface=true;

		// if any change
		if(ChangeSurface){
			
			// Patch the segments
			PatchDWORD();

			switch (Type){

				case	DOT:
				case	LINE:
				case	TRIANGLE:	// Check if a Textured new surace and last texture still valid
									if(Flags.b.Texture && m_pCurrentNode->Texture!=dwCurrentTexture){
										// No moer used Texture node
										//WriteTextureNode(m_pCurrentNode);
										dwCurrentTexture=m_pCurrentNode->Texture;
									}
									dwCurrentzBias=m_pCurrentNode->dwzBias;
									// Write the new Surface
									WriteSurfaceNode(m_pCurrentNode, dwCurrentTexture);
									// New ID
									m_dwNodeID++;
									break;

				case	DOF:		// We've to insert a new DOF node
									{DXDof *pDof = (DXDof*)m_pCurrentNode;	WriteDofNode(pDof);}
									// and reset surfaces properties
									Flags.w=0;
									dwCurrentTexture=-1;
									// New ID
									m_dwNodeID++;
									break;

				case	SLOT:		// We've to insert a new SLOT node
									WriteSlotNode((DXSlot*)m_pCurrentNode);
									// New ID
									m_dwNodeID++;
									break;

		
				case CLOSEDOF:		// We've to insert a new END DOF node
									WriteDofEndNode();
									// and reset surfaces properties
									Flags.w=0;
									dwCurrentTexture=-1;
									// New ID
									m_dwNodeID++;
									break;

				default	:			MessageBox(NULL, "Unknown SURFACE TYPE!!", "Encoder", 0);
			}

			ChangeSurface=false;
			LastFlags=Flags;
			LastType=Type;

		}


		switch(Type)
		{
			case DOT:
			{
				DXVertex *pVertex = (DXVertex*)m_pCurrentNode;
				D3DVERTEXEX dxVertex;
				InitializeVertex(&dxVertex);

				CopyVertex(&(pVertex->Vertex), pVertex->VColor, &dxVertex);
				/*memcpy((void*)&dxVertex, (const void*)&pVertex->Vertex, sizeof(pVertex->Vertex));
				memcpy((void*)(&dxVertex + sizeof(pVertex->Vertex)), (const void*)&pVertex->VColor, sizeof(pVertex->VColor));*/

				// Add vertex in NON INDEXED MODE
				Int16 iIndex = AddVertexToPool(&dxVertex, false);
				WriteBuffer((const void*)&iIndex, sizeof(iIndex));
			}
			break;

			case LINE:
			{
				DXLine *pLine = (DXLine*)m_pCurrentNode;

				for(int i=0; i<2; i++)
				{
					D3DVERTEXEX dxVertex;
					InitializeVertex(&dxVertex);

					CopyVertex(&(pLine->Vertex[i]), pLine->VColor[i], &dxVertex);
					/*memcpy((void*)&dxVertex, (const void*)&pLine->Vertex[i], sizeof(pLine->Vertex[i]));
					memcpy((void*)(&dxVertex + sizeof(pLine->Vertex[i])), (const void*)&pLine->VColor[i], sizeof(pLine->VColor[0]));*/

					Int16 iIndex = AddVertexToPool(&dxVertex);
					WriteBuffer((const void*)&iIndex, sizeof(iIndex));
				}
			}
			break;

			case TRIANGLE:
			{
				DXTriangle *pTriangle = (DXTriangle*)m_pCurrentNode;

				for(int i=0; i<3; i++)
				{
					D3DVERTEXEX dxVertex;
					InitializeVertex(&dxVertex);
					
					CopyVertex(&(pTriangle->Vertex[i]), pTriangle->VColor[i], &dxVertex);
					
					/*BYTE *pVertex = (BYTE*)&dxVertex;
					memcpy((void*)&dxVertex, (const void*)&pTriangle->Vertex[i], sizeof(pTriangle->Vertex[i]));
					memcpy((void*)(pVertex + sizeof(pTriangle->Vertex[i])), (const void*)&pTriangle->VColor[i], sizeof(pTriangle->VColor[0]));*/

					Int16 iIndex = AddVertexToPool(&dxVertex);
					WriteBuffer((const void*)&iIndex, sizeof(iIndex));
				}
			}
			break;

		}
		// Update pointers
		//m_pPreviousNode = m_pCurrentNode;
		m_pCurrentNode  = m_pCurrentNode->Next;
		//m_pNextNode     = m_pCurrentNode != NULL ? m_pCurrentNode->Next : NULL;
	}

	//// Set last node total size (Node + Data (total indexes size))
	//DWORD dwTotalNodeSize = (m_dwTotalSurfaceVertexes*sizeof(Int16) + sizeof(DxSurfaceType));
	//memcpy((void*)m_pLastSurfaceNode, (const void*)&dwTotalNodeSize, sizeof(dwTotalNodeSize));
	//// Add last node Vertex Counter to last surface node
	//memcpy(m_pLastSurfaceNode + 12, (const void*)&m_dwTotalSurfaceVertexes, sizeof(m_dwTotalSurfaceVertexes));

	// Patch the segments
	PatchDWORD();

	// Write ENDMODEL node
	DxEndModelType dxEndModelNode;
	dxEndModelNode.h.dwNodeSize = sizeof(DxEndModelType);
	dxEndModelNode.h.Type = DX_MODELEND;
 	WriteBuffer((void*)&dxEndModelNode, sizeof(dxEndModelNode));

	// Write total number of nodes
	((DxDbHeader*)m_pHeader)->dwNodesNr=m_dwTotalNodeCount;

	// Write other header fields
	//DWORD dwVertexesPoolStart = (DWORD)(m_pBuffer + m_dwBufferOffset);
	((DxDbHeader*)m_pHeader)->pVPool=m_dwBufferOffset;
	((DxDbHeader*)m_pHeader)->dwPoolSize=m_dwVertexesPoolSize;
	((DxDbHeader*)m_pHeader)->dwNVertices=m_dwVertexesNumber;

	// Copy vertexes pool after nodes section
	WriteBuffer((const void*)m_pVertexesPool, m_dwVertexesPoolSize);

	((DxDbHeader*)m_pHeader)->Id=ID;
	((DxDbHeader*)m_pHeader)->ModelSize= m_dwBufferOffset;
	((DxDbHeader*)m_pHeader)->VBClass=Class;
	((DxDbHeader*)m_pHeader)->Version=MODEL_VERSION|((MODEL_VERSION^0xffff)<<16);

	// Assign Materials Features
	m_dwBufferOffset=AssignSurfaceFeatures(m_pBuffer, CTNumber, MType);

#ifdef	CRYPTED_MODELS
	TheVbManager.Encrypt((DWORD*)m_pBuffer);
#endif
	// Write file
	//WriteFile();
}
Exemplo n.º 3
0
bool	FX_CSkinRenderer::TransformMesh	(	Fx_CHARACTER_t	*in_char,
											const FX_CMesh	*pMesh,
											const KEYFRAME	*pKeyFrames,
											const int		in_sysVBNum,
											const int		in_skinPartID	)
{
	int		index;
	UINT	subindex;
	int		globalBoneID;
	TEXTUREVERTEX	*sysVB;
	float	numToMultiply;

	 
	sysVB	=	m_vertexBuffer;
	for	(	index	=	0;	\
			index	<	in_sysVBNum;	\
			++index,	++sysVB		)
	{
		sysVB ->vecPos [0]		=	sysVB ->vecPos [1]		=	sysVB ->vecPos [2]		=	0.0f;
		sysVB ->vecNormal [0]	=	sysVB ->vecNormal [1]	=	sysVB ->vecNormal [2]	=	0.0f;
		
		m_pVertexMap	=	&pMesh->m_meshes[ in_char->stat_LODLevel ].meshchunk->vertexMaps[ index ];
		m_pInfluence	=	&pMesh->m_meshes[ in_char->stat_LODLevel ].influences[ m_pVertexMap->iVertexID ];

		if	(	1	==	m_pInfluence->iNumBoneInfluences	)
		{
			m_pBoneInfluence	=	&m_pInfluence->boneInfluences	[0];

				 
			globalBoneID	=	m_pSkelManager->m_iBoneLookUp[ in_char->attr_skelID ][ m_pBoneInfluence->iBoneID ];

			D3DXQuaternionConjugate ( (D3DXQUATERNION *)g_quatConjugate,	(D3DXQUATERNION *)pKeyFrames [globalBoneID].quatCoordinate );

			 
			Fx_Quat3Multiply( g_quatAfterTransform,	g_quatBuffer,	pKeyFrames [globalBoneID].quatCoordinate,	m_pBoneInfluence ->quatPos,	g_quatConjugate );

			sysVB ->vecPos [0]	=	g_quatAfterTransform [0]	+	pKeyFrames [globalBoneID].vecOffset [0];
			sysVB ->vecPos [1]	=	g_quatAfterTransform [1]	+	pKeyFrames [globalBoneID].vecOffset [1];
			sysVB ->vecPos [2]	=	g_quatAfterTransform [2]	+	pKeyFrames [globalBoneID].vecOffset [2];

			 
			Fx_Quat3Multiply( g_quatAfterTransform,	g_quatBuffer,	pKeyFrames [globalBoneID].quatCoordinate,	m_pBoneInfluence ->quatNormal,	g_quatConjugate );

			VectorCopy ( sysVB ->vecNormal,	g_quatAfterTransform );
		}
		else
		{
			for	(	subindex	=	0;	\
					subindex	<	m_pInfluence ->iNumBoneInfluences;	\
					++subindex		)
			{
				m_pBoneInfluence	=	&m_pInfluence ->boneInfluences [subindex];

					 
				globalBoneID	=	m_pSkelManager->m_iBoneLookUp[ in_char->attr_skelID ][ m_pBoneInfluence->iBoneID ];
	
				D3DXQuaternionConjugate	( (D3DXQUATERNION *)g_quatConjugate,	(D3DXQUATERNION *)pKeyFrames [globalBoneID].quatCoordinate );
				 
				Fx_Quat3Multiply( g_quatAfterTransform,	g_quatBuffer,	pKeyFrames [globalBoneID].quatCoordinate,	m_pBoneInfluence ->quatPos,	g_quatConjugate	);
	
				sysVB ->vecPos [0]	+=	m_pBoneInfluence ->fWeight * ( g_quatAfterTransform [0]	+ pKeyFrames [globalBoneID].vecOffset [0] );
				sysVB ->vecPos [1]	+=	m_pBoneInfluence ->fWeight * ( g_quatAfterTransform [1]	+ pKeyFrames [globalBoneID].vecOffset [1] );
				sysVB ->vecPos [2]	+=	m_pBoneInfluence ->fWeight * ( g_quatAfterTransform [2]	+ pKeyFrames [globalBoneID].vecOffset [2] );
	
				 
				Fx_Quat3Multiply( g_quatAfterTransform,	g_quatBuffer,	pKeyFrames [globalBoneID].quatCoordinate,	m_pBoneInfluence ->quatNormal,	g_quatConjugate );
	
				sysVB ->vecNormal [0]	+=	m_pBoneInfluence->fWeight * g_quatAfterTransform [0];
				sysVB ->vecNormal [1]	+=	m_pBoneInfluence->fWeight * g_quatAfterTransform [1];
				sysVB ->vecNormal [2]	+=	m_pBoneInfluence->fWeight * g_quatAfterTransform [2];
			}
			switch	(	m_pInfluence ->iNumBoneInfluences	)
			{
			case	2:
				numToMultiply	=	0.2f;
				break;
			case	3:
				numToMultiply	=	0.333333f;
				break;
			case	4:
				numToMultiply	=	0.25f;
				break;
			case	5:
				numToMultiply	=	0.2f;
				break;
			default:
				ShowError ( "Bone Influence 개수가 6개 이상입니다!",	__FILE__,	__LINE__	);
				exit (0);
			}
			sysVB ->vecNormal [0]	*=	numToMultiply;
			sysVB ->vecNormal [1]	*=	numToMultiply;
			sysVB ->vecNormal [2]	*=	numToMultiply;
		}
		sysVB ->tu	=	m_pVertexMap ->VertexTC [0].tu;		 
		sysVB ->tv	=	1.0f - m_pVertexMap ->VertexTC [0].tv;
	}

	CopyVertex( in_char, m_vertexBuffer, in_sysVBNum, in_skinPartID );

	return	true;
}