HRESULT D3DXMeshTransformation( LPD3DXMESH pMesh, const D3DXMATRIX* pMatrix , VisitorForD3DXVECTOR3* pPointFilter) { KG_PROCESS_ERROR(NULL != pMesh && NULL != pMatrix); { DWORD fvf = pMesh->GetFVF(); KG_PROCESS_ERROR(fvf | D3DFVF_XYZ); DWORD dwNumBytePerVertex = pMesh->GetNumBytesPerVertex(); _ASSERTE(dwNumBytePerVertex >= sizeof(D3DXVECTOR3)); DWORD dwNumVertex = pMesh->GetNumVertices(); BYTE* pBufferStart = NULL; _ASSERTE(sizeof(BYTE) == 1); if(NULL == pPointFilter) { HRESULT hr = pMesh->LockVertexBuffer(0, (LPVOID*)&pBufferStart); KG_COM_PROCESS_ERROR(hr); D3DXVec3TransformCoordArray((D3DXVECTOR3*)(pBufferStart), dwNumBytePerVertex , (D3DXVECTOR3*)pBufferStart, dwNumBytePerVertex, pMatrix, dwNumVertex); pMesh->UnlockVertexBuffer(); } else { //加了Filter之后性能下降是当然的,但是这不是给实时用的,所以没有关系,控制 //调用次数和调用时机就好了 D3DXMeshVertexEnumer vertexEnumer; HRESULT hr = D3DXMeshCreateVertexEnumer(pMesh, vertexEnumer); KG_COM_PROCESS_ERROR(hr); _ASSERTE(vertexEnumer.IsValid()); HRESULT hrForVisitor = E_FAIL; for (UINT i = 0; i < vertexEnumer.GetVertexCount(); ++i) { const D3DXVECTOR3& vTemp = vertexEnumer.GetPos(i); hrForVisitor = pPointFilter->Accept(vTemp); if (FAILED(hr)) { continue; } D3DXVECTOR3 vTransformed; D3DXVec3TransformCoord(&vTransformed, &vTemp, pMatrix); vertexEnumer.SetPos(i, vTransformed); } } } return S_OK; Exit0: return E_FAIL; }
//------------------------------------------------------------------------------------------------ // Name: CopyYRotatedGeometry // Desc: Copies geometry from one location to another, and rotates it about the Y-axis. This // method returns a pointer to the the next empty vertex in destGeometry //------------------------------------------------------------------------------------------------ GeometryVertex* CopyYRotatedGeometry(GeometryVertex* destGeometry, const GeometryVertex* sourceGeometry, int vertices, float angle) { // Copy all of the geometry memcpy(destGeometry, sourceGeometry, sizeof(GeometryVertex) * vertices); // Create the transformation matrix D3DXMATRIXA16 matrix; D3DXMatrixRotationY(&matrix, -angle); // this has to be negative for it to work // Transform this geometry in place D3DXVec3TransformCoordArray((D3DXVECTOR3*)destGeometry, sizeof(GeometryVertex), (const D3DXVECTOR3*)destGeometry, sizeof(GeometryVertex), &matrix, vertices); for (int i = 0; i < vertices; ++i) { destGeometry[i].nx = 0.0f; destGeometry[i].ny = 1.0f; destGeometry[i].nz = 0.0f; } // Return an empty area of the destination geometry pointer return destGeometry + vertices; }
static HRESULT WINAPI ID3DXSpriteImpl_Flush(ID3DXSprite *iface) { ID3DXSpriteImpl *This = impl_from_ID3DXSprite(iface); SPRITEVERTEX *vertices; int i, count=0, start; TRACE("(%p)->(): relay\n", This); if(!This->ready) return D3DERR_INVALIDCALL; if(!This->sprite_count) return D3D_OK; /* TODO: use of a vertex buffer here */ vertices=HeapAlloc(GetProcessHeap(), 0, sizeof(SPRITEVERTEX)*6*This->sprite_count); for(start=0; start<This->sprite_count; start+=count,count=0) { i=start; while(i<This->sprite_count && (count==0 || This->sprites[i].texture==This->sprites[i-1].texture)) { float spritewidth=(float)This->sprites[i].rect.right-(float)This->sprites[i].rect.left; float spriteheight=(float)This->sprites[i].rect.bottom-(float)This->sprites[i].rect.top; vertices[6*i ].pos.x = This->sprites[i].pos.x - This->sprites[i].center.x; vertices[6*i ].pos.y = This->sprites[i].pos.y - This->sprites[i].center.y; vertices[6*i ].pos.z = This->sprites[i].pos.z - This->sprites[i].center.z; vertices[6*i+1].pos.x = spritewidth + This->sprites[i].pos.x - This->sprites[i].center.x; vertices[6*i+1].pos.y = This->sprites[i].pos.y - This->sprites[i].center.y; vertices[6*i+1].pos.z = This->sprites[i].pos.z - This->sprites[i].center.z; vertices[6*i+2].pos.x = spritewidth + This->sprites[i].pos.x - This->sprites[i].center.x; vertices[6*i+2].pos.y = spriteheight + This->sprites[i].pos.y - This->sprites[i].center.y; vertices[6*i+2].pos.z = This->sprites[i].pos.z - This->sprites[i].center.z; vertices[6*i+3].pos.x = This->sprites[i].pos.x - This->sprites[i].center.x; vertices[6*i+3].pos.y = spriteheight + This->sprites[i].pos.y - This->sprites[i].center.y; vertices[6*i+3].pos.z = This->sprites[i].pos.z - This->sprites[i].center.z; vertices[6*i ].col = This->sprites[i].color; vertices[6*i+1].col = This->sprites[i].color; vertices[6*i+2].col = This->sprites[i].color; vertices[6*i+3].col = This->sprites[i].color; vertices[6*i ].tex.x = (float)This->sprites[i].rect.left / (float)This->sprites[i].texw; vertices[6*i ].tex.y = (float)This->sprites[i].rect.top / (float)This->sprites[i].texh; vertices[6*i+1].tex.x = (float)This->sprites[i].rect.right / (float)This->sprites[i].texw; vertices[6*i+1].tex.y = (float)This->sprites[i].rect.top / (float)This->sprites[i].texh; vertices[6*i+2].tex.x = (float)This->sprites[i].rect.right / (float)This->sprites[i].texw; vertices[6*i+2].tex.y = (float)This->sprites[i].rect.bottom / (float)This->sprites[i].texh; vertices[6*i+3].tex.x = (float)This->sprites[i].rect.left / (float)This->sprites[i].texw; vertices[6*i+3].tex.y = (float)This->sprites[i].rect.bottom / (float)This->sprites[i].texh; vertices[6*i+4]=vertices[6*i]; vertices[6*i+5]=vertices[6*i+2]; D3DXVec3TransformCoordArray(&vertices[6*i].pos, sizeof(SPRITEVERTEX), &vertices[6*i].pos, sizeof(SPRITEVERTEX), &This->sprites[i].transform, 6); count++; i++; } IDirect3DDevice9_SetTexture(This->device, 0, (struct IDirect3DBaseTexture9 *)This->sprites[start].texture); IDirect3DDevice9_SetVertexDeclaration(This->device, This->vdecl); IDirect3DDevice9_DrawPrimitiveUP(This->device, D3DPT_TRIANGLELIST, 2*count, vertices+6*start, sizeof(SPRITEVERTEX)); } HeapFree(GetProcessHeap(), 0, vertices); if(!(This->flags & D3DXSPRITE_DO_NOT_ADDREF_TEXTURE)) for(i=0; i<This->sprite_count; i++) IDirect3DTexture9_Release(This->sprites[i].texture); This->sprite_count=0; /* Flush may be called more than once, so we don't reset This->ready here */ return D3D_OK; }
static void CalculateLisPSM( const CCameraEntity& cam, Light& light ) { CalculateOrthoShadow( cam, light ); const SVector3& lightDir = light.mWorldMat.getAxisZ(); const SVector3& viewDir = cam.mWorldMat.getAxisZ(); double dotProd = lightDir.dot( viewDir ); if( fabs(dotProd) >= 0.999 ) { // degenerates to uniform shadow map return; } // calculate the hull of body B in world space HullFace bodyB; SMatrix4x4 invCamVP; D3DXMatrixInverse( &invCamVP, NULL, &cam.mWorldMat ); invCamVP *= cam.getProjectionMatrix(); D3DXMatrixInverse( &invCamVP, NULL, &invCamVP ); CalculateFocusedLightHull( invCamVP, lightDir, gCasterBounds, bodyB ); int zzz = bodyB.v.size(); int i, j; /* Frustum camFrustum( cam.getProjectionMatrix() ); std::vector<SVector3> bodyB; bodyB.reserve( gSceneCasters.size()*8 + 8 ); for( i = 0; i < 8; ++i ) bodyB.push_back( camFrustum.pntList[i] ); int ncasters = gSceneCasters.size(); for( i = 0; i < ncasters; ++i ) { const CAABox& aabb = gSceneCasters[i].aabb; for( j = 0; j < 8; ++j ) { SVector3 p; p.x = (j&1) ? aabb.getMin().x : aabb.getMax().x; p.y = (j&2) ? aabb.getMin().y : aabb.getMax().y; p.z = (j&4) ? aabb.getMin().z : aabb.getMax().z; bodyB.push_back( p ); } } */ // calculate basis of light space projection SVector3 ly = -lightDir; SVector3 lx = ly.cross( viewDir ).getNormalized(); SVector3 lz = lx.cross( ly ); SMatrix4x4 lightW; lightW.identify(); lightW.getAxisX() = lx; lightW.getAxisY() = ly; lightW.getAxisZ() = lz; SMatrix4x4 lightV; D3DXMatrixInverse( &lightV, NULL, &lightW ); // rotate bound body points from world into light projection space and calculate AABB there D3DXVec3TransformCoordArray( &bodyB.v[0], sizeof(SVector3), &bodyB.v[0], sizeof(SVector3), &lightV, bodyB.v.size() ); CAABox bodyLBounds; bodyLBounds.setNull(); for( i = 0; i < bodyB.v.size(); ++i ) bodyLBounds.extend( bodyB.v[i] ); float zextent = cam.getZFar() - cam.getZNear(); float zLextent = bodyLBounds.getMax().z - bodyLBounds.getMin().z; if( zLextent < zextent ) zextent = zLextent; // calculate free parameter N double sinGamma = sqrt( 1.0-dotProd*dotProd ); const double n = ( cam.getZNear() + sqrt(cam.getZNear() * (cam.getZNear() + zextent)) ) / sinGamma; // origin in this light space: looking at center of bounds, from distance n SVector3 lightSpaceO = bodyLBounds.getCenter(); lightSpaceO.z = bodyLBounds.getMin().z - n; // go through bound points in light space, and compute projected bound float maxx = 0.0f, maxy = 0.0f, maxz = 0.0f; for( i = 0; i < bodyB.v.size(); ++i ) { SVector3 tmp = bodyB.v[i] - lightSpaceO; assert( tmp.z > 0.0f ); maxx = max( maxx, fabsf(tmp.x / tmp.z) ); maxy = max( maxy, fabsf(tmp.y / tmp.z) ); maxz = max( maxz, tmp.z ); } SVector3 lpos; D3DXVec3TransformCoord( &lpos, &lightSpaceO, &lightW ); lightW.getOrigin() = lpos; SMatrix4x4 lightProj; D3DXMatrixPerspectiveLH( &lightProj, 2.0f*maxx*n, 2.0f*maxy*n, n, maxz ); SMatrix4x4 lsPermute, lsOrtho; lsPermute._11 = 1.f; lsPermute._12 = 0.f; lsPermute._13 = 0.f; lsPermute._14 = 0.f; lsPermute._21 = 0.f; lsPermute._22 = 0.f; lsPermute._23 =-1.f; lsPermute._24 = 0.f; lsPermute._31 = 0.f; lsPermute._32 = 1.f; lsPermute._33 = 0.f; lsPermute._34 = 0.f; lsPermute._41 = 0.f; lsPermute._42 = -0.5f; lsPermute._43 = 1.5f; lsPermute._44 = 1.f; D3DXMatrixOrthoLH( &lsOrtho, 2.f, 1.f, 0.5f, 2.5f ); lsPermute *= lsOrtho; lightProj *= lsPermute; G_RENDERCTX->getCamera().setCameraMatrix( lightW ); SMatrix4x4 lightFinal = G_RENDERCTX->getCamera().getViewMatrix() * lightProj; // unit cube clipping /* { // receiver hull std::vector<SVector3> receiverPts; receiverPts.reserve( gSceneReceivers.size() * 8 ); int nreceivers = gSceneReceivers.size(); for( i = 0; i < nreceivers; ++i ) { const CAABox& aabb = gSceneReceivers[i].aabb; for( j = 0; j < 8; ++j ) { SVector3 p; p.x = (j&1) ? aabb.getMin().x : aabb.getMax().x; p.y = (j&2) ? aabb.getMin().y : aabb.getMax().y; p.z = (j&4) ? aabb.getMin().z : aabb.getMax().z; receiverPts.push_back( p ); } } // transform to light post-perspective space D3DXVec3TransformCoordArray( &receiverPts[0], sizeof(SVector3), &receiverPts[0], sizeof(SVector3), &lightFinal, receiverPts.size() ); CAABox recvBounds; recvBounds.setNull(); for( i = 0; i < receiverPts.size(); ++i ) recvBounds.extend( receiverPts[i] ); recvBounds.getMax().x = min( 1.f, recvBounds.getMax().x ); recvBounds.getMin().x = max(-1.f, recvBounds.getMin().x ); recvBounds.getMax().y = min( 1.f, recvBounds.getMax().y ); recvBounds.getMin().y = max(-1.f, recvBounds.getMin().y ); float boxWidth = recvBounds.getMax().x - recvBounds.getMin().x; float boxHeight = recvBounds.getMax().y - recvBounds.getMin().y; if( !FLT_ALMOST_ZERO(boxWidth) && !FLT_ALMOST_ZERO(boxHeight) ) { float boxX = ( recvBounds.getMax().x + recvBounds.getMin().x ) * 0.5f; float boxY = ( recvBounds.getMax().y + recvBounds.getMin().y ) * 0.5f; SMatrix4x4 clipMatrix( 2.f/boxWidth, 0.f, 0.f, 0.f, 0.f, 2.f/boxHeight, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, -2.f*boxX/boxWidth, -2.f*boxY/boxHeight, 0.f, 1.f ); lightProj *= clipMatrix; } } */ G_RENDERCTX->getCamera().setProjectionMatrix( lightProj ); }