mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-12-14 23:01:26 +00:00
658 lines
18 KiB
C++
658 lines
18 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 GPL Source Code
|
|
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
|
|
|
Doom 3 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "sys/platform.h"
|
|
#include "framework/DemoFile.h"
|
|
#include "renderer/tr_local.h"
|
|
#include "renderer/VertexCache.h"
|
|
|
|
#include "renderer/GuiModel.h"
|
|
|
|
/*
|
|
================
|
|
idGuiModel::idGuiModel
|
|
================
|
|
*/
|
|
idGuiModel::idGuiModel() {
|
|
indexes.SetGranularity( 1000 );
|
|
verts.SetGranularity( 1000 );
|
|
}
|
|
|
|
/*
|
|
================
|
|
idGuiModel::Clear
|
|
|
|
Begins collecting draw commands into surfaces
|
|
================
|
|
*/
|
|
void idGuiModel::Clear() {
|
|
surfaces.SetNum( 0, false );
|
|
indexes.SetNum( 0, false );
|
|
verts.SetNum( 0, false );
|
|
AdvanceSurf();
|
|
}
|
|
|
|
/*
|
|
================
|
|
idGuiModel::WriteToDemo
|
|
================
|
|
*/
|
|
void idGuiModel::WriteToDemo( idDemoFile *demo ) {
|
|
int i, j;
|
|
|
|
i = verts.Num();
|
|
demo->WriteInt( i );
|
|
for ( j = 0; j < i; j++ )
|
|
{
|
|
demo->WriteVec3( verts[j].xyz );
|
|
demo->WriteVec2( verts[j].st );
|
|
demo->WriteVec3( verts[j].normal );
|
|
demo->WriteVec3( verts[j].tangents[0] );
|
|
demo->WriteVec3( verts[j].tangents[1] );
|
|
demo->WriteUnsignedChar( verts[j].color[0] );
|
|
demo->WriteUnsignedChar( verts[j].color[1] );
|
|
demo->WriteUnsignedChar( verts[j].color[2] );
|
|
demo->WriteUnsignedChar( verts[j].color[3] );
|
|
}
|
|
|
|
i = indexes.Num();
|
|
demo->WriteInt( i );
|
|
for ( j = 0; j < i; j++ ) {
|
|
demo->WriteInt(indexes[j] );
|
|
}
|
|
|
|
i = surfaces.Num();
|
|
demo->WriteInt( i );
|
|
for ( j = 0 ; j < i ; j++ ) {
|
|
guiModelSurface_t *surf = &surfaces[j];
|
|
|
|
demo->WriteInt( (int&)surf->material );
|
|
demo->WriteFloat( surf->color[0] );
|
|
demo->WriteFloat( surf->color[1] );
|
|
demo->WriteFloat( surf->color[2] );
|
|
demo->WriteFloat( surf->color[3] );
|
|
demo->WriteInt( surf->firstVert );
|
|
demo->WriteInt( surf->numVerts );
|
|
demo->WriteInt( surf->firstIndex );
|
|
demo->WriteInt( surf->numIndexes );
|
|
demo->WriteHashString( surf->material->GetName() );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
idGuiModel::ReadFromDemo
|
|
================
|
|
*/
|
|
void idGuiModel::ReadFromDemo( idDemoFile *demo ) {
|
|
int i, j;
|
|
|
|
i = verts.Num();
|
|
demo->ReadInt( i );
|
|
verts.SetNum( i, false );
|
|
for ( j = 0; j < i; j++ )
|
|
{
|
|
demo->ReadVec3( verts[j].xyz );
|
|
demo->ReadVec2( verts[j].st );
|
|
demo->ReadVec3( verts[j].normal );
|
|
demo->ReadVec3( verts[j].tangents[0] );
|
|
demo->ReadVec3( verts[j].tangents[1] );
|
|
demo->ReadUnsignedChar( verts[j].color[0] );
|
|
demo->ReadUnsignedChar( verts[j].color[1] );
|
|
demo->ReadUnsignedChar( verts[j].color[2] );
|
|
demo->ReadUnsignedChar( verts[j].color[3] );
|
|
}
|
|
|
|
i = indexes.Num();
|
|
demo->ReadInt( i );
|
|
indexes.SetNum( i, false );
|
|
for ( j = 0; j < i; j++ ) {
|
|
demo->ReadInt(indexes[j] );
|
|
}
|
|
|
|
i = surfaces.Num();
|
|
demo->ReadInt( i );
|
|
surfaces.SetNum( i, false );
|
|
for ( j = 0 ; j < i ; j++ ) {
|
|
guiModelSurface_t *surf = &surfaces[j];
|
|
|
|
demo->ReadInt( (int&)surf->material );
|
|
demo->ReadFloat( surf->color[0] );
|
|
demo->ReadFloat( surf->color[1] );
|
|
demo->ReadFloat( surf->color[2] );
|
|
demo->ReadFloat( surf->color[3] );
|
|
demo->ReadInt( surf->firstVert );
|
|
demo->ReadInt( surf->numVerts );
|
|
demo->ReadInt( surf->firstIndex );
|
|
demo->ReadInt( surf->numIndexes );
|
|
surf->material = declManager->FindMaterial( demo->ReadHashString() );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
EmitSurface
|
|
================
|
|
*/
|
|
void idGuiModel::EmitSurface( guiModelSurface_t *surf, float modelMatrix[16], float modelViewMatrix[16], bool depthHack ) {
|
|
srfTriangles_t *tri;
|
|
|
|
if ( surf->numVerts == 0 ) {
|
|
return; // nothing in the surface
|
|
}
|
|
|
|
// copy verts and indexes
|
|
tri = (srfTriangles_t *)R_ClearedFrameAlloc( sizeof( *tri ) );
|
|
|
|
tri->numIndexes = surf->numIndexes;
|
|
tri->numVerts = surf->numVerts;
|
|
tri->indexes = (glIndex_t *)R_FrameAlloc( tri->numIndexes * sizeof( tri->indexes[0] ) );
|
|
memcpy( tri->indexes, &indexes[surf->firstIndex], tri->numIndexes * sizeof( tri->indexes[0] ) );
|
|
|
|
// we might be able to avoid copying these and just let them reference the list vars
|
|
// but some things, like deforms and recursive
|
|
// guis, need to access the verts in cpu space, not just through the vertex range
|
|
tri->verts = (idDrawVert *)R_FrameAlloc( tri->numVerts * sizeof( tri->verts[0] ) );
|
|
memcpy( tri->verts, &verts[surf->firstVert], tri->numVerts * sizeof( tri->verts[0] ) );
|
|
|
|
// move the verts to the vertex cache
|
|
tri->ambientCache = vertexCache.AllocFrameTemp( tri->verts, tri->numVerts * sizeof( tri->verts[0] ) );
|
|
|
|
// if we are out of vertex cache, don't create the surface
|
|
if ( !tri->ambientCache ) {
|
|
return;
|
|
}
|
|
|
|
renderEntity_t renderEntity;
|
|
memset( &renderEntity, 0, sizeof( renderEntity ) );
|
|
memcpy( renderEntity.shaderParms, surf->color, sizeof( surf->color ) );
|
|
|
|
viewEntity_t *guiSpace = (viewEntity_t *)R_ClearedFrameAlloc( sizeof( *guiSpace ) );
|
|
memcpy( guiSpace->modelMatrix, modelMatrix, sizeof( guiSpace->modelMatrix ) );
|
|
memcpy( guiSpace->modelViewMatrix, modelViewMatrix, sizeof( guiSpace->modelViewMatrix ) );
|
|
guiSpace->weaponDepthHack = depthHack;
|
|
|
|
// add the surface, which might recursively create another gui
|
|
R_AddDrawSurf( tri, guiSpace, &renderEntity, surf->material, tr.viewDef->scissor );
|
|
}
|
|
|
|
/*
|
|
====================
|
|
EmitToCurrentView
|
|
====================
|
|
*/
|
|
void idGuiModel::EmitToCurrentView( float modelMatrix[16], bool depthHack ) {
|
|
float modelViewMatrix[16];
|
|
|
|
const float* worldMVM = tr.viewDef->worldSpace.modelViewMatrix;
|
|
// DG: for r_lockSurfaces use the real world modelViewMatrix
|
|
// so GUIs don't float around
|
|
if(r_lockSurfaces.GetBool() && tr.viewDef == tr.primaryView) {
|
|
worldMVM = tr.lockSurfacesRealViewDef.worldSpace.modelViewMatrix;
|
|
}
|
|
|
|
myGlMultMatrix( modelMatrix, worldMVM, modelViewMatrix );
|
|
|
|
for ( int i = 0 ; i < surfaces.Num() ; i++ ) {
|
|
EmitSurface( &surfaces[i], modelMatrix, modelViewMatrix, depthHack );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
idGuiModel::EmitFullScreen
|
|
|
|
Creates a view that covers the screen and emit the surfaces
|
|
================
|
|
*/
|
|
void idGuiModel::EmitFullScreen( void ) {
|
|
viewDef_t *viewDef;
|
|
|
|
if ( surfaces[0].numVerts == 0 ) {
|
|
return;
|
|
}
|
|
|
|
viewDef = (viewDef_t *)R_ClearedFrameAlloc( sizeof( *viewDef ) );
|
|
|
|
// for gui editor
|
|
if ( !tr.viewDef || !tr.viewDef->isEditor ) {
|
|
viewDef->renderView.x = 0;
|
|
viewDef->renderView.y = 0;
|
|
viewDef->renderView.width = SCREEN_WIDTH;
|
|
viewDef->renderView.height = SCREEN_HEIGHT;
|
|
|
|
tr.RenderViewToViewport( &viewDef->renderView, &viewDef->viewport );
|
|
|
|
viewDef->scissor.x1 = 0;
|
|
viewDef->scissor.y1 = 0;
|
|
viewDef->scissor.x2 = viewDef->viewport.x2 - viewDef->viewport.x1;
|
|
viewDef->scissor.y2 = viewDef->viewport.y2 - viewDef->viewport.y1;
|
|
} else {
|
|
viewDef->renderView.x = tr.viewDef->renderView.x;
|
|
viewDef->renderView.y = tr.viewDef->renderView.y;
|
|
viewDef->renderView.width = tr.viewDef->renderView.width;
|
|
viewDef->renderView.height = tr.viewDef->renderView.height;
|
|
|
|
viewDef->viewport.x1 = tr.viewDef->renderView.x;
|
|
viewDef->viewport.x2 = tr.viewDef->renderView.x + tr.viewDef->renderView.width;
|
|
viewDef->viewport.y1 = tr.viewDef->renderView.y;
|
|
viewDef->viewport.y2 = tr.viewDef->renderView.y + tr.viewDef->renderView.height;
|
|
|
|
viewDef->scissor.x1 = tr.viewDef->scissor.x1;
|
|
viewDef->scissor.y1 = tr.viewDef->scissor.y1;
|
|
viewDef->scissor.x2 = tr.viewDef->scissor.x2;
|
|
viewDef->scissor.y2 = tr.viewDef->scissor.y2;
|
|
}
|
|
|
|
viewDef->floatTime = tr.frameShaderTime;
|
|
|
|
// qglOrtho( 0, 640, 480, 0, 0, 1 ); // always assume 640x480 virtual coordinates
|
|
viewDef->projectionMatrix[0] = 2.0f / 640.0f;
|
|
viewDef->projectionMatrix[5] = -2.0f / 480.0f;
|
|
viewDef->projectionMatrix[10] = -2.0f / 1.0f;
|
|
viewDef->projectionMatrix[12] = -1.0f;
|
|
viewDef->projectionMatrix[13] = 1.0f;
|
|
viewDef->projectionMatrix[14] = -1.0f;
|
|
viewDef->projectionMatrix[15] = 1.0f;
|
|
|
|
viewDef->worldSpace.modelViewMatrix[0] = 1.0f;
|
|
viewDef->worldSpace.modelViewMatrix[5] = 1.0f;
|
|
viewDef->worldSpace.modelViewMatrix[10] = 1.0f;
|
|
viewDef->worldSpace.modelViewMatrix[15] = 1.0f;
|
|
|
|
viewDef->maxDrawSurfs = surfaces.Num();
|
|
viewDef->drawSurfs = (drawSurf_t **)R_FrameAlloc( viewDef->maxDrawSurfs * sizeof( viewDef->drawSurfs[0] ) );
|
|
viewDef->numDrawSurfs = 0;
|
|
|
|
viewDef_t *oldViewDef = tr.viewDef;
|
|
tr.viewDef = viewDef;
|
|
|
|
// add the surfaces to this view
|
|
for ( int i = 0 ; i < surfaces.Num() ; i++ ) {
|
|
EmitSurface( &surfaces[i], viewDef->worldSpace.modelMatrix, viewDef->worldSpace.modelViewMatrix, false );
|
|
}
|
|
|
|
tr.viewDef = oldViewDef;
|
|
|
|
// add the command to draw this view
|
|
R_AddDrawViewCmd( viewDef );
|
|
}
|
|
|
|
/*
|
|
=============
|
|
AdvanceSurf
|
|
=============
|
|
*/
|
|
void idGuiModel::AdvanceSurf() {
|
|
guiModelSurface_t s;
|
|
|
|
if ( surfaces.Num() ) {
|
|
s.color[0] = surf->color[0];
|
|
s.color[1] = surf->color[1];
|
|
s.color[2] = surf->color[2];
|
|
s.color[3] = surf->color[3];
|
|
s.material = surf->material;
|
|
} else {
|
|
s.color[0] = 1;
|
|
s.color[1] = 1;
|
|
s.color[2] = 1;
|
|
s.color[3] = 1;
|
|
s.material = tr.defaultMaterial;
|
|
}
|
|
s.numIndexes = 0;
|
|
s.firstIndex = indexes.Num();
|
|
s.numVerts = 0;
|
|
s.firstVert = verts.Num();
|
|
|
|
surfaces.Append( s );
|
|
surf = &surfaces[ surfaces.Num() - 1 ];
|
|
}
|
|
|
|
/*
|
|
=============
|
|
SetColor
|
|
=============
|
|
*/
|
|
void idGuiModel::SetColor( float r, float g, float b, float a ) {
|
|
if ( !glConfig.isInitialized ) {
|
|
return;
|
|
}
|
|
if ( r == surf->color[0] && g == surf->color[1]
|
|
&& b == surf->color[2] && a == surf->color[3] ) {
|
|
return; // no change
|
|
}
|
|
|
|
if ( surf->numVerts ) {
|
|
AdvanceSurf();
|
|
}
|
|
|
|
// change the parms
|
|
surf->color[0] = r;
|
|
surf->color[1] = g;
|
|
surf->color[2] = b;
|
|
surf->color[3] = a;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
DrawStretchPic
|
|
=============
|
|
*/
|
|
void idGuiModel::DrawStretchPic( const idDrawVert *dverts, const glIndex_t *dindexes, int vertCount, int indexCount, const idMaterial *hShader,
|
|
bool clip, float min_x, float min_y, float max_x, float max_y ) {
|
|
if ( !glConfig.isInitialized ) {
|
|
return;
|
|
}
|
|
if ( !( dverts && dindexes && vertCount && indexCount && hShader ) ) {
|
|
return;
|
|
}
|
|
|
|
// break the current surface if we are changing to a new material
|
|
if ( hShader != surf->material ) {
|
|
if ( surf->numVerts ) {
|
|
AdvanceSurf();
|
|
}
|
|
const_cast<idMaterial *>(hShader)->EnsureNotPurged(); // in case it was a gui item started before a level change
|
|
surf->material = hShader;
|
|
}
|
|
|
|
// add the verts and indexes to the current surface
|
|
|
|
if ( clip ) {
|
|
int i, j;
|
|
|
|
// FIXME: this is grim stuff, and should be rewritten if we have any significant
|
|
// number of guis asking for clipping
|
|
idFixedWinding w;
|
|
for ( i = 0; i < indexCount; i += 3 ) {
|
|
w.Clear();
|
|
w.AddPoint(idVec5(dverts[dindexes[i]].xyz.x, dverts[dindexes[i]].xyz.y, dverts[dindexes[i]].xyz.z, dverts[dindexes[i]].st.x, dverts[dindexes[i]].st.y));
|
|
w.AddPoint(idVec5(dverts[dindexes[i+1]].xyz.x, dverts[dindexes[i+1]].xyz.y, dverts[dindexes[i+1]].xyz.z, dverts[dindexes[i+1]].st.x, dverts[dindexes[i+1]].st.y));
|
|
w.AddPoint(idVec5(dverts[dindexes[i+2]].xyz.x, dverts[dindexes[i+2]].xyz.y, dverts[dindexes[i+2]].xyz.z, dverts[dindexes[i+2]].st.x, dverts[dindexes[i+2]].st.y));
|
|
|
|
for ( j = 0; j < 3; j++ ) {
|
|
if ( w[j].x < min_x || w[j].x > max_x ||
|
|
w[j].y < min_y || w[j].y > max_y ) {
|
|
break;
|
|
}
|
|
}
|
|
if ( j < 3 ) {
|
|
idPlane p;
|
|
p.Normal().y = p.Normal().z = 0.0f; p.Normal().x = 1.0f; p.SetDist( min_x );
|
|
w.ClipInPlace( p );
|
|
p.Normal().y = p.Normal().z = 0.0f; p.Normal().x = -1.0f; p.SetDist( -max_x );
|
|
w.ClipInPlace( p );
|
|
p.Normal().x = p.Normal().z = 0.0f; p.Normal().y = 1.0f; p.SetDist( min_y );
|
|
w.ClipInPlace( p );
|
|
p.Normal().x = p.Normal().z = 0.0f; p.Normal().y = -1.0f; p.SetDist( -max_y );
|
|
w.ClipInPlace( p );
|
|
}
|
|
|
|
int numVerts = verts.Num();
|
|
verts.SetNum( numVerts + w.GetNumPoints(), false );
|
|
for ( j = 0 ; j < w.GetNumPoints() ; j++ ) {
|
|
idDrawVert *dv = &verts[numVerts+j];
|
|
|
|
dv->xyz.x = w[j].x;
|
|
dv->xyz.y = w[j].y;
|
|
dv->xyz.z = w[j].z;
|
|
dv->st.x = w[j].s;
|
|
dv->st.y = w[j].t;
|
|
dv->normal.Set(0, 0, 1);
|
|
dv->tangents[0].Set(1, 0, 0);
|
|
dv->tangents[1].Set(0, 1, 0);
|
|
}
|
|
surf->numVerts += w.GetNumPoints();
|
|
|
|
for ( j = 2; j < w.GetNumPoints(); j++ ) {
|
|
indexes.Append( numVerts - surf->firstVert );
|
|
indexes.Append( numVerts + j - 1 - surf->firstVert );
|
|
indexes.Append( numVerts + j - surf->firstVert );
|
|
surf->numIndexes += 3;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
int numVerts = verts.Num();
|
|
int numIndexes = indexes.Num();
|
|
|
|
verts.AssureSize( numVerts + vertCount );
|
|
indexes.AssureSize( numIndexes + indexCount );
|
|
|
|
surf->numVerts += vertCount;
|
|
surf->numIndexes += indexCount;
|
|
|
|
for ( int i = 0; i < indexCount; i++ ) {
|
|
indexes[numIndexes + i] = numVerts + dindexes[i] - surf->firstVert;
|
|
}
|
|
|
|
memcpy( &verts[numVerts], dverts, vertCount * sizeof( verts[0] ) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
=============
|
|
DrawStretchPic
|
|
|
|
x/y/w/h are in the 0,0 to 640,480 range
|
|
=============
|
|
*/
|
|
void idGuiModel::DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *hShader ) {
|
|
idDrawVert verts[4];
|
|
glIndex_t indexes[6];
|
|
|
|
if ( !glConfig.isInitialized ) {
|
|
return;
|
|
}
|
|
if ( !hShader ) {
|
|
return;
|
|
}
|
|
|
|
// clip to edges, because the pic may be going into a guiShader
|
|
// instead of full screen
|
|
if ( x < 0 ) {
|
|
s1 += ( s2 - s1 ) * -x / w;
|
|
w += x;
|
|
x = 0;
|
|
}
|
|
if ( y < 0 ) {
|
|
t1 += ( t2 - t1 ) * -y / h;
|
|
h += y;
|
|
y = 0;
|
|
}
|
|
if ( x + w > 640 ) {
|
|
s2 -= ( s2 - s1 ) * ( x + w - 640 ) / w;
|
|
w = 640 - x;
|
|
}
|
|
if ( y + h > 480 ) {
|
|
t2 -= ( t2 - t1 ) * ( y + h - 480 ) / h;
|
|
h = 480 - y;
|
|
}
|
|
|
|
if ( w <= 0 || h <= 0 ) {
|
|
return; // completely clipped away
|
|
}
|
|
|
|
indexes[0] = 3;
|
|
indexes[1] = 0;
|
|
indexes[2] = 2;
|
|
indexes[3] = 2;
|
|
indexes[4] = 0;
|
|
indexes[5] = 1;
|
|
verts[0].xyz[0] = x;
|
|
verts[0].xyz[1] = y;
|
|
verts[0].xyz[2] = 0;
|
|
verts[0].st[0] = s1;
|
|
verts[0].st[1] = t1;
|
|
verts[0].normal[0] = 0;
|
|
verts[0].normal[1] = 0;
|
|
verts[0].normal[2] = 1;
|
|
verts[0].tangents[0][0] = 1;
|
|
verts[0].tangents[0][1] = 0;
|
|
verts[0].tangents[0][2] = 0;
|
|
verts[0].tangents[1][0] = 0;
|
|
verts[0].tangents[1][1] = 1;
|
|
verts[0].tangents[1][2] = 0;
|
|
verts[1].xyz[0] = x + w;
|
|
verts[1].xyz[1] = y;
|
|
verts[1].xyz[2] = 0;
|
|
verts[1].st[0] = s2;
|
|
verts[1].st[1] = t1;
|
|
verts[1].normal[0] = 0;
|
|
verts[1].normal[1] = 0;
|
|
verts[1].normal[2] = 1;
|
|
verts[1].tangents[0][0] = 1;
|
|
verts[1].tangents[0][1] = 0;
|
|
verts[1].tangents[0][2] = 0;
|
|
verts[1].tangents[1][0] = 0;
|
|
verts[1].tangents[1][1] = 1;
|
|
verts[1].tangents[1][2] = 0;
|
|
verts[2].xyz[0] = x + w;
|
|
verts[2].xyz[1] = y + h;
|
|
verts[2].xyz[2] = 0;
|
|
verts[2].st[0] = s2;
|
|
verts[2].st[1] = t2;
|
|
verts[2].normal[0] = 0;
|
|
verts[2].normal[1] = 0;
|
|
verts[2].normal[2] = 1;
|
|
verts[2].tangents[0][0] = 1;
|
|
verts[2].tangents[0][1] = 0;
|
|
verts[2].tangents[0][2] = 0;
|
|
verts[2].tangents[1][0] = 0;
|
|
verts[2].tangents[1][1] = 1;
|
|
verts[2].tangents[1][2] = 0;
|
|
verts[3].xyz[0] = x;
|
|
verts[3].xyz[1] = y + h;
|
|
verts[3].xyz[2] = 0;
|
|
verts[3].st[0] = s1;
|
|
verts[3].st[1] = t2;
|
|
verts[3].normal[0] = 0;
|
|
verts[3].normal[1] = 0;
|
|
verts[3].normal[2] = 1;
|
|
verts[3].tangents[0][0] = 1;
|
|
verts[3].tangents[0][1] = 0;
|
|
verts[3].tangents[0][2] = 0;
|
|
verts[3].tangents[1][0] = 0;
|
|
verts[3].tangents[1][1] = 1;
|
|
verts[3].tangents[1][2] = 0;
|
|
|
|
DrawStretchPic( &verts[0], &indexes[0], 4, 6, hShader, false, 0.0f, 0.0f, 640.0f, 480.0f );
|
|
}
|
|
|
|
/*
|
|
=============
|
|
DrawStretchTri
|
|
|
|
x/y/w/h are in the 0,0 to 640,480 range
|
|
=============
|
|
*/
|
|
void idGuiModel::DrawStretchTri( idVec2 p1, idVec2 p2, idVec2 p3, idVec2 t1, idVec2 t2, idVec2 t3, const idMaterial *material ) {
|
|
idDrawVert tempVerts[3];
|
|
glIndex_t tempIndexes[3];
|
|
int vertCount = 3;
|
|
int indexCount = 3;
|
|
|
|
if ( !glConfig.isInitialized ) {
|
|
return;
|
|
}
|
|
if ( !material ) {
|
|
return;
|
|
}
|
|
|
|
tempIndexes[0] = 1;
|
|
tempIndexes[1] = 0;
|
|
tempIndexes[2] = 2;
|
|
tempVerts[0].xyz[0] = p1.x;
|
|
tempVerts[0].xyz[1] = p1.y;
|
|
tempVerts[0].xyz[2] = 0;
|
|
tempVerts[0].st[0] = t1.x;
|
|
tempVerts[0].st[1] = t1.y;
|
|
tempVerts[0].normal[0] = 0;
|
|
tempVerts[0].normal[1] = 0;
|
|
tempVerts[0].normal[2] = 1;
|
|
tempVerts[0].tangents[0][0] = 1;
|
|
tempVerts[0].tangents[0][1] = 0;
|
|
tempVerts[0].tangents[0][2] = 0;
|
|
tempVerts[0].tangents[1][0] = 0;
|
|
tempVerts[0].tangents[1][1] = 1;
|
|
tempVerts[0].tangents[1][2] = 0;
|
|
tempVerts[1].xyz[0] = p2.x;
|
|
tempVerts[1].xyz[1] = p2.y;
|
|
tempVerts[1].xyz[2] = 0;
|
|
tempVerts[1].st[0] = t2.x;
|
|
tempVerts[1].st[1] = t2.y;
|
|
tempVerts[1].normal[0] = 0;
|
|
tempVerts[1].normal[1] = 0;
|
|
tempVerts[1].normal[2] = 1;
|
|
tempVerts[1].tangents[0][0] = 1;
|
|
tempVerts[1].tangents[0][1] = 0;
|
|
tempVerts[1].tangents[0][2] = 0;
|
|
tempVerts[1].tangents[1][0] = 0;
|
|
tempVerts[1].tangents[1][1] = 1;
|
|
tempVerts[1].tangents[1][2] = 0;
|
|
tempVerts[2].xyz[0] = p3.x;
|
|
tempVerts[2].xyz[1] = p3.y;
|
|
tempVerts[2].xyz[2] = 0;
|
|
tempVerts[2].st[0] = t3.x;
|
|
tempVerts[2].st[1] = t3.y;
|
|
tempVerts[2].normal[0] = 0;
|
|
tempVerts[2].normal[1] = 0;
|
|
tempVerts[2].normal[2] = 1;
|
|
tempVerts[2].tangents[0][0] = 1;
|
|
tempVerts[2].tangents[0][1] = 0;
|
|
tempVerts[2].tangents[0][2] = 0;
|
|
tempVerts[2].tangents[1][0] = 0;
|
|
tempVerts[2].tangents[1][1] = 1;
|
|
tempVerts[2].tangents[1][2] = 0;
|
|
|
|
// break the current surface if we are changing to a new material
|
|
if ( material != surf->material ) {
|
|
if ( surf->numVerts ) {
|
|
AdvanceSurf();
|
|
}
|
|
const_cast<idMaterial *>(material)->EnsureNotPurged(); // in case it was a gui item started before a level change
|
|
surf->material = material;
|
|
}
|
|
|
|
|
|
int numVerts = verts.Num();
|
|
int numIndexes = indexes.Num();
|
|
|
|
verts.AssureSize( numVerts + vertCount );
|
|
indexes.AssureSize( numIndexes + indexCount );
|
|
|
|
surf->numVerts += vertCount;
|
|
surf->numIndexes += indexCount;
|
|
|
|
for ( int i = 0; i < indexCount; i++ ) {
|
|
indexes[numIndexes + i] = numVerts + tempIndexes[i] - surf->firstVert;
|
|
}
|
|
|
|
memcpy( &verts[numVerts], tempVerts, vertCount * sizeof( verts[0] ) );
|
|
}
|