MacGLide/MacGLide/glide2x/sst1/glide/src/gsplash.c

1005 lines
29 KiB
C

/*
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
**
** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
** THE UNITED STATES.
**
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
**
** $Header: /cvsroot/macglide/MacGLide/glide2x/sst1/glide/src/gsplash.c,v 1.6 2006/05/18 20:50:17 jens-olaf Exp $
** $Log: gsplash.c,v $
** Revision 1.6 2006/05/18 20:50:17 jens-olaf
** No subtexturing/gapfix in splash anim
**
** Revision 1.5 2005/11/05 14:50:49 jens-olaf
** Fixed endian-issues in grLfbWriteRegion() (fixes the menu backgrunds in Carmageddon 2)
**
** Revision 1.4 2005/08/17 20:16:57 jens-olaf
** Fixed color of "3dfx" texture
**
** Revision 1.3 2005/07/14 18:54:34 jens-olaf
** Fixed clearing the screen after the last frame
**
** Revision 1.2 2005/07/11 18:59:44 jens-olaf
** Fixed buffer swap interval, added clear buffer command at the end of the animation because the last frame was displayed during game load
**
** Revision 1.1 2005/07/09 21:28:54 jens-olaf
** Added splash screen and shameless plug
**
** Revision 1.1.1.1 1999/12/07 21:48:52 joseph
** Initial checkin into SourceForge.
**
*
* 14 12/19/97 8:09a Peter
* fog table propogation
*
* 13 7/07/97 3:05p Dow
* Moved fouled clears
*
* 12 3/18/97 9:07p Dow
* Got rid of #$#%#$ // comments
*
* 11 3/16/97 12:42a Jdt
* Removed watcom warning
*
* 10 3/13/97 10:53p Jdt
* Rewrote with simple optimizations. Changed prototype for
* multi-resolution, and running as a better shameless plug.
*
* 9 3/13/97 2:52a Jdt
* Added arguments to splash.
*
* 8 3/09/97 10:31a Dow
* Added GR_DIENTRY for di glide functions
*
* 7 3/01/97 6:24p Jdt
* Made splash force yorigin.
*
* 6 1/02/97 1:06p Dow
* Fixed state bug
*
* 3 11/17/96 11:16p Garymct
* Updated grSplash code to set all of the necessary state itself rather
* than expecting the caller to do so.
*/
/*
#include <3dfx.h>
#define FX_DLL_DEFINITION
#include <fxdll.h>
#include <glide.h>
#include "fxglide.h"
*/
#include "fxinline.h"
// OpenGLide specific
#include "../../../driversrc_defines.h"
#include "Glide.h"
#include <math.h>
/*-----------------------------
Constants
-----------------------------*/
#define MAX_NUM_VERTS 2556
#define FADEIN_END_PERCENT ( 0.3f )
#define FADEOUT_BEGIN_PERCENT ( 0.8f )
#define SPIN_FRAMES 25
#define SPIN_START 26
#define NO_TABLE ((GrTexTable_t)(~0))
/*-----------------------------
Macros
-----------------------------*/
#define SNAP_BIAS ((float)(3<<18))
#define SNAP_COORD(X) ((X)+SNAP_BIAS)
/*-----------------------------
Types
-----------------------------*/
typedef struct {
float x, y, z; /* object space coordinates */
float nx, ny, nz; /* object space vertex normal for lighting */
float s, t; /* pre-glide-ified texture coordinates */
} Vert;
typedef struct {
int v[3]; /* vertex indices into array of vertes for face */
int mat_index; /* material index */
int aa_edge_flags;
} Face;
typedef float Vector[3];
typedef float Matrix[16];
// typedef FxU32 Palette[256];
typedef struct {
FxU8 yRGB[16];
FxI16 iRGB[4][3];
FxI16 qRGB[4][3];
FxU32 packed_data[12];
} NCCTable;
typedef union {
// Palette palette;
FxU32 palette[256];
NCCTable nccTable;
} TextureTable;
/*-----------------------------
Globals
-----------------------------*/
/* xScale, xOffset, yScale, yOffset */
static float viewPort[4] = {
480.0f, 320.0f,
480.0f, 240.0f
};
typedef struct {
GrTexInfo info;
FxU32 addr;
GrTexTable_t tableType;
TextureTable tableData;
} Texture;
static int do_phong = 0;
static int pass;
static int fog;
static int useTextures;
static Vector light = { -0.57735f, -0.57735f, -0.57735f };
static Vector transformed_verts[MAX_NUM_VERTS];
static Vector transformed_norms[MAX_NUM_VERTS];
#include "splshdat.inc"
static Texture textImage;
static Texture hiliteImage;
static Texture shadowImage;
static FxU32 nextFreeBase;
/*-----------------------------
Privates
-----------------------------*/
static void sourceTexture( Texture *texture ) {
static Texture *lastTexture;
if ( texture != lastTexture && useTextures ) {
grTexSource( GR_TMU0,
texture->addr,
GR_MIPMAPLEVELMASK_BOTH,
&texture->info );
if ( texture->tableType != NO_TABLE ) {
grTexDownloadTable( GR_TMU0,
texture->tableType,
&texture->tableData );
}
lastTexture = texture;
}
}
static GrTexTable_t texTableType( GrTextureFormat_t format ) {
GrTexTable_t rv = (GrTexTable_t)NO_TABLE;
switch( format ) {
case GR_TEXFMT_YIQ_422:
case GR_TEXFMT_AYIQ_8422:
rv = GR_TEXTABLE_NCC0;
break;
case GR_TEXFMT_P_8:
case GR_TEXFMT_AP_88:
rv = GR_TEXTABLE_PALETTE;
break;
}
return rv;
}
static void downloadTexture( Texture *texture, Gu3dfInfo *info ) {
texture->info.data = info->data;
texture->info.smallLod = info->header.small_lod;
texture->info.largeLod = info->header.large_lod;
texture->info.aspectRatio = info->header.aspect_ratio;
texture->info.format = info->header.format;
texture->addr = nextFreeBase;
nextFreeBase += grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH,
&texture->info );
grTexDownloadMipMap( GR_TMU0,
texture->addr,
GR_MIPMAPLEVELMASK_BOTH,
&texture->info );
texture->tableType = texTableType( info->header.format );
switch( texture->tableType ) {
case GR_TEXTABLE_NCC0:
case GR_TEXTABLE_NCC1:
case GR_TEXTABLE_PALETTE:
texture->tableData = *(TextureTable*)(&info->table);
break;
default:
break;
}
return;
}
#ifdef OPENGLIDE_HOST_MAC
void ConvertGu3dfInfoLSB2MSB(Gu3dfInfo* gu3dinfo)
{
// Swap endianess fro LSB to MSB:
// Less optimal than supplying the correct data,
// but on the other hand it works with the original splash.inc
if (gu3dinfo->header.width > 0xffff)
{
// Convert the first time only...
swaplong(&gu3dinfo->header.width);
swaplong(&gu3dinfo->header.height);
swaplong(&gu3dinfo->header.small_lod);
swaplong(&gu3dinfo->header.large_lod);
swaplong(&gu3dinfo->header.aspect_ratio);
swaplong(&gu3dinfo->header.format);
// palette tables aren't swapped
// simply because they're not used
/*
for(FxU32 i = 0; i < 256; i++)
{
swaplong(&gu3dinfo->table.palette.data[i]);
}
*/
GuNccTable* ncc = &gu3dinfo->table.nccTable;
for ( int i = 0; i < 4; i++ )
{
swapshort(&ncc->iRGB[i][0]);
swapshort(&ncc->iRGB[i][1]);
swapshort(&ncc->iRGB[i][2]);
}
for ( int i = 0; i < 4; i++ )
{
swapshort(&ncc->qRGB[i][0]);
swapshort(&ncc->qRGB[i][1]);
swapshort(&ncc->qRGB[i][2]);
}
swaplong(&gu3dinfo->mem_required);
}
}
#else
void ConvertGu3dfInfoLSB2MSB(Gu3dfInfo* gu3dinfo)
{
}
#endif
static void createTextures( void ) {
Gu3dfInfo *info;
/*
* Download the texture for the "3D" part of the model.
*/
info = ( Gu3dfInfo * )text_3dfinfo_raw;
info->data = ( void * )text_3dfinfo_image;
ConvertGu3dfInfoLSB2MSB(info);
downloadTexture( &textImage, info );
/*
* Download the texture for the specular highlight.
*/
info = ( Gu3dfInfo * )hilite_3dfinfo_raw;
info->data = ( void * )hilite_3dfinfo_image;
ConvertGu3dfInfoLSB2MSB(info);
downloadTexture( &hiliteImage, info );
/*
* Download the texture for the shadow.
*/
info = ( Gu3dfInfo * )shadow_3dfinfo_raw;
info->data = ( void * )shadow_3dfinfo_image;
ConvertGu3dfInfoLSB2MSB(info);
downloadTexture( &shadowImage, info );
return;
}
static void vecMatMult( float *dstVec, float *srcVec, float *matrix ) {
dstVec[0] =
srcVec[0] * matrix[0] +
srcVec[1] * matrix[4] +
srcVec[2] * matrix[8] +
matrix[12];
dstVec[1] =
srcVec[0] * matrix[1] +
srcVec[1] * matrix[5] +
srcVec[2] * matrix[9] +
matrix[13];
dstVec[2] =
srcVec[0] * matrix[2] +
srcVec[1] * matrix[6] +
srcVec[2] * matrix[10] +
matrix[14];
}
static void normMatMult( float *dstVec, float *srcVec, float *matrix ) {
dstVec[0] =
srcVec[0] * matrix[0] +
srcVec[1] * matrix[4] +
srcVec[2] * matrix[8];
dstVec[1] =
srcVec[0] * matrix[1] +
srcVec[1] * matrix[5] +
srcVec[2] * matrix[9];
dstVec[2] =
srcVec[0] * matrix[2] +
srcVec[1] * matrix[6] +
srcVec[2] * matrix[10];
}
static void xfAndProj( int frame, int obj ) {
int vertex;
float *matrix;
matrix = &mat[frame][obj][0];
for( vertex = 0; vertex < num_verts[obj]; vertex++ ) {
float *srcVec;
float *dstVec;
float oow;
/* transform point */
srcVec = (float*)&(vert[obj][vertex].x);
dstVec = (float*)transformed_verts[vertex];
vecMatMult( dstVec, srcVec, matrix );
/* project point */
oow = 1.0f / dstVec[2];
dstVec[0] = dstVec[0] * oow * viewPort[0] + viewPort[1] + SNAP_BIAS;
dstVec[1] = dstVec[1] * oow * viewPort[2] + viewPort[3] + SNAP_BIAS;
/* transform normal */
srcVec = (float*)&(vert[obj][vertex].nx);
dstVec = (float*)transformed_norms[vertex];
normMatMult( dstVec, srcVec, matrix );
}
}
static void setupMaterial( int material_index ) {
switch( material_index ) {
case 0: /* 3d */
if( pass == 1 ) {
sourceTexture( &textImage );
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_LOCAL_ITERATED,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE );
do_phong = 1;
} else if ( pass == 0xbeef ) {
/* Pantone 320C - 3D Green */
grConstantColorValue( 0x00989100 );
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_LOCAL_CONSTANT,
GR_COMBINE_OTHER_ITERATED,
FXFALSE );
} else {
sourceTexture( &hiliteImage );
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_LOCAL_NONE,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE );
}
break;
case 1: /* fx */
if ( pass == 0xbeef ) {
/* Black - fx */
grConstantColorValue( 0x00 );
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_LOCAL_CONSTANT,
GR_COMBINE_OTHER_ITERATED,
FXFALSE );
do_phong = 1;
} else {
sourceTexture( &hiliteImage );
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_LOCAL_NONE,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE );
do_phong = 1;
}
break;
case 2:
case 3:
case 4:
grColorCombine( GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_LOCAL_ITERATED,
GR_COMBINE_OTHER_NONE,
FXFALSE );
do_phong = 0;
break;
}
return;
}
static void calculateIntensity( int material_index,
Vector intensity_factor,
int frame ) {
switch( material_index ) {
case 0:
/* 3d */
intensity_factor[0] = 1.0f;
intensity_factor[1] = 1.0f;
intensity_factor[2] = 1.0f;
break;
case 1:
/* fx */
intensity_factor[0] = 0.125f;
intensity_factor[1] = 0.125f;
intensity_factor[2] = 0.125f;
break;
case 2:
/* cyan */
intensity_factor[0] = ( 10.0f / 255.0f );
intensity_factor[1] = ( 75.0f / 255.0f );
intensity_factor[2] = ( 120.0f / 255.0f );
break;
case 3:
/* white */
intensity_factor[0] = 1.0f;
intensity_factor[1] = 1.0f;
intensity_factor[2] = 1.0f;
break;
case 4:
/* yellow */
intensity_factor[0] = ( 248.0f / 255.0f );
intensity_factor[1] = ( 204.0f / 255.0f );
intensity_factor[2] = 0.0f;
break;
}
}
static void drawFaces( int frame, int objnum ) {
int facenum;
int material_index;
float intensity_factor[3];
GrVertex gvert[3];
static int prev_mat_index = 0xffff;
int i;
FxBool aa_a, aa_b, aa_c;
for( facenum = 0; facenum < num_faces[objnum]; facenum++ ) {
material_index = face[objnum][facenum].mat_index;
if( material_index != prev_mat_index ) {
setupMaterial( material_index );
calculateIntensity( material_index,
intensity_factor, frame );
prev_mat_index = material_index;
}
if( ( material_index != 0 ) && ( pass == 2 ) )
continue;
aa_a = aa_b = aa_c = FXFALSE;
if( face[objnum][facenum].aa_edge_flags & 4 )
aa_a = FXTRUE;
if( face[objnum][facenum].aa_edge_flags & 2 )
aa_b = FXTRUE;
if( face[objnum][facenum].aa_edge_flags & 1 )
aa_c = FXTRUE;
for( i = 0; i < 3; i++ ) {
float *transformed_vert, *transformed_norm;
Vert *v;
int vertnum;
float factor;
vertnum = face[objnum][facenum].v[i];
transformed_vert = transformed_verts[vertnum];
transformed_norm = transformed_norms[vertnum];
v = &vert[objnum][vertnum];
gvert[i].x = transformed_vert[0];
gvert[i].y = transformed_vert[1];
gvert[i].oow = 1.0f / transformed_vert[2];
gvert[i].tmuvtx[0].oow = gvert[i].oow;
gvert[i].tmuvtx[0].sow = v->s * gvert[i].oow;
gvert[i].tmuvtx[0].tow = v->t * gvert[i].oow;
factor =
( ( light[0] * transformed_norm[0] +
light[1] * transformed_norm[1] +
light[2] * transformed_norm[2] ) + 1.0f ) * 127.5f;
gvert[i].r = factor * intensity_factor[0];
gvert[i].g = factor * intensity_factor[1];
gvert[i].b = factor * intensity_factor[2];
gvert[i].a = 255.0f;
}
if( pass == 2 ) {
for( i = 0; i < 3; i++ ) {
float *transformed_norm;
transformed_norm =
transformed_norms[face[objnum][facenum].v[i]];
gvert[i].tmuvtx[0].sow = gvert[i].oow *
( 128.0f + transformed_norm[0] * 128.0f );
gvert[i].tmuvtx[0].tow = gvert[i].oow *
( 128.0f + transformed_norm[1] * 128.0f );
gvert[i].r = intensity_factor[0] * 255.0f;
gvert[i].g = intensity_factor[1] * 255.0f;
gvert[i].b = intensity_factor[2] * 255.0f;
}
grDrawTriangle( &gvert[0], &gvert[1], &gvert[2] );
continue;
}
grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA,
GR_BLEND_ONE, GR_BLEND_ZERO );
/* Do this if 3D. */
if( material_index == 0 ) {
/*
* Draw the textured 3D without specular.
*/
sourceTexture( &textImage );
#if 0
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_LOCAL_ITERATED,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE );
#endif
grAADrawTriangle( &gvert[0], &gvert[1], &gvert[2],
aa_a, aa_b, aa_c );
} else if( material_index != 1 ) {
/*
* Just go ahead and draw for things that don't
* have specular highlights.
*/
grAADrawTriangle( &gvert[0], &gvert[1], &gvert[2],
aa_a, aa_b, aa_c );
}
if( do_phong && ( material_index != 0 ) ) {
/*
* figure out texture coords in [0..255.0f] based on the normal
* the specular highlight.
*/
for( i = 0; i < 3; i++ ) {
float *transformed_norm;
transformed_norm =
transformed_norms[face[objnum][facenum].v[i]];
gvert[i].tmuvtx[0].sow = gvert[i].oow *
( 128.0f + transformed_norm[0] * 128.0f );
gvert[i].tmuvtx[0].tow = gvert[i].oow *
( 128.0f + transformed_norm[1] * 128.0f );
gvert[i].r = intensity_factor[0] * 255.0f;
gvert[i].g = intensity_factor[1] * 255.0f;
gvert[i].b = intensity_factor[2] * 255.0f;
}
grAADrawTriangle( &gvert[0], &gvert[1], &gvert[2],
aa_a, aa_b, aa_c );
}
}
}
static void intersectLineWithZPlane( Vector result, Vector p1,
Vector p2, float z ) {
float t;
t = ( z - p1[2] ) / ( p2[2] - p1[2] );
result[0] = p1[0] + ( p2[0] - p1[0] ) * t;
result[1] = p1[1] + ( p2[1] - p1[1] ) * t;
result[2] = z;
}
static float vectorMag( float *v ) {
return ( float )sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
}
static void drawShadow( int frame, int shadow_object_index,
int receiver_object_index, Vector light_position ) {
float *shadow_object_matrix;
float *receiver_object_matrix;
Vector view_verts[4];
Vector projected_view_verts[4];
int i;
Vector local_verts[4] = {
{ -280.0f, 0.0f, -160.0f },
{ -280.0f, 0.0f, 150.0f },
{ 280.0f, 0.0f, 150.0f },
{ 280.0f, 0.0f, -160.0f }
};
float texcoords[4][2] = {
{ 10.5f, 127.5f },
{ 10.5f, 0.5f },
{ 255.0f, 0.5f },
{ 255.0f, 127.5f }
};
GrVertex gvert[4];
GrVertex projected_gvert[4];
GrVertex light_gvert;
/*
* The point relative to the back part of the shield that
* the shadow is going to be projected onto.
*/
Vector shadow_light;
shadow_light[0] = light_position[0];
shadow_light[1] = light_position[1];
shadow_light[2] = light_position[2];
shadow_object_matrix = &mat[frame][shadow_object_index][0];
receiver_object_matrix = &mat[frame][receiver_object_index][0];
/*
* Offset the light by the Z position of
* the backplane that we are projected
* onto.
*/
shadow_light[2] += receiver_object_matrix[14];
for( i = 0; i < 4; i++ ) {
vecMatMult( view_verts[i], local_verts[i], shadow_object_matrix );
/*
* project . . .
*/
gvert[i].oow = 1.0f / view_verts[i][2];
gvert[i].x =
view_verts[i][0] * gvert[i].oow * viewPort[0] +
viewPort[1] + SNAP_BIAS;
gvert[i].y =
view_verts[i][1] * gvert[i].oow * viewPort[2] +
viewPort[3] + SNAP_BIAS;
/*
* Set up texture coordinates.
*/
gvert[i].tmuvtx[0].sow = texcoords[i][0] * gvert[i].oow;
gvert[i].tmuvtx[0].tow = texcoords[i][1] * gvert[i].oow;
}
/*
* Intersect each line formed by the light source and a
* particular corner of the shadow object with the
* plane which the texture is to be projected onto.
*/
for( i = 0; i < 4; i++ ) {
Vector tmpvect;
float q;
intersectLineWithZPlane( projected_view_verts[i],
shadow_light,
view_verts[i],
receiver_object_matrix[14] - 26.0f );
projected_gvert[i].oow = 1.0f / projected_view_verts[i][2];
projected_gvert[i].x =
projected_view_verts[i][0] * projected_gvert[i].oow * viewPort[0] +
viewPort[1] + SNAP_BIAS;
projected_gvert[i].y =
projected_view_verts[i][1] * projected_gvert[i].oow * viewPort[2] +
viewPort[3] + SNAP_BIAS;
tmpvect[0] = projected_view_verts[i][0] - shadow_light[0];
tmpvect[1] = projected_view_verts[i][1] - shadow_light[1];
tmpvect[2] = projected_view_verts[i][2] - shadow_light[2];
q = vectorMag( tmpvect );
/*
* Set up texture coordinates.
*/
projected_gvert[i].tmuvtx[0].oow = projected_gvert[i].oow * q;
projected_gvert[i].tmuvtx[0].sow =
texcoords[i][0] * projected_gvert[i].oow;
projected_gvert[i].tmuvtx[0].tow =
texcoords[i][1] * projected_gvert[i].oow;
}
light_gvert.oow = 1.0f / shadow_light[2];
light_gvert.x = shadow_light[0] * light_gvert.oow * viewPort[0] +
viewPort[1] + SNAP_BIAS;
light_gvert.y = shadow_light[1] * light_gvert.oow * viewPort[2] +
viewPort[3] + SNAP_BIAS;
/*
* Draw a segment between the light and the point which hits
* the surface that the light is being projected onto.
*/
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_LOCAL_NONE,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE );
sourceTexture( &shadowImage );
grAlphaBlendFunction( GR_BLEND_DST_COLOR, GR_BLEND_ZERO,
GR_BLEND_ONE, GR_BLEND_ZERO );
grDrawTriangle( &projected_gvert[0],
&projected_gvert[1],
&projected_gvert[2] );
grDrawTriangle( &projected_gvert[0],
&projected_gvert[2],
&projected_gvert[3] );
grDrawTriangle( &projected_gvert[0],
&projected_gvert[2],
&projected_gvert[1] );
grDrawTriangle( &projected_gvert[0],
&projected_gvert[3],
&projected_gvert[2] );
grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO,
GR_BLEND_ONE, GR_BLEND_ZERO );
}
/*-------------------------------------------------------------------
Function: grSplash
Date: 3/13
Implementor(s): GaryMcT
Library: Glide
Description:
Render the opening splash screen animation, or render
a single frame of the splash screen.
Arguments:
x, y - upper left hand coord of window
w, h - width and height of window to render
_frame - frame number to render ( ~0 to render all frames )
Return:
none
-------------------------------------------------------------------*/
GR_DIENTRY(grSplash,void,(float x,float y,float w,float h,FxU32 _frame))
{
// OpenGLide addition
#ifdef OGL_DONE
GlideMsg( "grSplash( %-4.2f, %-4.2f, %-4.2f, %-4.2f, %lu )\n",
x, y, w, h, _frame );
#endif
GrState oldState;
int frame;
Vector lights[] = {
{ 5.0f, 300.0f, -1500.0f },
{ 5.0f, 150.0f, -1000.0f },
{ -30.0f, 150.0f, -1000.0f },
{ -30.0f, 100.0f, -1000.0f },
{ 30.0f, 70.0f, -1000.0f },
};
GrFog_t fogTable[kInternalFogTableEntryCount];
int fadeInFrames, fadeOutFrames;
GR_BEGIN_NOFIFOCHECK( "grSplash", 85 );
GDBG_INFO_MORE((gc->myLevel,"(%f,%f,%f,%f,%d)\n",
x, y, w, h, _frame ));
/* Check Screen Dimensions and Check Avail of Depth Buffer */
// The emulation offers virtually unlimited buffers, so we don't have to check
/*
if ( (x > gc->state.screen_width) ||
((x+w) > gc->state.screen_width) ||
( y > gc->state.screen_height ) ||
((y+h) > gc->state.screen_height ) )
return;
if ( gc->state.screen_height == 640 ) {
if ( gc->fbuf_size == 1 ) {
return;
}
} else if ( gc->state.screen_width == 800 ) {
if ( ( gc->fbuf_size == 1 ) ||
( gc->fbuf_size == 2 ) ) {
return;
}
}
*/
// subtexturing doesn't work with the splash animation
// so we're going to turn it off temporarily
const unsigned long generatesubtextures = InternalConfig.GenerateSubTextures; InternalConfig.GenerateSubTextures = 0;
// Gapfix decreases the framerate but doesn't improve the rendering quality of the animation
const OpenGLideGapFixFlags gapfix = InternalConfig.GapFix; InternalConfig.GapFix = OpenGLideGapFixFlag_Disabled;
// if ( !(gc->state.fbi_config.fbzMode & SST_YORIGIN)
if (Glide.State.OriginInformation == GR_ORIGIN_LOWER_LEFT) // @todo: correct?
{
y = (( Glide.WindowHeight - 1.0f ) - (h-1.0f) ) - y;
}
viewPort[0] = w * ( 480.0f / 640.0f );
viewPort[1] = x + ( w / 2.0f );
viewPort[2] = h;
viewPort[3] = y + ( h / 2.0f );
grGlideGetState(&oldState);
grSstOrigin( GR_ORIGIN_LOWER_LEFT );
if ( _frame == 0 ) {
createTextures();
useTextures = 1;
} else {
useTextures = 0;
}
grAlphaTestFunction( GR_CMP_ALWAYS );
grChromakeyMode( GR_CHROMAKEY_DISABLE );
grConstantColorValue( 0xffffffff );
grDepthBufferMode( GR_DEPTHBUFFER_WBUFFER );
grDepthMask( FXTRUE );
grAlphaCombine( GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_LOCAL_ITERATED,
GR_COMBINE_OTHER_NONE,
FXFALSE );
grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO,
GR_BLEND_ONE, GR_BLEND_ZERO );
if ( useTextures )
grTexCombine( GR_TMU0,
GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE,
FXFALSE, FXFALSE );
else
grTexCombine( GR_TMU0,
GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE,
FXTRUE, FXFALSE );
grTexMipMapMode( GR_TMU0,
GR_MIPMAP_NEAREST,
FXFALSE );
grTexFilterMode( GR_TMU0,
GR_TEXTUREFILTER_BILINEAR,
GR_TEXTUREFILTER_BILINEAR );
grDepthBufferFunction( GR_CMP_LEQUAL );
grCullMode( GR_CULL_NEGATIVE );
// grClipWindow( (int)x, (int)y, (int)(x+w), (int)(y+h) );
grFogColorValue( 0x0 );
fadeInFrames = (int)(((float)total_num_frames) * FADEIN_END_PERCENT);
fadeOutFrames = (int)(((float)total_num_frames) *
(1.0f - FADEOUT_BEGIN_PERCENT));
if ( _frame == 0 ) { /* Render Whole Animation */
for( frame = 1; frame < total_num_frames; frame++ ) {
int i;
/* Set Fog Value For This Frame */
if( frame < fadeInFrames ) {
unsigned char fval =
((unsigned char)255) -
((unsigned char)( 255.0f *
(float)(frame+1) /
(float)fadeInFrames ));
for( i = 0; i < kInternalFogTableEntryCount; i++ )
fogTable[i] = fval;
grFogMode( GR_FOG_WITH_TABLE );
grFogTable( fogTable );
fog = 1;
} else if( frame > total_num_frames-fadeOutFrames ) {
unsigned char fval =
((unsigned char)255) -
(unsigned char)(255.0f*
((float)(total_num_frames-frame))/
((float)fadeOutFrames));
for( i = 0; i < kInternalFogTableEntryCount; i++ )
fogTable[i] = fval;
grFogMode( GR_FOG_WITH_TABLE );
grFogTable( fogTable );
fog = 1;
} else {
grFogMode( GR_FOG_DISABLE );
fog = 0;
}
grBufferClear( 0x00000000, 0, GR_WDEPTHVALUE_FARTHEST );
pass = 1;
/*
* Avoid Z-aliasing between the shield and the 3dfx by
* not writing Z for the shield.
*/
grDepthMask( FXFALSE );
/* cyan part of shield */
xfAndProj( frame, 2 );
drawFaces( frame, 2 );
/* yellow and white part of shield. */
xfAndProj( frame, 0 );
drawFaces( frame, 0 );
/*
* Reanable writes to the depth-buffer.
*/
grDepthMask( FXTRUE );
/*
* Draw the shadow projected from the 3Dfx logo onto
* the rest of the powershield.
*/
grDepthBufferFunction( GR_CMP_ALWAYS );
grFogMode( GR_FOG_DISABLE );
drawShadow( frame, 1, 0, lights[0] );
if ( fog ) grFogMode( GR_FOG_WITH_TABLE ); /* hack around mp fog */
grDepthBufferFunction( GR_CMP_LEQUAL );
/* 3Dfx logo */
xfAndProj( frame, 1 );
drawFaces( frame, 1 );
grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ONE,
GR_BLEND_ONE, GR_BLEND_ZERO );
pass = 2;
drawFaces( frame, 1 );
pass = 1;
grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO,
GR_BLEND_ONE, GR_BLEND_ZERO );
grBufferSwap( 2 );
}
} else { /* Render One Frame */
frame = ((_frame>>1) % SPIN_FRAMES)+SPIN_START;
grColorMask( FXFALSE, FXFALSE );
grBufferClear( 0x00000000, 0, GR_WDEPTHVALUE_FARTHEST );
grColorMask( FXTRUE, FXFALSE );
pass = 0xbeef;
/* 3Dfx logo */
xfAndProj( frame, 1 );
drawFaces( frame, 1 );
}
// Added by Jenz: Clear the buffer after the last frame to avoid
// the last image be displayed while the game is loading
// (May be a problem of MacGLide since the 3dfx hardware
if (_frame == 0)
{
grColorMask(FXTRUE, FXTRUE);
grBufferClear(0x00000000, 0, GR_WDEPTHVALUE_FARTHEST);
grColorMask(FXTRUE, FXFALSE);
grBufferSwap( 2 );
}
/*
* Clean up after yourself!
*/
grGlideSetState(&oldState);
// Reenable temporarily disabled settings
InternalConfig.GenerateSubTextures = generatesubtextures;
InternalConfig.GapFix = gapfix;
}