123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- /******************************************************************************
- @File PVRTMisc.cpp
- @Title PVRTMisc
- @Version
- @Copyright Copyright (C) Imagination Technologies Limited.
- @Platform ANSI compatible
- @Description Miscellaneous functions used in 3D rendering.
- ******************************************************************************/
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <limits.h>
- #include <math.h>
- #include "PVRTGlobal.h"
- #include "PVRTContext.h"
- #include "PVRTFixedPoint.h"
- #include "PVRTMatrix.h"
- #include "PVRTMisc.h"
- /*!***************************************************************************
- @Function PVRTMiscCalculateIntersectionLinePlane
- @Input pfPlane Length 4 [A,B,C,D], values for plane
- equation
- @Input pv0 A point on the line
- @Input pv1 Another point on the line
- @Output pvIntersection The point of intersection
- @Description Calculates coords of the intersection of a line and an
- infinite plane
- *****************************************************************************/
- void PVRTMiscCalculateIntersectionLinePlane(
- PVRTVECTOR3 * const pvIntersection,
- const VERTTYPE pfPlane[4],
- const PVRTVECTOR3 * const pv0,
- const PVRTVECTOR3 * const pv1)
- {
- PVRTVECTOR3 vD;
- VERTTYPE fN, fD, fT;
- /* Calculate vector from point0 to point1 */
- vD.x = pv1->x - pv0->x;
- vD.y = pv1->y - pv0->y;
- vD.z = pv1->z - pv0->z;
- /* Denominator */
- fD =
- VERTTYPEMUL(pfPlane[0], vD.x) +
- VERTTYPEMUL(pfPlane[1], vD.y) +
- VERTTYPEMUL(pfPlane[2], vD.z);
- /* Numerator */
- fN =
- VERTTYPEMUL(pfPlane[0], pv0->x) +
- VERTTYPEMUL(pfPlane[1], pv0->y) +
- VERTTYPEMUL(pfPlane[2], pv0->z) +
- pfPlane[3];
- fT = VERTTYPEDIV(-fN, fD);
- /* And for a finale, calculate the intersection coordinate */
- pvIntersection->x = pv0->x + VERTTYPEMUL(fT, vD.x);
- pvIntersection->y = pv0->y + VERTTYPEMUL(fT, vD.y);
- pvIntersection->z = pv0->z + VERTTYPEMUL(fT, vD.z);
- }
- /*!***************************************************************************
- @Function PVRTMiscCalculateInfinitePlane
- @Input nStride Size of each vertex structure containing pfVtx
- @Input pvPlane Length 4 [A,B,C,D], values for plane equation
- @Input pmViewProjInv The inverse of the View Projection matrix
- @Input pFrom Position of the camera
- @Input fFar Far clipping distance
- @Output pfVtx Position of the first of 3 floats to receive
- the position of vertex 0; up to 5 vertex positions
- will be written (5 is the maximum number of vertices
- required to draw an infinite polygon clipped to screen
- and far clip plane).
- @Returns Number of vertices in the polygon fan (Can be 0, 3, 4 or 5)
- @Description Calculates world-space coords of a screen-filling
- representation of an infinite plane The resulting vertices run
- counter-clockwise around the screen, and can be simply drawn using
- non-indexed TRIANGLEFAN
- *****************************************************************************/
- int PVRTMiscCalculateInfinitePlane(
- VERTTYPE * const pfVtx,
- const int nStride,
- const PVRTVECTOR4 * const pvPlane,
- const PVRTMATRIX * const pmViewProjInv,
- const PVRTVECTOR3 * const pFrom,
- const VERTTYPE fFar)
- {
- PVRTVECTOR3 pvWorld[5];
- PVRTVECTOR3 *pvPolyPtr;
- unsigned int dwCount;
- bool bClip;
- int nVert;
- VERTTYPE fDotProduct;
- /*
- Check whether the plane faces the camera
- */
- fDotProduct =
- VERTTYPEMUL((pFrom->x + VERTTYPEMUL(pvPlane->x, pvPlane->w)), pvPlane->x) +
- VERTTYPEMUL((pFrom->y + VERTTYPEMUL(pvPlane->y, pvPlane->w)), pvPlane->y) +
- VERTTYPEMUL((pFrom->z + VERTTYPEMUL(pvPlane->z, pvPlane->w)), pvPlane->z);
- if(fDotProduct < 0) {
- /* Camera is behind plane, hence it's not visible */
- return 0;
- }
- /*
- Back transform front clipping plane into world space,
- to give us a point on the line through each corner of the screen
- (from the camera).
- */
- /* x = -1.0f; y = -1.0f; z = 1.0f; w = 1.0f */
- pvWorld[0].x = VERTTYPEMUL((-pmViewProjInv->f[ 0] - pmViewProjInv->f[ 4] + pmViewProjInv->f[ 8] + pmViewProjInv->f[12]), fFar);
- pvWorld[0].y = VERTTYPEMUL((-pmViewProjInv->f[ 1] - pmViewProjInv->f[ 5] + pmViewProjInv->f[ 9] + pmViewProjInv->f[13]), fFar);
- pvWorld[0].z = VERTTYPEMUL((-pmViewProjInv->f[ 2] - pmViewProjInv->f[ 6] + pmViewProjInv->f[10] + pmViewProjInv->f[14]), fFar);
- /* x = 1.0f, y = -1.0f, z = 1.0f; w = 1.0f */
- pvWorld[1].x = VERTTYPEMUL(( pmViewProjInv->f[ 0] - pmViewProjInv->f[ 4] + pmViewProjInv->f[ 8] + pmViewProjInv->f[12]), fFar);
- pvWorld[1].y = VERTTYPEMUL(( pmViewProjInv->f[ 1] - pmViewProjInv->f[ 5] + pmViewProjInv->f[ 9] + pmViewProjInv->f[13]), fFar);
- pvWorld[1].z = VERTTYPEMUL(( pmViewProjInv->f[ 2] - pmViewProjInv->f[ 6] + pmViewProjInv->f[10] + pmViewProjInv->f[14]), fFar);
- /* x = 1.0f, y = 1.0f, z = 1.0f; w = 1.0f */
- pvWorld[2].x = VERTTYPEMUL(( pmViewProjInv->f[ 0] + pmViewProjInv->f[ 4] + pmViewProjInv->f[ 8] + pmViewProjInv->f[12]), fFar);
- pvWorld[2].y = VERTTYPEMUL(( pmViewProjInv->f[ 1] + pmViewProjInv->f[ 5] + pmViewProjInv->f[ 9] + pmViewProjInv->f[13]), fFar);
- pvWorld[2].z = VERTTYPEMUL(( pmViewProjInv->f[ 2] + pmViewProjInv->f[ 6] + pmViewProjInv->f[10] + pmViewProjInv->f[14]), fFar);
- /* x = -1.0f, y = 1.0f, z = 1.0f; w = 1.0f */
- pvWorld[3].x = VERTTYPEMUL((-pmViewProjInv->f[ 0] + pmViewProjInv->f[ 4] + pmViewProjInv->f[ 8] + pmViewProjInv->f[12]), fFar);
- pvWorld[3].y = VERTTYPEMUL((-pmViewProjInv->f[ 1] + pmViewProjInv->f[ 5] + pmViewProjInv->f[ 9] + pmViewProjInv->f[13]), fFar);
- pvWorld[3].z = VERTTYPEMUL((-pmViewProjInv->f[ 2] + pmViewProjInv->f[ 6] + pmViewProjInv->f[10] + pmViewProjInv->f[14]), fFar);
- /* We need to do a closed loop of the screen vertices, so copy the first vertex into the last */
- pvWorld[4] = pvWorld[0];
- /*
- Now build a pre-clipped polygon
- */
- /* Lets get ready to loop */
- dwCount = 0;
- bClip = false;
- pvPolyPtr = (PVRTVECTOR3*)pfVtx;
- nVert = 5;
- while(nVert)
- {
- nVert--;
- /*
- Check which side of the Plane this corner of the far clipping
- plane is on. [A,B,C] of plane equation is the plane normal, D is
- distance from origin; hence [pvPlane->x * -pvPlane->w,
- pvPlane->y * -pvPlane->w,
- pvPlane->z * -pvPlane->w]
- is a point on the plane
- */
- fDotProduct =
- VERTTYPEMUL((pvWorld[nVert].x + VERTTYPEMUL(pvPlane->x, pvPlane->w)), pvPlane->x) +
- VERTTYPEMUL((pvWorld[nVert].y + VERTTYPEMUL(pvPlane->y, pvPlane->w)), pvPlane->y) +
- VERTTYPEMUL((pvWorld[nVert].z + VERTTYPEMUL(pvPlane->z, pvPlane->w)), pvPlane->z);
- if(fDotProduct < 0)
- {
- /*
- Behind plane; Vertex does NOT need clipping
- */
- if(bClip == true)
- {
- /* Clipping finished */
- bClip = false;
- /*
- We've been clipping, so we need to add an additional
- point on the line to this point, where clipping was
- stopped.
- */
- PVRTMiscCalculateIntersectionLinePlane(pvPolyPtr, &pvPlane->x, &pvWorld[nVert+1], &pvWorld[nVert]);
- pvPolyPtr = (PVRTVECTOR3*)((char*)pvPolyPtr + nStride);
- dwCount++;
- }
- if(!nVert)
- {
- /* Abort, abort: we've closed the loop with the clipped point */
- break;
- }
- /* Add the current point */
- PVRTMiscCalculateIntersectionLinePlane(pvPolyPtr, &pvPlane->x, pFrom, &pvWorld[nVert]);
- pvPolyPtr = (PVRTVECTOR3*)((char*)pvPolyPtr + nStride);
- dwCount++;
- }
- else
- {
- /*
- Before plane; Vertex DOES need clipping
- */
- if(bClip == true)
- {
- /* Already in clipping, skip point */
- continue;
- }
- /* Clipping initiated */
- bClip = true;
- /* Don't bother with entry point on first vertex; will take care of it on last vertex (which is a repeat of first vertex) */
- if(nVert != 4)
- {
- /* We need to add an additional point on the line to this point, where clipping was started */
- PVRTMiscCalculateIntersectionLinePlane(pvPolyPtr, &pvPlane->x, &pvWorld[nVert+1], &pvWorld[nVert]);
- pvPolyPtr = (PVRTVECTOR3*)((char*)pvPolyPtr + nStride);
- dwCount++;
- }
- }
- }
- /* Valid vertex counts are 0, 3, 4, 5 */
- _ASSERT(dwCount <= 5);
- _ASSERT(dwCount != 1);
- _ASSERT(dwCount != 2);
- return dwCount;
- }
- /*!***************************************************************************
- @Function SetVertex
- @Modified Vertices
- @Input index
- @Input x
- @Input y
- @Input z
- @Description Writes a vertex in a vertex array
- *****************************************************************************/
- void SetVertex(VERTTYPE** Vertices, int index, VERTTYPE x, VERTTYPE y, VERTTYPE z)
- {
- (*Vertices)[index*3+0] = x;
- (*Vertices)[index*3+1] = y;
- (*Vertices)[index*3+2] = z;
- }
- /*!***************************************************************************
- @Function SetUV
- @Modified UVs
- @Input index
- @Input u
- @Input v
- @Description Writes a texture coordinate in a texture coordinate array
- *****************************************************************************/
- void SetUV(VERTTYPE** UVs, int index, VERTTYPE u, VERTTYPE v)
- {
- (*UVs)[index*2+0] = u;
- (*UVs)[index*2+1] = v;
- }
- /*!***************************************************************************
- @Function PVRTCreateSkybox
- @Input scale Scale the skybox
- @Input adjustUV Adjust or not UVs for PVRT compression
- @Input textureSize Texture size in pixels
- @Output Vertices Array of vertices
- @Output UVs Array of UVs
- @Description Creates the vertices and texture coordinates for a skybox
- *****************************************************************************/
- void PVRTCreateSkybox(float scale, bool adjustUV, int textureSize, VERTTYPE** Vertices, VERTTYPE** UVs)
- {
- *Vertices = new VERTTYPE[24*3];
- *UVs = new VERTTYPE[24*2];
- VERTTYPE unit = f2vt(1);
- VERTTYPE a0 = 0, a1 = unit;
- if (adjustUV)
- {
- VERTTYPE oneover = f2vt(1.0f / textureSize);
- a0 = VERTTYPEMUL(f2vt(4.0f), oneover);
- a1 = unit - a0;
- }
- // Front
- SetVertex(Vertices, 0, -unit, +unit, -unit);
- SetVertex(Vertices, 1, +unit, +unit, -unit);
- SetVertex(Vertices, 2, -unit, -unit, -unit);
- SetVertex(Vertices, 3, +unit, -unit, -unit);
- SetUV(UVs, 0, a0, a1);
- SetUV(UVs, 1, a1, a1);
- SetUV(UVs, 2, a0, a0);
- SetUV(UVs, 3, a1, a0);
- // Right
- SetVertex(Vertices, 4, +unit, +unit, -unit);
- SetVertex(Vertices, 5, +unit, +unit, +unit);
- SetVertex(Vertices, 6, +unit, -unit, -unit);
- SetVertex(Vertices, 7, +unit, -unit, +unit);
- SetUV(UVs, 4, a0, a1);
- SetUV(UVs, 5, a1, a1);
- SetUV(UVs, 6, a0, a0);
- SetUV(UVs, 7, a1, a0);
- // Back
- SetVertex(Vertices, 8 , +unit, +unit, +unit);
- SetVertex(Vertices, 9 , -unit, +unit, +unit);
- SetVertex(Vertices, 10, +unit, -unit, +unit);
- SetVertex(Vertices, 11, -unit, -unit, +unit);
- SetUV(UVs, 8 , a0, a1);
- SetUV(UVs, 9 , a1, a1);
- SetUV(UVs, 10, a0, a0);
- SetUV(UVs, 11, a1, a0);
- // Left
- SetVertex(Vertices, 12, -unit, +unit, +unit);
- SetVertex(Vertices, 13, -unit, +unit, -unit);
- SetVertex(Vertices, 14, -unit, -unit, +unit);
- SetVertex(Vertices, 15, -unit, -unit, -unit);
- SetUV(UVs, 12, a0, a1);
- SetUV(UVs, 13, a1, a1);
- SetUV(UVs, 14, a0, a0);
- SetUV(UVs, 15, a1, a0);
- // Top
- SetVertex(Vertices, 16, -unit, +unit, +unit);
- SetVertex(Vertices, 17, +unit, +unit, +unit);
- SetVertex(Vertices, 18, -unit, +unit, -unit);
- SetVertex(Vertices, 19, +unit, +unit, -unit);
- SetUV(UVs, 16, a0, a1);
- SetUV(UVs, 17, a1, a1);
- SetUV(UVs, 18, a0, a0);
- SetUV(UVs, 19, a1, a0);
- // Bottom
- SetVertex(Vertices, 20, -unit, -unit, -unit);
- SetVertex(Vertices, 21, +unit, -unit, -unit);
- SetVertex(Vertices, 22, -unit, -unit, +unit);
- SetVertex(Vertices, 23, +unit, -unit, +unit);
- SetUV(UVs, 20, a0, a1);
- SetUV(UVs, 21, a1, a1);
- SetUV(UVs, 22, a0, a0);
- SetUV(UVs, 23, a1, a0);
- for (int i=0; i<24*3; i++) (*Vertices)[i] = VERTTYPEMUL((*Vertices)[i], f2vt(scale));
- }
- /*!***************************************************************************
- @Function PVRTDestroySkybox
- @Input Vertices Vertices array to destroy
- @Input UVs UVs array to destroy
- @Description Destroy the memory allocated for a skybox
- *****************************************************************************/
- void PVRTDestroySkybox(VERTTYPE* Vertices, VERTTYPE* UVs)
- {
- delete [] Vertices;
- delete [] UVs;
- }
- /*!***************************************************************************
- @Function GetPOTHigher
- @Input uiOriginalValue Base value
- @Input iTimesHigher Multiplier
- @Description When iTimesHigher is one, this function will return the closest
- power-of-two value above the base value.
- For every increment beyond one for the iTimesHigher value,
- the next highest power-of-two value will be calculated.
- *****************************************************************************/
- unsigned int GetPOTHigher(unsigned int uiOriginalValue, int iTimesHigher)
- {
- if(uiOriginalValue == 0 || iTimesHigher < 0)
- {
- return 0;
- }
- unsigned int uiSize = 1;
- while (uiSize < uiOriginalValue) uiSize *= 2;
- // Keep increasing the POT value until the iTimesHigher value has been met
- for(int i = 1 ; i < iTimesHigher; ++i)
- {
- uiSize *= 2;
- }
- return uiSize;
- }
- /*!***************************************************************************
- @Function GetPOTLower
- @Input uiOriginalValue Base value
- @Input iTimesLower Multiplier
- @Description When iTimesLower is one, this function will return the closest
- power-of-two value below the base value.
- For every increment beyond one for the iTimesLower value,
- the next lowest power-of-two value will be calculated. The lowest
- value that can be reached is 1.
- *****************************************************************************/
- // NOTE: This function should be optimised
- unsigned int GetPOTLower(unsigned int uiOriginalValue, int iTimesLower)
- {
- if(uiOriginalValue == 0 || iTimesLower < 0)
- {
- return 0;
- }
- unsigned int uiSize = GetPOTHigher(uiOriginalValue,1);
- uiSize >>= 1;//uiSize /=2;
- for(int i = 1; i < iTimesLower; ++i)
- {
- uiSize >>= 1;//uiSize /=2;
- if(uiSize == 1)
- {
- // Lowest possible value has been reached, so break
- break;
- }
- }
- return uiSize;
- }
- /*****************************************************************************
- End of file (PVRTMisc.cpp)
- *****************************************************************************/
|