2024-12-19 23:18:21 +01:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2010 su44
|
|
|
|
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
OpenMoHAA source code 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
// tr_sprite.c - MoHAA sprite system
|
|
|
|
|
|
|
|
#include "tr_local.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
=====================
|
|
|
|
SPR_RegisterSprite
|
|
|
|
=====================
|
|
|
|
*/
|
|
|
|
sprite_t *SPR_RegisterSprite(const char *name)
|
|
|
|
{
|
|
|
|
image_t *spriteImage;
|
|
|
|
shader_t *shader;
|
|
|
|
sprite_t *spr;
|
|
|
|
char shadername[256];
|
|
|
|
COM_StripExtension(name,shadername,sizeof(shadername));
|
|
|
|
shader = R_FindShader(shadername,-1,qfalse);
|
|
|
|
if(shader) {
|
|
|
|
spriteImage = 0;
|
|
|
|
if(shader->stages[0])
|
|
|
|
spriteImage = shader->stages[0]->bundle[0].image[0];
|
|
|
|
if ( !spriteImage ) {
|
|
|
|
ri.Printf(1, "Could not find image for sprite in shader %s\n", name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
spr = ri.Hunk_Alloc(sizeof(sprite_t), h_dontcare);
|
|
|
|
spr->height = spriteImage->height;
|
|
|
|
spr->width = spriteImage->width;
|
|
|
|
spr->origin_x = spr->width * 0.5;
|
|
|
|
spr->origin_y = spr->height * 0.5;
|
|
|
|
spr->shader = shader;
|
|
|
|
spr->scale = spr->shader->sprite.scale;
|
|
|
|
return spr;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int CullSprite(const vec3_t* points) {
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < backEnd.viewParms.fog.extrafrustums + 4; i++) {
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
if (DotProduct(points[j], backEnd.viewParms.frustum[i].normal) - backEnd.viewParms.frustum[i].dist > 0.0f) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == 4) {
|
|
|
|
return CULL_CLIP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CULL_IN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=====================
|
|
|
|
RB_DrawSprite
|
|
|
|
=====================
|
|
|
|
*/
|
|
|
|
void RB_DrawSprite( const refSprite_t *spr ) {
|
|
|
|
model_t* model;
|
|
|
|
vec3_t norm;
|
|
|
|
vec3_t up, right;
|
|
|
|
vec3_t points[4];
|
|
|
|
float org_x, org_y;
|
|
|
|
float scale;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!spr->hModel)
|
|
|
|
{
|
|
|
|
ri.Printf(PRINT_WARNING, "No model found for Sprite\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
model = tr.models;
|
|
|
|
if (spr->hModel > 0 && spr->hModel < tr.numModels) {
|
2024-12-21 21:43:42 +01:00
|
|
|
model = tr.models[spr->hModel];
|
2024-12-19 23:18:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
scale = spr->scale * model->d.sprite->scale;
|
|
|
|
|
|
|
|
switch (model->d.sprite->shader->sprite.type)
|
|
|
|
{
|
|
|
|
case SPRITE_PARALLEL_ORIENTED:
|
|
|
|
{
|
|
|
|
float invmag;
|
|
|
|
float cr, sr;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
invmag = 1.0 / sqrt(spr->axis[1][2] * spr->axis[1][2] + spr->axis[1][1] * spr->axis[1][1]);
|
|
|
|
|
|
|
|
cr = invmag * spr->axis[1][1];
|
|
|
|
sr = invmag * spr->axis[1][2];
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
up[i] = backEnd.viewParms.or.axis[2][i] * cr - backEnd.viewParms.or.axis[1][i] * sr;
|
|
|
|
right[i] = backEnd.viewParms.or.axis[1][i] * cr + backEnd.viewParms.or.axis[2][i] * sr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SPRITE_PARALLEL:
|
|
|
|
VectorCopy(backEnd.viewParms.or.axis[2], up);
|
|
|
|
if (!backEnd.viewParms.isMirror) {
|
|
|
|
VectorNegate(backEnd.viewParms.or.axis[1], right);
|
|
|
|
} else {
|
|
|
|
VectorCopy(backEnd.viewParms.or.axis[1], right);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SPRITE_ORIENTED:
|
|
|
|
VectorCopy(spr->axis[1], right);
|
|
|
|
VectorCopy(spr->axis[2], up);
|
|
|
|
break;
|
|
|
|
case SPRITE_PARALLEL_UPRIGHT:
|
|
|
|
VectorCopy(backEnd.viewParms.or.axis[0], norm);
|
|
|
|
VectorCopy(backEnd.viewParms.or.axis[1], right);
|
|
|
|
VectorCopy(backEnd.viewParms.or.axis[2], up);
|
|
|
|
if (backEnd.viewParms.or.axis[0][2] > 0.999) {
|
|
|
|
return;
|
|
|
|
} else if (backEnd.viewParms.or.axis[0][2] < -0.999) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorSet(up, 0.0f, 0.0f, 1.0f);
|
|
|
|
VectorSet(right, backEnd.viewParms.or.axis[0][1], -backEnd.viewParms.or.axis[0][0], 0.0f);
|
|
|
|
VectorNormalize(right);
|
|
|
|
VectorSet(norm, -right[1], right[0], 0.0f);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
org_x = model->d.sprite->origin_x * scale;
|
|
|
|
org_y = model->d.sprite->origin_y * scale;
|
|
|
|
|
|
|
|
VectorScale(up, org_y, up);
|
|
|
|
VectorScale(right, org_x, right);
|
|
|
|
|
|
|
|
points[0][0] = spr->origin[0] + up[0] - right[0];
|
|
|
|
points[1][0] = spr->origin[0] + up[0] + right[0];
|
|
|
|
points[2][0] = spr->origin[0] - up[0] - right[0];
|
|
|
|
points[3][0] = spr->origin[0] - up[0] + right[0];
|
|
|
|
|
|
|
|
points[0][1] = spr->origin[1] + up[1] - right[1];
|
|
|
|
points[1][1] = spr->origin[1] + up[1] + right[1];
|
|
|
|
points[2][1] = spr->origin[1] - up[1] - right[1];
|
|
|
|
points[3][1] = spr->origin[1] - up[1] + right[1];
|
|
|
|
|
|
|
|
points[0][2] = spr->origin[2] + up[2] - right[2];
|
|
|
|
points[1][2] = spr->origin[2] + up[2] + right[2];
|
|
|
|
points[2][2] = spr->origin[2] - up[2] - right[2];
|
|
|
|
points[3][2] = spr->origin[2] - up[2] + right[2];
|
|
|
|
|
|
|
|
if (CullSprite(points) == CULL_OUT) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
RB_CHECKOVERFLOW(4, 6);
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
tess.color[tess.numVertexes + i][0] = spr->shaderRGBA[0] * 0xffff / 0xff;
|
|
|
|
tess.color[tess.numVertexes + i][1] = spr->shaderRGBA[1] * 0xffff / 0xff;
|
|
|
|
tess.color[tess.numVertexes + i][2] = spr->shaderRGBA[2] * 0xffff / 0xff;
|
|
|
|
tess.color[tess.numVertexes + i][3] = spr->shaderRGBA[3] * 0xffff / 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
tess.texCoords[tess.numVertexes][0] = 0.0f;
|
|
|
|
tess.texCoords[tess.numVertexes][1] = 0.0f;
|
|
|
|
tess.texCoords[tess.numVertexes + 1][0] = 1.0f;
|
|
|
|
tess.texCoords[tess.numVertexes + 1][1] = 0.0f;
|
|
|
|
tess.texCoords[tess.numVertexes + 2][0] = 0.0f;
|
|
|
|
tess.texCoords[tess.numVertexes + 2][1] = 1.0f;
|
|
|
|
tess.texCoords[tess.numVertexes + 3][0] = 1.0f;
|
|
|
|
tess.texCoords[tess.numVertexes + 3][1] = 1.0f;
|
|
|
|
|
|
|
|
tess.xyz[tess.numVertexes][0] = points[0][0];
|
|
|
|
tess.xyz[tess.numVertexes][1] = points[0][1];
|
|
|
|
tess.xyz[tess.numVertexes][2] = points[0][2];
|
|
|
|
tess.xyz[tess.numVertexes + 1][0] = points[1][0];
|
|
|
|
tess.xyz[tess.numVertexes + 1][1] = points[1][1];
|
|
|
|
tess.xyz[tess.numVertexes + 1][2] = points[1][2];
|
|
|
|
tess.xyz[tess.numVertexes + 2][0] = points[2][0];
|
|
|
|
tess.xyz[tess.numVertexes + 2][1] = points[2][1];
|
|
|
|
tess.xyz[tess.numVertexes + 2][2] = points[2][2];
|
|
|
|
tess.xyz[tess.numVertexes + 3][0] = points[3][0];
|
|
|
|
tess.xyz[tess.numVertexes + 3][1] = points[3][1];
|
|
|
|
tess.xyz[tess.numVertexes + 3][2] = points[3][2];
|
|
|
|
|
|
|
|
tess.indexes[tess.numIndexes] = tess.numVertexes + 2;
|
|
|
|
tess.indexes[tess.numIndexes + 1] = tess.numVertexes + 1;
|
|
|
|
tess.indexes[tess.numIndexes + 2] = tess.numVertexes;
|
|
|
|
tess.indexes[tess.numIndexes + 3] = tess.numVertexes + 2;
|
|
|
|
tess.indexes[tess.numIndexes + 4] = tess.numVertexes + 3;
|
|
|
|
tess.indexes[tess.numIndexes + 5] = tess.numVertexes + 1;
|
|
|
|
|
|
|
|
tess.numVertexes += 4;
|
|
|
|
tess.numIndexes += 6;
|
|
|
|
}
|