I reworked my old Frustum code for the terrain engine project.
This code is much faster than Microsoft's method.
They calculate the frustum vertices, then use them to obtain planes.
This version extracts planes directly from the combined view/proj matrix.
You can obtain planes AND/OR vertices with this version, depending apon your project's requirements.

If you can see any way to further optimize this code please tell me !!

``;The following code is used to extract the "view frustum";from the current view and proj matrices;;UpdateFrustum is your common entrypoint procedure;Its parameters are:;bWantVertices - Want the frustum bounding vertices? True or False;bWantPlanes - Want the frustum bounding planes? True or False;pmatView - Pointer to the current View matrix;pmatProj - Pointer to the current Projection matrix;pOutputVertices - Pointer to 8 x Vec3 output;pOutputPlanes - Pointer to 6 x Plane output (see Frustum struct);;We describe a Plane with a Normal and DistancePlane struct   vNormal Vec3 <>   fDistance REAL4 ?Plane ends; We describe a Frustum as SIX PLANESFrustum struct	plLeft		Plane <>	plRight		Plane <>	plTop		Plane <>	plBottom	Plane <>	plNear		Plane <>	plFar		Plane <>Frustum ends;Just some helper macros for simple vector mathvecadd macro pvout:req, pv1in:req, pv2in:req	fld  pv1in	fadd pv2in	fstp pvoutendmvecsub macro pvout:req, pv1in:req, pv2in:req	fld  pv1in	fsub pv2in	fstp pvoutendmvecmul macro pvout:req, pv1in:req, pv2in:req	fld  pv1in	fmul pv2in	fstp pvoutendm.data;This describes a UNIT CUBE which we will;deform to calculate frustum corner vertices	FrustumUn	Vec3 <-1.0f, -1.0f,  0.0f>				Vec3 < 1.0f, -1.0f,  0.0f>				Vec3 <-1.0f,  1.0f,  0.0f>				Vec3 < 1.0f,  1.0f,  0.0f>				Vec3 <-1.0f, -1.0f,  1.0f>				Vec3 < 1.0f, -1.0f,  1.0f>				Vec3 <-1.0f,  1.0f,  1.0f>				Vec3 < 1.0f,  1.0f,  1.0f>.codeVec3Normalize proc uses esi,pVecLOCAL fdenom	mov esi,pVec	assume esi:ptr Vec3		;Calculate denominator	fld1	fld  .X	fmul .X	fld  .Y	fmul .Y	fld  .Z	fmul .Z	fadd	fadd	fdiv	fstp fdenom	;Multiply vector components by denom	vecmul .X, .X, fdenom	vecmul .Y, .Y, fdenom	vecmul .Z, .Z, fdenom		assume esi:nothing	retVec3Normalize endp;This procedure extracts the PLANES of the view frustum;from the current Projection and View matricesExtractFrustumPlanesFromView proc uses edi esi, pmatComb, pFrustPlanesmov edi,pFrustPlanesmov esi,pmatCombassume edi:ptr Frustumassume esi:ptr D3DXMATRIX;Get Left clipping planevecadd .plLeft.vNormal.X, .m03, .m00vecadd .plLeft.vNormal.Y, .m13, .m10vecadd .plLeft.vNormal.Z, .m23, .m20vecadd .plLeft.fDistance, .m33, .m30;Get Right clipping plane vecsub .plRight.vNormal.X, .m03, .m00vecsub .plRight.vNormal.Y, .m13, .m10vecsub .plRight.vNormal.Z, .m23, .m20vecsub .plRight.fDistance, .m33, .m30;Get Top clipping plane vecsub .plTop.vNormal.X, .m03, .m01vecsub .plTop.vNormal.Y, .m13, .m11vecsub .plTop.vNormal.Z, .m23, .m21vecsub .plTop.fDistance, .m33, .m31;Get Bottom clipping plane vecadd .plBottom.vNormal.X, .m03, .m01vecadd .plBottom.vNormal.Y, .m13, .m11vecadd .plBottom.vNormal.Z, .m23, .m21vecadd .plBottom.fDistance, .m33, .m31;Get Near clipping plane m2m .plNear.vNormal.X, .m02m2m .plNear.vNormal.Y, .m12m2m .plNear.vNormal.Z, .m22m2m .plNear.fDistance, .m32;Get Far clipping plane vecsub .plFar.vNormal.X, .m03, .m02vecsub .plFar.vNormal.Y, .m13, .m12vecsub .plFar.vNormal.Z, .m23, .m22vecsub .plFar.fDistance, .m33, .m32;Normalize plane normalsinvoke Vec3Normalize, addr .plLeft.vNormalinvoke Vec3Normalize, addr .plRight.vNormalinvoke Vec3Normalize, addr .plTop.vNormalinvoke Vec3Normalize, addr .plBottom.vNormalinvoke Vec3Normalize, addr .plNear.vNormalinvoke Vec3Normalize, addr .plFar.vNormalassume edi:nothingassume esi:nothingretExtractFrustumPlanesFromView endp;This procedure extracts the BOUNDING VERTICES of the view frustrum;by deforming a Unit Cube with the Inverse of the Combined View and Proj matricesExtractFrustumVerticesFromView proc uses esi edi ecx,pInverseComb,pOutputVertices	;Transform the untransformed boundingbox of the Frustrum 	;by the inverse view/projection	xor ecx,ecx	lea esi,FrustumUn	mov edi,pOutputVertices	.while ecx<8		push ecx		invoke D3DXVec3TransformCoord, edi,esi, pInverseComb		add esi,sizeof Vec3		add edi,sizeof Vec3		pop ecx		inc ecx	.endw	retExtractFrustumVerticesFromView endpUpdateFrustum proc bWantVertices,bWantPlanes, pmatView,pmatProj,pOutputVertices, pOutputPlanesLOCAL matComb:D3DXMATRIXLOCAL imatComb:D3DXMATRIX	;Calculate the combined projection/view matrix	invoke D3DXMatrixMultiply,addr matComb, pmatView, pmatProj	.if bWantVertices==TRUE		;In order to deform the unit cube for obtaining frustum vertices,		;we need the INVERSE of the aforementioned combined matrix		invoke D3DXMatrixInverse, addr imatComb,NULL, addr matComb		invoke ExtractFrustumVerticesFromView,addr imatComb,pOutputVertices	.endif	.if bWantPlanes==TRUE		invoke ExtractFrustumPlanesFromView,addr matComb, pOutputPlanes	.endif		retUpdateFrustum endp``

Posted on 2006-01-06 22:31:34 by Homer
Nice code.
Using the FPU there's really no hope for optimization :D

I rewrote one of the functions using SIMD instructions. I noticed that if you rotate the matrix data you can make the job extremely parallel.

``;;SSE2 then SSE3 for the normalize codeExtractFrustumPlanesFromView:;;ebp+16 = pmatComb;;ebp+20 = pFrustPlanes;;trash all xmm0-6 wOOt! for xmm7;;ASSUMING edi's address is 16byte alignedpush ebppush esipush edimov ebp,espmov esi,mov edi,sub esp,16and esp,0FFFFFFF0h ;; 16byte align the stack;;make a copy of the matrix rotated 90degrees for sse;;16 pushespush  ;;col 0push push push       push  ;;col 1push push push push  ;;col 2push push push push  ;;col 3push push push ;;|esp col3 col2 col1 col0|movdqa xmm3,;;col 3movdqa xmm2,;;col 2movdqa xmm1,;;col 1movdqa xmm0,;;col 0;;calc and store left and right clip planesmovdqa xmm4,xmm3movdqa xmm5,xmm3movdqa xmm6,xmm0addps xmm4,xmm6subps xmm5,xmm6;;if edi is 16byte aligned use dqA insteadmovdqa ,xmm4movdqa ,xmm5;;calc and store top and bottommovdqa xmm4,xmm3movdqa xmm5,xmm3movdqa xmm6,xmm1subps xmm4,xmm6addps xmm4,xmm6movdqa ,xmm4movdqa ,xmm5;;near and farmovdqa ,xmm2;;nearsubps xmm3,xmm2movdqa ,xmm3;;;NORMALIZING time;;;SSE3 haddps and movsldup will be usedmovdqa xmm6,;;data to mask out dist;;normals for right left and topLABEL1: ;;for lazinessmovdqa xmm0,movdqa xmm1,movdqa xmm2,andps xmm0,xmm6 ;;no more dstandps xmm1,xmm6andps xmm2,xmm6movdqa xmm3,xmm0 ;;copymovdqa xmm4,xmm1movdqa xmm5,xmm2mulps xmm0,xmm0 ;;x^2 y^2 z^2mulps xmm1,xmm1mulps xmm2,xmm2haddps xmm0,xmm0 ;;x^2+y^2+z^2haddps xmm1,xmm1haddps xmm2,xmm2haddps xmm0,xmm0haddps xmm1,xmm1haddps xmm2,xmm2rsqrtss xmm0,xmm0 ;;1/sqrtrsqrtss xmm1,xmm1rsqrtss xmm2,xmm2movsldup xmm0,xmm0 ;;1/sqrt 1/sqrt 1/sqrt 1/sqrtmovsldup xmm1,xmm1movsldup xmm2,xmm2movlhps xmm0,xmm0movlhps xmm1,xmm1movlhps xmm2,xmm2mulps xmm3,xmm0 ;;normalizemulps xmm4,xmm1mulps xmm5,xmm2mov eax, ;; save distsmov ecx,mov edx,movdqa ,xmm3movdqa ,xmm4movdqa ,xmm5mov ,eaxmov ,ecxmov ,edx;;NORMALIZE bottom near and far planes;;I'm not redoing all these indexes into edi;;Time for a hack job!add esp,1 ;;I aligned it beforeadd edi,48test esp,1jnz LABEL1mov esp,ebppop edipop esipop ebpret 8;;dataalign 16NoDist dd -1,-1,-1,0``

sorry for the total lack of formating I wrote it in notepad (current time 4:47AM)
at least there's a few comments
Posted on 2006-01-07 03:47:45 by r22