khanat-opennel-code/code/nel/src/3d/mesh_mrm_skin_template.cpp
2014-09-10 20:19:49 +02:00

1608 lines
48 KiB
C++

/**
* File not compiled. Included from mesh_mrm_skin.cpp. It is a "old school" template.
*/
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "std3d.h"
// ace: before including this, #define this define to use it
// the goal is to be able to compile every .cpp file with no
// special case (GNU/Linux needs)
#ifdef ADD_MESH_MRM_SKIN_TEMPLATE
// ***************************************************************************
// ***************************************************************************
// "Templates" for VertexSkinning with any input matrix type.
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
static void applyArraySkinNormalT(uint numMatrixes, uint32 *infPtr, CMesh::CSkinWeight *srcSkinPtr,
CVector *srcVertexPtr, CVector *srcNormalPtr, uint normalOff,
uint8 *destVertexPtr, vector<CMatrix3x4> &boneMat3x4, uint vertexSize, uint nInf)
{
/* Prefetch all vertex/normal before, it is to be faster.
*/
#ifdef NL_HAS_SSE2
{
uint nInfTmp= nInf;
uint32 *infTmpPtr= infPtr;
for(;nInfTmp>0;nInfTmp--, infTmpPtr++)
{
uint index= *infTmpPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
_mm_prefetch((const char *)(void *)srcSkin, _MM_HINT_T1);
_mm_prefetch((const char *)(void *)srcVertex, _MM_HINT_T1);
_mm_prefetch((const char *)(void *)srcNormal, _MM_HINT_T1);
}
}
#elif defined(NL_OS_WINDOWS) && !defined(NL_NO_ASM)
{
uint nInfTmp= nInf;
uint32 *infTmpPtr= infPtr;
for(;nInfTmp>0;nInfTmp--, infTmpPtr++)
{
uint index= *infTmpPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
__asm
{
mov eax, srcSkin
mov ebx, srcVertex
mov ecx, srcNormal
mov edx, [eax]
mov edx, [ebx]
mov edx, [ecx]
}
}
}
#endif
// Process vertices.
switch(numMatrixes)
{
//=========
case 0:
// Special case for Vertices influenced by one matrix. Just copy result of mul.
// for all InfluencedVertices only.
for(;nInf>0;nInf--, infPtr++)
{
uint index= *infPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
CVector *dstVertex= (CVector*)(dstVertexVB);
CVector *dstNormal= (CVector*)(dstVertexVB + normalOff);
// Vertex.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, *dstVertex);
// Normal.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcNormal, *dstNormal);
}
break;
//=========
case 1:
// for all InfluencedVertices only.
for(;nInf>0;nInf--, infPtr++)
{
uint index= *infPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
CVector *dstVertex= (CVector*)(dstVertexVB);
CVector *dstNormal= (CVector*)(dstVertexVB + normalOff);
// Vertex.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
// Normal.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcNormal, srcSkin->Weights[0], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcNormal, srcSkin->Weights[1], *dstNormal);
}
break;
//=========
case 2:
// for all InfluencedVertices only.
for(;nInf>0;nInf--, infPtr++)
{
uint index= *infPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
CVector *dstVertex= (CVector*)(dstVertexVB);
CVector *dstNormal= (CVector*)(dstVertexVB + normalOff);
// Vertex.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
// Normal.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcNormal, srcSkin->Weights[0], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcNormal, srcSkin->Weights[1], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddVector( *srcNormal, srcSkin->Weights[2], *dstNormal);
}
break;
//=========
case 3:
// for all InfluencedVertices only.
for(;nInf>0;nInf--, infPtr++)
{
uint index= *infPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
CVector *dstVertex= (CVector*)(dstVertexVB);
CVector *dstNormal= (CVector*)(dstVertexVB + normalOff);
// Vertex.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[3] ].mulAddPoint( *srcVertex, srcSkin->Weights[3], *dstVertex);
// Normal.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcNormal, srcSkin->Weights[0], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcNormal, srcSkin->Weights[1], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddVector( *srcNormal, srcSkin->Weights[2], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[3] ].mulAddVector( *srcNormal, srcSkin->Weights[3], *dstNormal);
}
break;
}
}
// ***************************************************************************
static void applyArraySkinTangentSpaceT(uint numMatrixes, uint32 *infPtr, CMesh::CSkinWeight *srcSkinPtr,
CVector *srcVertexPtr, CVector *srcNormalPtr, CVector *tgSpacePtr, uint normalOff, uint tgSpaceOff,
uint8 *destVertexPtr, vector<CMatrix3x4> &boneMat3x4, uint vertexSize, uint nInf)
{
/* Prefetch all vertex/normal/tgSpace before, it is faster.
*/
#ifdef NL_HAS_SSE2
{
uint nInfTmp= nInf;
uint32 *infTmpPtr= infPtr;
for(;nInfTmp>0;nInfTmp--, infTmpPtr++)
{
uint index= *infTmpPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
CVector *srcTgSpace= tgSpacePtr + index;
_mm_prefetch((const char *)(void *)srcSkin, _MM_HINT_T1);
_mm_prefetch((const char *)(void *)srcVertex, _MM_HINT_T1);
_mm_prefetch((const char *)(void *)srcNormal, _MM_HINT_T1);
_mm_prefetch((const char *)(void *)srcTgSpace, _MM_HINT_T1);
}
}
#elif defined(NL_OS_WINDOWS) && !defined(NL_NO_ASM)
{
uint nInfTmp= nInf;
uint32 *infTmpPtr= infPtr;
for(;nInfTmp>0;nInfTmp--, infTmpPtr++)
{
uint index= *infTmpPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
CVector *srcTgSpace= tgSpacePtr + index;
__asm
{
mov eax, srcSkin
mov ebx, srcVertex
mov ecx, srcNormal
mov esi, srcTgSpace
mov edx, [eax]
mov edx, [ebx]
mov edx, [ecx]
mov edx, [esi]
}
}
}
#endif
// Process vertices.
switch(numMatrixes)
{
//=========
case 0:
// Special case for Vertices influenced by one matrix. Just copy result of mul.
// for all InfluencedVertices only.
for(;nInf>0;nInf--, infPtr++)
{
uint index= *infPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
CVector *srcTgSpace= tgSpacePtr + index;
//
uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
CVector *dstVertex= (CVector*)(dstVertexVB);
CVector *dstNormal= (CVector*)(dstVertexVB + normalOff);
CVector *dstTgSpace= (CVector*)(dstVertexVB + tgSpaceOff);
// Vertex.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, *dstVertex);
// Normal.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcNormal, *dstNormal);
// Tg space
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcTgSpace, *dstTgSpace);
}
break;
//=========
case 1:
// for all InfluencedVertices only.
for(;nInf>0;nInf--, infPtr++)
{
uint index= *infPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
CVector *srcTgSpace= tgSpacePtr + index;
//
uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
CVector *dstVertex= (CVector*)(dstVertexVB);
CVector *dstNormal= (CVector*)(dstVertexVB + normalOff);
CVector *dstTgSpace= (CVector*)(dstVertexVB + tgSpaceOff);
// Vertex.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
// Normal.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcNormal, srcSkin->Weights[0], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcNormal, srcSkin->Weights[1], *dstNormal);
// Tg space
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcTgSpace, srcSkin->Weights[0], *dstTgSpace);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcTgSpace, srcSkin->Weights[1], *dstTgSpace);
}
break;
//=========
case 2:
// for all InfluencedVertices only.
for(;nInf>0;nInf--, infPtr++)
{
uint index= *infPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
CVector *srcTgSpace= tgSpacePtr + index;
//
uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
CVector *dstVertex= (CVector*)(dstVertexVB);
CVector *dstNormal= (CVector*)(dstVertexVB + normalOff);
CVector *dstTgSpace= (CVector*)(dstVertexVB + tgSpaceOff);
// Vertex.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
// Normal.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcNormal, srcSkin->Weights[0], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcNormal, srcSkin->Weights[1], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddVector( *srcNormal, srcSkin->Weights[2], *dstNormal);
// Tg space
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcTgSpace, srcSkin->Weights[0], *dstTgSpace);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcTgSpace, srcSkin->Weights[1], *dstTgSpace);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddVector( *srcTgSpace, srcSkin->Weights[2], *dstTgSpace);
}
break;
//=========
case 3:
// for all InfluencedVertices only.
for(;nInf>0;nInf--, infPtr++)
{
uint index= *infPtr;
CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
CVector *srcVertex= srcVertexPtr + index;
CVector *srcNormal= srcNormalPtr + index;
CVector *srcTgSpace= tgSpacePtr + index;
//
uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
CVector *dstVertex= (CVector*)(dstVertexVB);
CVector *dstNormal= (CVector*)(dstVertexVB + normalOff);
CVector *dstTgSpace= (CVector*)(dstVertexVB + tgSpaceOff);
// Vertex.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
boneMat3x4[ srcSkin->MatrixId[3] ].mulAddPoint( *srcVertex, srcSkin->Weights[3], *dstVertex);
// Normal.
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcNormal, srcSkin->Weights[0], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcNormal, srcSkin->Weights[1], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddVector( *srcNormal, srcSkin->Weights[2], *dstNormal);
boneMat3x4[ srcSkin->MatrixId[3] ].mulAddVector( *srcNormal, srcSkin->Weights[3], *dstNormal);
// Tg space
boneMat3x4[ srcSkin->MatrixId[0] ].mulSetVector( *srcTgSpace, srcSkin->Weights[0], *dstTgSpace);
boneMat3x4[ srcSkin->MatrixId[1] ].mulAddVector( *srcTgSpace, srcSkin->Weights[1], *dstTgSpace);
boneMat3x4[ srcSkin->MatrixId[2] ].mulAddVector( *srcTgSpace, srcSkin->Weights[2], *dstTgSpace);
boneMat3x4[ srcSkin->MatrixId[3] ].mulAddVector( *srcTgSpace, srcSkin->Weights[3], *dstTgSpace);
}
break;
}
}
// ***************************************************************************
// ***************************************************************************
// ApplySkin methods.
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
void CMeshMRMGeom::applySkinWithNormal(CLod &lod, const CSkeletonModel *skeleton)
{
nlassert(_Skinned);
if(_SkinWeights.size()==0)
return;
// get vertexPtr / normalOff.
//===========================
CVertexBufferReadWrite vba;
_VBufferFinal.lock (vba);
uint8 *destVertexPtr= (uint8*)vba.getVertexCoordPointer();
uint flags= _VBufferFinal.getVertexFormat();
sint32 vertexSize= _VBufferFinal.getVertexSize();
// must have XYZ and Normal.
nlassert((flags & CVertexBuffer::PositionFlag)
&& (flags & CVertexBuffer::NormalFlag)
);
// Compute offset of each component of the VB.
sint32 normalOff;
normalOff= _VBufferFinal.getNormalOff();
// compute src array.
CMesh::CSkinWeight *srcSkinPtr;
CVector *srcVertexPtr;
CVector *srcNormalPtr= NULL;
srcSkinPtr= &_SkinWeights[0];
srcVertexPtr= &_OriginalSkinVertices[0];
srcNormalPtr= &(_OriginalSkinNormals[0]);
// Compute useful Matrix for this lod.
//===========================
// Those arrays map the array of bones in skeleton.
static vector<CMatrix3x4> boneMat3x4;
computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);
// apply skinning.
//===========================
// assert, code below is written especially for 4 per vertex.
nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
{
uint nInf= (uint)lod.InfluencedVertices[i].size();
if( nInf==0 )
continue;
uint32 *infPtr= &(lod.InfluencedVertices[i][0]);
// TestYoyo
/*extern uint TESTYOYO_NumStdSkinVertices;
TESTYOYO_NumStdSkinVertices+= nInf;*/
// apply the skin to the vertices
applyArraySkinNormalT(i, infPtr, srcSkinPtr, srcVertexPtr, srcNormalPtr,
normalOff, destVertexPtr,
boneMat3x4, vertexSize, nInf);
}
}
// ***************************************************************************
void CMeshMRMGeom::applySkinWithTangentSpace(CLod &lod, const CSkeletonModel *skeleton,
uint tangentSpaceTexCoord)
{
nlassert(_Skinned);
if(_SkinWeights.size()==0)
return;
// get vertexPtr / normalOff / tangent space offset.
//===========================
CVertexBufferReadWrite vba;
_VBufferFinal.lock (vba);
uint8 *destVertexPtr= (uint8*)vba.getVertexCoordPointer();
uint flags= _VBufferFinal.getVertexFormat();
sint32 vertexSize= _VBufferFinal.getVertexSize();
// must have XYZ.
// if there's tangent space, there also must be a normal there.
nlassert((flags & CVertexBuffer::PositionFlag)
&& (flags & CVertexBuffer::NormalFlag)
);
// Compute offset of each component of the VB.
sint32 normalOff;
normalOff= _VBufferFinal.getNormalOff();
// tg space offset
sint32 tgSpaceOff = _VBufferFinal.getTexCoordOff((uint8) tangentSpaceTexCoord);
// compute src array.
CMesh::CSkinWeight *srcSkinPtr;
CVector *srcVertexPtr;
CVector *srcNormalPtr;
CVector *tgSpacePtr;
//
srcSkinPtr= &_SkinWeights[0];
srcVertexPtr= &_OriginalSkinVertices[0];
srcNormalPtr= &(_OriginalSkinNormals[0]);
tgSpacePtr = &(_OriginalTGSpace[0]);
// Compute useful Matrix for this lod.
//===========================
// Those arrays map the array of bones in skeleton.
static vector<CMatrix3x4> boneMat3x4;
computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);
// apply skinning (with tangent space added)
//===========================
// assert, code below is written especially for 4 per vertex.
nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
{
uint nInf= (uint)lod.InfluencedVertices[i].size();
if( nInf==0 )
continue;
uint32 *infPtr= &(lod.InfluencedVertices[i][0]);
// apply the skin to the vertices
applyArraySkinTangentSpaceT(i, infPtr, srcSkinPtr, srcVertexPtr, srcNormalPtr, tgSpacePtr,
normalOff, tgSpaceOff, destVertexPtr,
boneMat3x4, vertexSize, nInf);
}
}
// ***************************************************************************
// ***************************************************************************
// Raw "Vertex/Normal only" ApplySkin methods.
// ***************************************************************************
// ***************************************************************************
#define NL3D_RAWSKIN_NORMAL_OFF 12
#define NL3D_RAWSKIN_UV_OFF 24
#define NL3D_RAWSKIN_VERTEX_SIZE 32
/* Speed Feature test.
Don't use precaching for now, cause its seems to be slower on some configs (P4-2.4Ghz),
but maybe faster on other (P3-800)
On a P4-2.4Ghz, for 40000 vertices skinned, both no precaching and asm
saves 27% of execution time in the applyRawSkinNormal*() loop (ie 1 ms)
*/
#if defined(NL_OS_WINDOWS) && !defined(NL_NO_ASM)
//#define NL3D_RAWSKIN_PRECACHE
#define NL3D_RAWSKIN_ASM
#endif
// ***************************************************************************
void CMeshMRMGeom::applyArrayRawSkinNormal1(CRawVertexNormalSkin1 *src, uint8 *destVertexPtr,
CMatrix3x4 *boneMat3x4, uint nInf)
{
// must write contigously in AGP, and ASM is hardcoded...
nlctassert(NL3D_RAWSKIN_NORMAL_OFF==12);
nlctassert(NL3D_RAWSKIN_UV_OFF==24);
/*extern uint TESTYOYO_NumRawSkinVertices1;
TESTYOYO_NumRawSkinVertices1+= nInf;
H_AUTO( TestYoyo_RawSkin1 );*/
#ifdef NL3D_RAWSKIN_PRECACHE
for(;nInf>0;)
{
// number of vertices to process for this block.
uint nBlockInf= min(NumCacheVertexNormal1, nInf);
// next block.
nInf-= nBlockInf;
// cache the data in L1 cache.
CFastMem::precache(src, nBlockInf * sizeof(CRawVertexNormalSkin1));
#else
{
uint nBlockInf= nInf;
#endif
#ifndef NL3D_RAWSKIN_ASM
// for all InfluencedVertices only.
for(;nBlockInf>0;nBlockInf--, src++, destVertexPtr+=NL3D_RAWSKIN_VERTEX_SIZE)
{
CVector *dstVertex= (CVector*)(destVertexPtr);
CVector *dstNormal= (CVector*)(destVertexPtr + NL3D_RAWSKIN_NORMAL_OFF);
// For 1 matrix, can write directly to AGP (if destVertexPtr is AGP...)
// Vertex.
boneMat3x4[ src->MatrixId[0] ].mulSetPoint( src->Vertex.Pos, *(CVector*)(destVertexPtr) );
// Normal.
boneMat3x4[ src->MatrixId[0] ].mulSetVector( src->Vertex.Normal, *(CVector*)(destVertexPtr + NL3D_RAWSKIN_NORMAL_OFF) );
// UV copy.
*(CUV*)(destVertexPtr + NL3D_RAWSKIN_UV_OFF)= src->Vertex.UV;
}
#else
// ASM harcoded for 36
nlctassert(sizeof(CRawVertexNormalSkin1)==36);
/* 116 cycles / loop typical
58 cycles / loop in theory (no memory problem)
*/
__asm
{
mov ecx, nBlockInf
mov esi, src
mov edi, destVertexPtr
mov edx, boneMat3x4
theLoop:
// Vertex.
// **** boneMat3x4[ src->MatrixId[0] ].mulSetPoint( src->Vertex.Pos, *(CVector*)(destVertexPtr) );
// eax= matrix
mov eax, [esi]src.MatrixId // uop: 0/1
lea eax, [eax*2+eax]
shl eax, 4
add eax, edx // uop: 1/0
// load x y z
fld [esi]src.Vertex.Pos.x // uop: 0/1
fld [esi]src.Vertex.Pos.y // uop: 0/1
fld [esi]src.Vertex.Pos.z // uop: 0/1
// vout.x= (a11*vin.x + a12*vin.y + a13*vin.z + a14);
fld [eax]CMatrix3x4.a11 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
fld [eax]CMatrix3x4.a12 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a13 // uop: 0/1
fmul st, st(2) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a14 // uop: 0/1
faddp st(1), st // uop: 1/0 (3)
fstp dword ptr[edi] // uop: 0/0/1/1
// vout.y= (a21*vin.x + a22*vin.y + a23*vin.z + a24);
fld [eax]CMatrix3x4.a21
fmul st, st(3)
fld [eax]CMatrix3x4.a22
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a23
fmul st, st(2)
faddp st(1), st
fld [eax]CMatrix3x4.a24
faddp st(1), st
fstp dword ptr[edi+4]
// vout.z= (a31*vin.x + a32*vin.y + a33*vin.z + a34);
fld [eax]CMatrix3x4.a31
fmul st, st(3)
fld [eax]CMatrix3x4.a32
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a33
fmul st, st(2)
faddp st(1), st
fld [eax]CMatrix3x4.a34
faddp st(1), st
fstp dword ptr[edi+8]
// free x y z
fstp st // uop: 1/0
fstp st // uop: 1/0
fstp st // uop: 1/0
// Normal
// **** boneMat3x4[ src->MatrixId[0] ].mulSetVector( src->Vertex.Normal, *(CVector*)(destVertexPtr + NL3D_RAWSKIN_NORMAL_OFF) );
// load x y z
fld [esi]src.Vertex.Normal.x
fld [esi]src.Vertex.Normal.y
fld [esi]src.Vertex.Normal.z
// vout.x= (a11*vin.x + a12*vin.y + a13*vin.z + a14);
fld [eax]CMatrix3x4.a11 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
fld [eax]CMatrix3x4.a12 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a13 // uop: 0/1
fmul st, st(2) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fstp dword ptr[edi+12] // uop: 0/0/1/1
// vout.y= (a21*vin.x + a22*vin.y + a23*vin.z + a24);
fld [eax]CMatrix3x4.a21
fmul st, st(3)
fld [eax]CMatrix3x4.a22
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a23
fmul st, st(2)
faddp st(1), st
fstp dword ptr[edi+16]
// vout.z= (a31*vin.x + a32*vin.y + a33*vin.z + a34);
fld [eax]CMatrix3x4.a31
fmul st, st(3)
fld [eax]CMatrix3x4.a32
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a33
fmul st, st(2)
faddp st(1), st
fstp dword ptr[edi+20]
// free x y z
fstp st
fstp st
fstp st
// UV copy.
// **** *(CUV*)(destVertexPtr + NL3D_RAWSKIN_UV_OFF)= src->Vertex.UV;
mov eax, [esi]src.Vertex.UV.U // uop: 0/1
mov dword ptr[edi+24], eax // uop: 0/0/1/1
mov eax, [esi]src.Vertex.UV.V // uop: 0/1
mov dword ptr[edi+28], eax // uop: 0/0/1/1
// **** next
add esi, 36 // uop: 1/0
add edi, NL3D_RAWSKIN_VERTEX_SIZE // uop: 1/0
dec ecx // uop: 1/0
jnz theLoop // uop: 1/1 (p1)
mov nBlockInf, ecx
mov src, esi
mov destVertexPtr, edi
}
#endif
}
}
// ***************************************************************************
void CMeshMRMGeom::applyArrayRawSkinNormal2(CRawVertexNormalSkin2 *src, uint8 *destVertexPtr,
CMatrix3x4 *boneMat3x4, uint nInf)
{
// must write contigously in AGP, and ASM is hardcoded...
nlctassert(NL3D_RAWSKIN_NORMAL_OFF==12);
nlctassert(NL3D_RAWSKIN_UV_OFF==24);
/*extern uint TESTYOYO_NumRawSkinVertices2;
TESTYOYO_NumRawSkinVertices2+= nInf;
H_AUTO( TestYoyo_RawSkin2 );*/
// Since VertexPtr may be a AGP Ram, MUST NOT read into it! (mulAdd*() do it!)
CVector tmpVert;
#ifdef NL3D_RAWSKIN_PRECACHE
for(;nInf>0;)
{
// number of vertices to process for this block.
uint nBlockInf= min(NumCacheVertexNormal2, nInf);
// next block.
nInf-= nBlockInf;
// cache the data in L1 cache.
CFastMem::precache(src, nBlockInf * sizeof(CRawVertexNormalSkin2));
#else
{
uint nBlockInf= nInf;
#endif
#ifndef NL3D_RAWSKIN_ASM
// for all InfluencedVertices only.
for(;nBlockInf>0;nBlockInf--, src++, destVertexPtr+=NL3D_RAWSKIN_VERTEX_SIZE)
{
// Vertex.
boneMat3x4[ src->MatrixId[0] ].mulSetPoint( src->Vertex.Pos, src->Weights[0], tmpVert);
boneMat3x4[ src->MatrixId[1] ].mulAddPoint( src->Vertex.Pos, src->Weights[1], tmpVert);
*(CVector*)(destVertexPtr)= tmpVert;
// Normal.
boneMat3x4[ src->MatrixId[0] ].mulSetVector( src->Vertex.Normal, src->Weights[0], tmpVert);
boneMat3x4[ src->MatrixId[1] ].mulAddVector( src->Vertex.Normal, src->Weights[1], tmpVert);
*(CVector*)(destVertexPtr + NL3D_RAWSKIN_NORMAL_OFF)= tmpVert;
// UV copy.
*(CUV*)(destVertexPtr + NL3D_RAWSKIN_UV_OFF)= src->Vertex.UV;
}
#else
// ASM harcoded for 48
nlctassert(sizeof(CRawVertexNormalSkin2)==48);
/* 154 cycles / loop typical
124 cycles / loop in theory (no memory problem)
*/
__asm
{
mov ecx, nBlockInf
mov esi, src
mov edi, destVertexPtr
mov edx, boneMat3x4
theLoop:
// Vertex.
// **** boneMat3x4[ src->MatrixId[0] ].mulSetPoint( src->Vertex.Pos, *(CVector*)(destVertexPtr) );
// eax= matrix0
mov eax, [esi+0]src.MatrixId // uop: 0/1
lea eax, [eax*2+eax]
shl eax, 4
add eax, edx // uop: 1/0
// ebx= matrix1
mov ebx, [esi+4]src.MatrixId // uop: 0/1
lea ebx, [ebx*2+ebx]
shl ebx, 4
add ebx, edx // uop: 1/0
// load x y z
fld [esi]src.Vertex.Pos.x // uop: 0/1
fld [esi]src.Vertex.Pos.y // uop: 0/1
fld [esi]src.Vertex.Pos.z // uop: 0/1
// **** vout.x= (a11*vin.x + a12*vin.y + a13*vin.z + a14);
// 1st Matrix
fld [eax]CMatrix3x4.a11 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
fld [eax]CMatrix3x4.a12 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a13 // uop: 0/1
fmul st, st(2) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a14 // uop: 0/1
faddp st(1), st // uop: 1/0 (3)
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a11
fmul st, st(4)
fld [ebx]CMatrix3x4.a12
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a13
fmul st, st(3)
faddp st(1), st
fld [ebx]CMatrix3x4.a14
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi] // uop: 0/0/1/1
// **** vout.y= (a21*vin.x + a22*vin.y + a23*vin.z + a24);
fld [eax]CMatrix3x4.a21
fmul st, st(3)
fld [eax]CMatrix3x4.a22
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a23
fmul st, st(2)
faddp st(1), st
fld [eax]CMatrix3x4.a24
faddp st(1), st
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a21
fmul st, st(4)
fld [ebx]CMatrix3x4.a22
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a23
fmul st, st(3)
faddp st(1), st
fld [ebx]CMatrix3x4.a24
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+4]
// **** vout.z= (a31*vin.x + a32*vin.y + a33*vin.z + a34);
fld [eax]CMatrix3x4.a31
fmul st, st(3)
fld [eax]CMatrix3x4.a32
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a33
fmul st, st(2)
faddp st(1), st
fld [eax]CMatrix3x4.a34
faddp st(1), st
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a31
fmul st, st(4)
fld [ebx]CMatrix3x4.a32
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a33
fmul st, st(3)
faddp st(1), st
fld [ebx]CMatrix3x4.a34
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+8]
// free x y z
fstp st // uop: 1/0
fstp st // uop: 1/0
fstp st // uop: 1/0
// Normal
// **** boneMat3x4[ src->MatrixId[0] ].mulSetVector( src->Vertex.Normal, *(CVector*)(destVertexPtr + NL3D_RAWSKIN_NORMAL_OFF) );
// load x y z
fld [esi]src.Vertex.Normal.x
fld [esi]src.Vertex.Normal.y
fld [esi]src.Vertex.Normal.z
// **** vout.x= (a11*vin.x + a12*vin.y + a13*vin.z + a14);
fld [eax]CMatrix3x4.a11 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
fld [eax]CMatrix3x4.a12 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a13 // uop: 0/1
fmul st, st(2) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a11
fmul st, st(4)
fld [ebx]CMatrix3x4.a12
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a13
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+12] // uop: 0/0/1/1
// **** vout.y= (a21*vin.x + a22*vin.y + a23*vin.z + a24);
fld [eax]CMatrix3x4.a21
fmul st, st(3)
fld [eax]CMatrix3x4.a22
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a23
fmul st, st(2)
faddp st(1), st
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a21
fmul st, st(4)
fld [ebx]CMatrix3x4.a22
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a23
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+16]
// **** vout.z= (a31*vin.x + a32*vin.y + a33*vin.z + a34);
fld [eax]CMatrix3x4.a31
fmul st, st(3)
fld [eax]CMatrix3x4.a32
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a33
fmul st, st(2)
faddp st(1), st
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a31
fmul st, st(4)
fld [ebx]CMatrix3x4.a32
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a33
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+20]
// free x y z
fstp st
fstp st
fstp st
// UV copy.
// **** *(CUV*)(destVertexPtr + NL3D_RAWSKIN_UV_OFF)= src->Vertex.UV;
mov eax, [esi]src.Vertex.UV.U // uop: 0/1
mov dword ptr[edi+24], eax // uop: 0/0/1/1
mov eax, [esi]src.Vertex.UV.V // uop: 0/1
mov dword ptr[edi+28], eax // uop: 0/0/1/1
// **** next
add esi, 48 // uop: 1/0
add edi, NL3D_RAWSKIN_VERTEX_SIZE // uop: 1/0
dec ecx // uop: 1/0
jnz theLoop // uop: 1/1 (p1)
mov nBlockInf, ecx
mov src, esi
mov destVertexPtr, edi
}
#endif
}
}
// ***************************************************************************
void CMeshMRMGeom::applyArrayRawSkinNormal3(CRawVertexNormalSkin3 *src, uint8 *destVertexPtr,
CMatrix3x4 *boneMat3x4, uint nInf)
{
// must write contigously in AGP, and ASM is hardcoded...
nlctassert(NL3D_RAWSKIN_NORMAL_OFF==12);
nlctassert(NL3D_RAWSKIN_UV_OFF==24);
/*extern uint TESTYOYO_NumRawSkinVertices3;
TESTYOYO_NumRawSkinVertices3+= nInf;
H_AUTO( TestYoyo_RawSkin3 );*/
// Since VertexPtr may be a AGP Ram, MUST NOT read into it! (mulAdd*() do it!)
CVector tmpVert;
#ifdef NL3D_RAWSKIN_PRECACHE
for(;nInf>0;)
{
// number of vertices to process for this block.
uint nBlockInf= min(NumCacheVertexNormal3, nInf);
// next block.
nInf-= nBlockInf;
// cache the data in L1 cache.
CFastMem::precache(src, nBlockInf * sizeof(CRawVertexNormalSkin3));
#else
{
uint nBlockInf= nInf;
#endif
#ifndef NL3D_RAWSKIN_ASM
// for all InfluencedVertices only.
for(;nBlockInf>0;nBlockInf--, src++, destVertexPtr+=NL3D_RAWSKIN_VERTEX_SIZE)
{
// Vertex.
boneMat3x4[ src->MatrixId[0] ].mulSetPoint( src->Vertex.Pos, src->Weights[0], tmpVert);
boneMat3x4[ src->MatrixId[1] ].mulAddPoint( src->Vertex.Pos, src->Weights[1], tmpVert);
boneMat3x4[ src->MatrixId[2] ].mulAddPoint( src->Vertex.Pos, src->Weights[2], tmpVert);
*(CVector*)(destVertexPtr)= tmpVert;
// Normal.
boneMat3x4[ src->MatrixId[0] ].mulSetVector( src->Vertex.Normal, src->Weights[0], tmpVert);
boneMat3x4[ src->MatrixId[1] ].mulAddVector( src->Vertex.Normal, src->Weights[1], tmpVert);
boneMat3x4[ src->MatrixId[2] ].mulAddVector( src->Vertex.Normal, src->Weights[2], tmpVert);
*(CVector*)(destVertexPtr + NL3D_RAWSKIN_NORMAL_OFF)= tmpVert;
// UV copy.
*(CUV*)(destVertexPtr + NL3D_RAWSKIN_UV_OFF)= src->Vertex.UV;
}
#else
// ASM harcoded for 56
nlctassert(sizeof(CRawVertexNormalSkin3)==56);
/* 226 cycles / loop typical
192 cycles / loop in theory (no memory problem)
148 optimal
*/
__asm
{
mov ecx, nBlockInf
mov esi, src
mov edi, destVertexPtr
theLoop:
// Vertex.
// **** boneMat3x4[ src->MatrixId[0] ].mulSetPoint( src->Vertex.Pos, *(CVector*)(destVertexPtr) );
// eax= matrix0
mov eax, [esi+0]src.MatrixId // uop: 0/1
lea eax, [eax*2+eax]
shl eax, 4
add eax, boneMat3x4 // uop: 1/0
// ebx= matrix1
mov ebx, [esi+4]src.MatrixId // uop: 0/1
lea ebx, [ebx*2+ebx]
shl ebx, 4
add ebx, boneMat3x4 // uop: 1/0
// edx= matrix2
mov edx, [esi+8]src.MatrixId // uop: 0/1
lea edx, [edx*2+edx]
shl edx, 4
add edx, boneMat3x4 // uop: 1/0
// load x y z
fld [esi]src.Vertex.Pos.x // uop: 0/1
fld [esi]src.Vertex.Pos.y // uop: 0/1
fld [esi]src.Vertex.Pos.z // uop: 0/1
// **** vout.x= (a11*vin.x + a12*vin.y + a13*vin.z + a14);
// 1st Matrix
fld [eax]CMatrix3x4.a11 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
fld [eax]CMatrix3x4.a12 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a13 // uop: 0/1
fmul st, st(2) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a14 // uop: 0/1
faddp st(1), st // uop: 1/0 (3)
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a11
fmul st, st(4)
fld [ebx]CMatrix3x4.a12
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a13
fmul st, st(3)
faddp st(1), st
fld [ebx]CMatrix3x4.a14
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// 3rd matrix
fld [edx]CMatrix3x4.a11
fmul st, st(4)
fld [edx]CMatrix3x4.a12
fmul st, st(4)
faddp st(1), st
fld [edx]CMatrix3x4.a13
fmul st, st(3)
faddp st(1), st
fld [edx]CMatrix3x4.a14
faddp st(1), st
// mul by scale, and append
fmul [esi+8]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi] // uop: 0/0/1/1
// **** vout.y= (a21*vin.x + a22*vin.y + a23*vin.z + a24);
fld [eax]CMatrix3x4.a21
fmul st, st(3)
fld [eax]CMatrix3x4.a22
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a23
fmul st, st(2)
faddp st(1), st
fld [eax]CMatrix3x4.a24
faddp st(1), st
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a21
fmul st, st(4)
fld [ebx]CMatrix3x4.a22
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a23
fmul st, st(3)
faddp st(1), st
fld [ebx]CMatrix3x4.a24
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// 3rd matrix
fld [edx]CMatrix3x4.a21
fmul st, st(4)
fld [edx]CMatrix3x4.a22
fmul st, st(4)
faddp st(1), st
fld [edx]CMatrix3x4.a23
fmul st, st(3)
faddp st(1), st
fld [edx]CMatrix3x4.a24
faddp st(1), st
// mul by scale, and append
fmul [esi+8]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+4]
// **** vout.z= (a31*vin.x + a32*vin.y + a33*vin.z + a34);
fld [eax]CMatrix3x4.a31
fmul st, st(3)
fld [eax]CMatrix3x4.a32
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a33
fmul st, st(2)
faddp st(1), st
fld [eax]CMatrix3x4.a34
faddp st(1), st
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a31
fmul st, st(4)
fld [ebx]CMatrix3x4.a32
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a33
fmul st, st(3)
faddp st(1), st
fld [ebx]CMatrix3x4.a34
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// 3rd matrix
fld [edx]CMatrix3x4.a31
fmul st, st(4)
fld [edx]CMatrix3x4.a32
fmul st, st(4)
faddp st(1), st
fld [edx]CMatrix3x4.a33
fmul st, st(3)
faddp st(1), st
fld [edx]CMatrix3x4.a34
faddp st(1), st
// mul by scale, and append
fmul [esi+8]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+8]
// free x y z
fstp st // uop: 1/0
fstp st // uop: 1/0
fstp st // uop: 1/0
// Normal
// **** boneMat3x4[ src->MatrixId[0] ].mulSetVector( src->Vertex.Normal, *(CVector*)(destVertexPtr + NL3D_RAWSKIN_NORMAL_OFF) );
// load x y z
fld [esi]src.Vertex.Normal.x
fld [esi]src.Vertex.Normal.y
fld [esi]src.Vertex.Normal.z
// **** vout.x= (a11*vin.x + a12*vin.y + a13*vin.z + a14);
fld [eax]CMatrix3x4.a11 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
fld [eax]CMatrix3x4.a12 // uop: 0/1
fmul st, st(3) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
fld [eax]CMatrix3x4.a13 // uop: 0/1
fmul st, st(2) // uop: 1/0 (5)
faddp st(1), st // uop: 1/0 (3)
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a11
fmul st, st(4)
fld [ebx]CMatrix3x4.a12
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a13
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// 3rd matrix
fld [edx]CMatrix3x4.a11
fmul st, st(4)
fld [edx]CMatrix3x4.a12
fmul st, st(4)
faddp st(1), st
fld [edx]CMatrix3x4.a13
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+8]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+12] // uop: 0/0/1/1
// **** vout.y= (a21*vin.x + a22*vin.y + a23*vin.z + a24);
fld [eax]CMatrix3x4.a21
fmul st, st(3)
fld [eax]CMatrix3x4.a22
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a23
fmul st, st(2)
faddp st(1), st
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a21
fmul st, st(4)
fld [ebx]CMatrix3x4.a22
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a23
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// 3rd matrix
fld [edx]CMatrix3x4.a21
fmul st, st(4)
fld [edx]CMatrix3x4.a22
fmul st, st(4)
faddp st(1), st
fld [edx]CMatrix3x4.a23
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+8]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+16]
// **** vout.z= (a31*vin.x + a32*vin.y + a33*vin.z + a34);
fld [eax]CMatrix3x4.a31
fmul st, st(3)
fld [eax]CMatrix3x4.a32
fmul st, st(3)
faddp st(1), st
fld [eax]CMatrix3x4.a33
fmul st, st(2)
faddp st(1), st
// mul by scale
fmul [esi+0]src.Weights
// 2nd matrix
fld [ebx]CMatrix3x4.a31
fmul st, st(4)
fld [ebx]CMatrix3x4.a32
fmul st, st(4)
faddp st(1), st
fld [ebx]CMatrix3x4.a33
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+4]src.Weights
faddp st(1), st
// 3rd matrix
fld [edx]CMatrix3x4.a31
fmul st, st(4)
fld [edx]CMatrix3x4.a32
fmul st, st(4)
faddp st(1), st
fld [edx]CMatrix3x4.a33
fmul st, st(3)
faddp st(1), st
// mul by scale, and append
fmul [esi+8]src.Weights
faddp st(1), st
// store
fstp dword ptr[edi+20]
// free x y z
fstp st
fstp st
fstp st
// UV copy.
// **** *(CUV*)(destVertexPtr + NL3D_RAWSKIN_UV_OFF)= src->Vertex.UV;
mov eax, [esi]src.Vertex.UV.U // uop: 0/1
mov dword ptr[edi+24], eax // uop: 0/0/1/1
mov eax, [esi]src.Vertex.UV.V // uop: 0/1
mov dword ptr[edi+28], eax // uop: 0/0/1/1
// **** next
add esi, 56 // uop: 1/0
add edi, NL3D_RAWSKIN_VERTEX_SIZE // uop: 1/0
dec ecx // uop: 1/0
jnz theLoop // uop: 1/1 (p1)
mov nBlockInf, ecx
mov src, esi
mov destVertexPtr, edi
}
#endif
}
}
// ***************************************************************************
void CMeshMRMGeom::applyArrayRawSkinNormal4(CRawVertexNormalSkin4 *src, uint8 *destVertexPtr,
CMatrix3x4 *boneMat3x4, uint nInf)
{
// must write contigously in AGP, and ASM is hardcoded...
nlctassert(NL3D_RAWSKIN_NORMAL_OFF==12);
nlctassert(NL3D_RAWSKIN_UV_OFF==24);
/*extern uint TESTYOYO_NumRawSkinVertices4;
TESTYOYO_NumRawSkinVertices4+= nInf;
H_AUTO( TestYoyo_RawSkin4 );*/
// Since VertexPtr may be a AGP Ram, MUST NOT read into it! (mulAdd*() do it!)
CVector tmpVert;
#ifdef NL3D_RAWSKIN_PRECACHE
for(;nInf>0;)
{
// number of vertices to process for this block.
uint nBlockInf= min(NumCacheVertexNormal4, nInf);
// next block.
nInf-= nBlockInf;
// cache the data in L1 cache.
CFastMem::precache(src, nBlockInf * sizeof(CRawVertexNormalSkin4));
#else
{
uint nBlockInf= nInf;
#endif
// for all InfluencedVertices only.
for(;nBlockInf>0;nBlockInf--, src++, destVertexPtr+=NL3D_RAWSKIN_VERTEX_SIZE)
{
// Vertex.
boneMat3x4[ src->MatrixId[0] ].mulSetPoint( src->Vertex.Pos, src->Weights[0], tmpVert);
boneMat3x4[ src->MatrixId[1] ].mulAddPoint( src->Vertex.Pos, src->Weights[1], tmpVert);
boneMat3x4[ src->MatrixId[2] ].mulAddPoint( src->Vertex.Pos, src->Weights[2], tmpVert);
boneMat3x4[ src->MatrixId[3] ].mulAddPoint( src->Vertex.Pos, src->Weights[3], tmpVert);
*(CVector*)(destVertexPtr)= tmpVert;
// Normal.
boneMat3x4[ src->MatrixId[0] ].mulSetVector( src->Vertex.Normal, src->Weights[0], tmpVert);
boneMat3x4[ src->MatrixId[1] ].mulAddVector( src->Vertex.Normal, src->Weights[1], tmpVert);
boneMat3x4[ src->MatrixId[2] ].mulAddVector( src->Vertex.Normal, src->Weights[2], tmpVert);
boneMat3x4[ src->MatrixId[3] ].mulAddVector( src->Vertex.Normal, src->Weights[3], tmpVert);
*(CVector*)(destVertexPtr + NL3D_RAWSKIN_NORMAL_OFF)= tmpVert;
// UV copy.
*(CUV*)(destVertexPtr + NL3D_RAWSKIN_UV_OFF)= src->Vertex.UV;
}
// NB: ASM not done for 4 vertices, cause very rare and negligeable ...
}
}
// ***************************************************************************
void CMeshMRMGeom::applyRawSkinWithNormal(CLod &lod, CRawSkinNormalCache &rawSkinLod, const CSkeletonModel *skeleton, uint8 *vbHard, float alphaLod)
{
nlassert(_Skinned);
if(_SkinWeights.size()==0)
return;
// Some assert
//===========================
// must have XYZ, Normal and UV only
nlassert( _VBufferFinal.getVertexFormat() == (CVertexBuffer::PositionFlag | CVertexBuffer::NormalFlag | CVertexBuffer::TexCoord0Flag) );
nlassert( _VBufferFinal.getValueType(CVertexBuffer::TexCoord0) == CVertexBuffer::Float2 );
nlassert( _VBufferFinal.getVertexSize() ==NL3D_RAWSKIN_VERTEX_SIZE);
// HardCoded for normalOff==12 (see applyArrayRawSkinNormal*)
nlassert( _VBufferFinal.getNormalOff()==NL3D_RAWSKIN_NORMAL_OFF );
nlassert( _VBufferFinal.getTexCoordOff()==NL3D_RAWSKIN_UV_OFF );
// assert, code below is written especially for 4 per vertex.
nlassert( NL3D_MESH_SKINNING_MAX_MATRIX==4 );
// Compute useful Matrix for this lod.
//===========================
// Those arrays map the array of bones in skeleton.
static vector<CMatrix3x4> boneMat3x4;
computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);
// TestYoyo
/*extern uint TESTYOYO_NumRawSkinVertices;
TESTYOYO_NumRawSkinVertices+= rawSkinLod.Vertices1.size();
TESTYOYO_NumRawSkinVertices+= rawSkinLod.Vertices2.size();
TESTYOYO_NumRawSkinVertices+= rawSkinLod.Vertices3.size();
TESTYOYO_NumRawSkinVertices+= rawSkinLod.Vertices4.size();*/
uint nInf;
// Manage "SoftVertices"
if(rawSkinLod.TotalSoftVertices)
{
// apply skinning into Temp RAM for vertices that are Src of Geomorph
//===========================
static vector<uint8> tempSkin;
uint tempVbSize= rawSkinLod.TotalSoftVertices*NL3D_RAWSKIN_VERTEX_SIZE;
if(tempSkin.size() < tempVbSize)
tempSkin.resize(tempVbSize);
uint8 *destVertexPtr= &tempSkin[0];
// 1 Matrix
nInf= rawSkinLod.SoftVertices[0];
if(nInf>0)
{
applyArrayRawSkinNormal1(&rawSkinLod.Vertices1[0], destVertexPtr, &boneMat3x4[0], nInf);
destVertexPtr+= nInf * NL3D_RAWSKIN_VERTEX_SIZE;
}
// 2 Matrix
nInf= rawSkinLod.SoftVertices[1];
if(nInf>0)
{
applyArrayRawSkinNormal2(&rawSkinLod.Vertices2[0], destVertexPtr, &boneMat3x4[0], nInf);
destVertexPtr+= nInf * NL3D_RAWSKIN_VERTEX_SIZE;
}
// 3 Matrix
nInf= rawSkinLod.SoftVertices[2];
if(nInf>0)
{
applyArrayRawSkinNormal3(&rawSkinLod.Vertices3[0], destVertexPtr, &boneMat3x4[0], nInf);
destVertexPtr+= nInf * NL3D_RAWSKIN_VERTEX_SIZE;
}
// 4 Matrix
nInf= rawSkinLod.SoftVertices[3];
if(nInf>0)
{
applyArrayRawSkinNormal4(&rawSkinLod.Vertices4[0], destVertexPtr, &boneMat3x4[0], nInf);
destVertexPtr+= nInf * NL3D_RAWSKIN_VERTEX_SIZE;
}
// Fast Copy this into AGP Ram. NB: done before Geomorphs, because ensure some precaching this way!!
//===========================
// Skin geomorphs.
uint8 *vbHardStart= vbHard + rawSkinLod.Geomorphs.size()*NL3D_RAWSKIN_VERTEX_SIZE;
// fast copy
CFastMem::memcpy(vbHardStart, &tempSkin[0], tempVbSize);
// Geomorphs directly into AGP Ram
//===========================
clamp(alphaLod, 0.f, 1.f);
float a= alphaLod;
float a1= 1 - alphaLod;
// Fast Geomorph
applyGeomorphPosNormalUV0(rawSkinLod.Geomorphs, &tempSkin[0], vbHard, NL3D_RAWSKIN_VERTEX_SIZE, a, a1);
}
// Manage HardVertices
if(rawSkinLod.TotalHardVertices)
{
// apply skinning directly into AGP RAM for vertices that are not Src of Geomorph
//===========================
uint startId;
// Skip Geomorphs and SoftVertices.
uint8 *destVertexPtr= vbHard + (rawSkinLod.Geomorphs.size()+rawSkinLod.TotalSoftVertices)*NL3D_RAWSKIN_VERTEX_SIZE;
// 1 Matrix
nInf= rawSkinLod.HardVertices[0];
startId= rawSkinLod.SoftVertices[0];
if(nInf>0)
{
applyArrayRawSkinNormal1(&rawSkinLod.Vertices1[startId], destVertexPtr, &boneMat3x4[0], nInf);
destVertexPtr+= nInf * NL3D_RAWSKIN_VERTEX_SIZE;
}
// 2 Matrix
nInf= rawSkinLod.HardVertices[1];
startId= rawSkinLod.SoftVertices[1];
if(nInf>0)
{
applyArrayRawSkinNormal2(&rawSkinLod.Vertices2[startId], destVertexPtr, &boneMat3x4[0], nInf);
destVertexPtr+= nInf * NL3D_RAWSKIN_VERTEX_SIZE;
}
// 3 Matrix
nInf= rawSkinLod.HardVertices[2];
startId= rawSkinLod.SoftVertices[2];
if(nInf>0)
{
applyArrayRawSkinNormal3(&rawSkinLod.Vertices3[startId], destVertexPtr, &boneMat3x4[0], nInf);
destVertexPtr+= nInf * NL3D_RAWSKIN_VERTEX_SIZE;
}
// 4 Matrix
nInf= rawSkinLod.HardVertices[3];
startId= rawSkinLod.SoftVertices[3];
if(nInf>0)
{
applyArrayRawSkinNormal4(&rawSkinLod.Vertices4[startId], destVertexPtr, &boneMat3x4[0], nInf);
destVertexPtr+= nInf * NL3D_RAWSKIN_VERTEX_SIZE;
}
}
}
#endif // ADD_MESH_MRM_SKIN_TEMPLATE