diff options
Diffstat (limited to 'src/video/trail_geometry.c')
-rw-r--r-- | src/video/trail_geometry.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/src/video/trail_geometry.c b/src/video/trail_geometry.c new file mode 100644 index 0000000..c045822 --- /dev/null +++ b/src/video/trail_geometry.c @@ -0,0 +1,235 @@ +#include "video/trail_geometry.h" + +#include <math.h> + +enum { + COLOR_TRAIL, COLOR_BRIGHT, COLOR_CYCLE +}; + +int cmpdir(segment2 *line1, segment2 *line2); + +void float2ubyte(unsigned char* pubColor, float *pfColor) { + pubColor[0] = (unsigned char)(pfColor[0] * 255.0f); + pubColor[1] = (unsigned char)(pfColor[1] * 255.0f); + pubColor[2] = (unsigned char)(pfColor[2] * 255.0f); + pubColor[3] = (unsigned char)(pfColor[3] * 255.0f); +} + +void storeColor(TrailMesh *pMesh, int offset, PlayerVisual *pV, int type) { + float color[] = { 0, 0, 0, 1 }; + float white[] = { 1, 1, 1, 1 }; + + switch(type) { + case COLOR_TRAIL: + if(gSettingsCache.alpha_trails) + memcpy(color, pV->pColorAlpha, 4 * sizeof(float)); + else + memcpy(color, pV->pColorAlpha, 3 * sizeof(float)); + break; + case COLOR_BRIGHT: + memcpy(color, white, 3 * sizeof(float)); + break; + case COLOR_CYCLE: + memcpy(color, pV->pColorDiffuse, 3 * sizeof(float)); + break; + } + float2ubyte(pMesh->pColors + 4 * offset, color); + float2ubyte(pMesh->pColors + 4 * (offset + 1), color); +} + +void storeVertex(TrailMesh *pMesh, int offset, + segment2 *s, float t, /* 0: start, 1: end */ + float fFloor, float fTop, + float fSegLength, float fTotalLength) { + vec3 *pVertices = pMesh->pVertices + offset; + vec3 *pNormals = pMesh->pNormals + offset; + vec2 *pTexCoords = pMesh->pTexCoords + offset; + vec3 v; + vec2 uv; + float fUStart; + vec3 pvNormals[] = { + { { 1, 0, 0 } }, + { { -1, 0, 0 } }, + { { 0, 1, 0 } }, + { { 0, -1, 0 } } + }; + + + int iNormal; + if(s->vDirection.v[0] == 0) + // iNormal = (line->sx <= line->ex) ? 0 : 1; + iNormal = 0; + else + // iNormal = (line->sy <= line->sy) ? 2 : 3; + iNormal = 2; + + fUStart = (fTotalLength / DECAL_WIDTH) - floorf(fTotalLength / DECAL_WIDTH); + + v.v[0] = s->vStart.v[0] + t * s->vDirection.v[0]; + v.v[1] = s->vStart.v[1] + t * s->vDirection.v[1]; + v.v[2] = fFloor; + uv.v[0] = fUStart + t * fSegLength / DECAL_WIDTH; + + uv.v[1] = 0; + vec3Copy(pVertices, &v); + vec3Copy(pNormals, pvNormals + iNormal); + vec2Copy(pTexCoords, &uv); + + v.v[2] = fTop; + uv.v[1] = 1; + vec3Copy(pVertices + 1, &v); + vec3Copy(pNormals + 1, pvNormals + iNormal); + vec2Copy(pTexCoords + 1, &uv); +} + +void storeIndices(TrailMesh *pMesh, int indexOffset, int vertexOffset) { + unsigned short ppBase[2][6] = { + { 0, 2, 1, 2, 3, 1 }, + { 0, 1, 2, 1, 3, 2 } + }; + int i; + int winding; + + if(pMesh->pVertices[vertexOffset].v[0] == + pMesh->pVertices[vertexOffset + 2].v[0]) + winding = (pMesh->pVertices[vertexOffset].v[1] <= + pMesh->pVertices[vertexOffset + 2].v[1]) ? 0 : 1; + else + winding = (pMesh->pVertices[vertexOffset].v[0] < + pMesh->pVertices[vertexOffset + 2].v[0]) ? 1 : 0; + + for(i = 0; i < 6; i++) { + pMesh->pIndices[i + indexOffset] = ppBase[winding][i] + vertexOffset; + } +} + +int cmpdir(segment2 *s1, segment2 *s2) { + if((s1->vDirection.v[0] == 0 && s2->vDirection.v[0] == 0) || + (s1->vDirection.v[1] == 0 && s2->vDirection.v[1] == 0)) + return 0; + return 1; +} + +void trailGeometry(Player *pPlayer, PlayerVisual* pV, + TrailMesh *pMesh, + int *pvOffset, int *piOffset) { + Data *pData = pPlayer->data; + int curVertex = *pvOffset, curIndex = *piOffset; + int i; + float fTotalLength = 0; + float fSegLength; + for(i = 0; i < pData->trailOffset; i++) { + fSegLength = segment2_Length(pData->trails + i); + if(i == 0 || cmpdir(pData->trails + i - 1, pData->trails + i)) { + storeVertex(pMesh, curVertex, pData->trails + i, 0, + 0, pData->trail_height, + fSegLength, fTotalLength); + storeColor(pMesh, curVertex, pV, COLOR_TRAIL); + curVertex += 2; + } + + storeVertex(pMesh, curVertex, pData->trails + i, 1, + 0, pData->trail_height, + fSegLength, fTotalLength); + storeColor(pMesh, curVertex, pV, COLOR_TRAIL); + curVertex += 2; + + storeIndices(pMesh, curIndex, curVertex - 4); + curIndex += 6; + + fTotalLength += fSegLength; + + } + { + segment2 s; + vec2Copy(&s.vStart, & pData->trails[pData->trailOffset].vStart); + s.vDirection.v[0] = getSegmentEndX( pData, 1 ) - s.vStart.v[0]; + s.vDirection.v[1] = getSegmentEndY( pData, 1 ) - s.vStart.v[1]; + + fSegLength = segment2_Length(&s); + + storeVertex(pMesh, curVertex, &s, 0, + 0, pData->trail_height, + fSegLength, fTotalLength); + storeColor(pMesh, curVertex, pV, COLOR_TRAIL); + curVertex += 2; + + storeVertex(pMesh, curVertex, &s, 1, + 0, pData->trail_height, + fSegLength, fTotalLength); + storeColor(pMesh, curVertex, pV, COLOR_TRAIL); + curVertex += 2; + + storeIndices(pMesh, curIndex, curVertex - 4); + curIndex += 6; + + fTotalLength += fSegLength; + + vec2Add(&s.vStart, &s.vStart, &s.vDirection); + s.vDirection.v[0] = getSegmentEndX( pData, 0 ) - s.vStart.v[0]; + s.vDirection.v[1] = getSegmentEndY( pData, 0 ) - s.vStart.v[1]; + fSegLength = segment2_Length(&s); + + storeVertex(pMesh, curVertex, &s, 0, + 0, pData->trail_height, + fSegLength, fTotalLength); + storeColor(pMesh, curVertex, pV, COLOR_TRAIL); + curVertex += 2; + + storeVertex(pMesh, curVertex, &s, 1, + 0, pData->trail_height, + fSegLength, fTotalLength); + storeColor(pMesh, curVertex, pV, COLOR_BRIGHT); + curVertex += 2; + + storeIndices(pMesh, curIndex, curVertex - 4); + curIndex += 6; + } + + pMesh->iUsed += curIndex - *piOffset; + *piOffset = curIndex; + *pvOffset = curVertex; +} + +void bowGeometry(Player *pPlayer, PlayerVisual *pV, + TrailMesh *pMesh, int *pvOffset, int *piOffset) { + Data *pData = pPlayer->data; + segment2 s; + int bdist = PLAYER_IS_ACTIVE(pPlayer) ? 2 : 3; + int i; + int vOffset = *pvOffset; int iOffset = *piOffset; + + s.vStart.v[0] = getSegmentEndX( pData, 0 ); + s.vStart.v[1] = getSegmentEndY( pData, 0 ); + s.vDirection.v[0] = getSegmentEndX( pData, bdist ) - s.vStart.v[0]; + s.vDirection.v[1] = getSegmentEndY( pData, bdist ) - s.vStart.v[1]; + + for(i = 0; i < 10; i++) { + float t = i * 1.0f / 10; + float fTop = sqrtf(1 - t*t); + float fFloor = (t < 0.6f) ? 0 : 0.5f * (t - 0.6f); + if(fTop < 0.3f) fTop = 0.3f; + + storeVertex(pMesh, vOffset, &s, t, + fFloor * pPlayer->data->trail_height, + fTop * pPlayer->data->trail_height, + DECAL_WIDTH, 0); + storeColor(pMesh, vOffset, pV, COLOR_BRIGHT); + vOffset += 2; + if(i) { + storeIndices(pMesh, iOffset, vOffset - 4); + iOffset += 6; + } + } + storeVertex(pMesh, vOffset, &s, 1, + 0.2f * pData->trail_height, 0.3f * pData->trail_height, + DECAL_WIDTH, 0); + storeColor(pMesh, vOffset, pV, COLOR_CYCLE); + vOffset += 2; + storeIndices(pMesh, iOffset, vOffset - 4); + + pMesh->iUsed += iOffset - *piOffset; + *piOffset = iOffset; + *pvOffset = vOffset; +} + |