engine/dgl/dgl.cc
2024-01-07 04:36:33 +00:00

747 lines
21 KiB
C++

//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "math/mPoint.h"
#include "dgl/gTexManager.h"
#include "dgl/dgl.h"
#include "core/color.h"
#include "math/mPoint.h"
#include "math/mRect.h"
#include "dgl/gFont.h"
#include "console/console.h"
#include "math/mMatrix.h"
#include "sim/frameAllocator.h"
#include "platform/profiler.h"
namespace {
ColorI sg_bitmapModulation(255, 255, 255, 255);
ColorI sg_textAnchorColor(255, 255, 255, 255);
ColorI sg_stackColor(255, 255, 255, 255);
RectI sgCurrentClipRect;
} // namespace {}
//--------------------------------------------------------------------------
void dglSetBitmapModulation(const ColorF& in_rColor)
{
ColorF c = in_rColor;
c.clamp();
sg_bitmapModulation = c;
sg_textAnchorColor = sg_bitmapModulation;
}
void dglGetBitmapModulation(ColorF* color)
{
*color = sg_bitmapModulation;
}
void dglGetBitmapModulation(ColorI* color)
{
*color = sg_bitmapModulation;
}
void dglClearBitmapModulation()
{
sg_bitmapModulation.set(255, 255, 255, 255);
}
void dglSetTextAnchorColor(const ColorF& in_rColor)
{
ColorF c = in_rColor;
c.clamp();
sg_textAnchorColor = c;
}
//--------------------------------------------------------------------------
void dglDrawBitmapStretchSR(TextureObject* texture,
const RectI& dstRect,
const RectI& srcRect,
const U32 in_flip)
{
AssertFatal(texture != NULL, "GSurface::drawBitmapStretchSR: NULL Handle");
if(!dstRect.isValidRect())
return;
AssertFatal(srcRect.isValidRect() == true,
"GSurface::drawBitmapStretchSR: routines assume normal rects");
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture->texGLName);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
F32 texLeft = F32(srcRect.point.x) / F32(texture->texWidth);
F32 texRight = F32(srcRect.point.x + srcRect.extent.x) / F32(texture->texWidth);
F32 texTop = F32(srcRect.point.y) / F32(texture->texHeight);
F32 texBottom = F32(srcRect.point.y + srcRect.extent.y) / F32(texture->texHeight);
F32 screenLeft = dstRect.point.x;
F32 screenRight = dstRect.point.x + dstRect.extent.x;
F32 screenTop = dstRect.point.y;
F32 screenBottom = dstRect.point.y + dstRect.extent.y;
if(in_flip & GFlip_X)
{
F32 temp = texLeft;
texLeft = texRight;
texRight = temp;
}
if(in_flip & GFlip_Y)
{
F32 temp = texTop;
texTop = texBottom;
texBottom = temp;
}
glColor4ub(sg_bitmapModulation.red,
sg_bitmapModulation.green,
sg_bitmapModulation.blue,
sg_bitmapModulation.alpha);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(texLeft, texBottom);
glVertex2f(screenLeft, screenBottom);
glTexCoord2f(texRight, texBottom);
glVertex2f(screenRight, screenBottom);
glTexCoord2f(texRight, texTop);
glVertex2f(screenRight, screenTop);
glTexCoord2f(texLeft, texTop);
glVertex2f(screenLeft, screenTop);
glEnd();
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
}
void dglDrawBitmap(TextureObject* texture, const Point2I& in_rAt, const U32 in_flip)
{
AssertFatal(texture != NULL, "GSurface::drawBitmap: NULL Handle");
// All non-StretchSR bitmaps are transformed into StretchSR calls...
//
RectI subRegion(0, 0,
texture->bitmapWidth,
texture->bitmapHeight);
RectI stretch(in_rAt.x, in_rAt.y,
texture->bitmapWidth,
texture->bitmapHeight);
dglDrawBitmapStretchSR(texture,
stretch,
subRegion,
in_flip);
}
void dglDrawBitmapStretch(TextureObject* texture, const RectI& dstRect, const U32 in_flip)
{
AssertFatal(texture != NULL, "GSurface::drawBitmapStretch: NULL Handle");
AssertFatal(dstRect.isValidRect() == true,
"GSurface::drawBitmapStretch: routines assume normal rects");
RectI subRegion(0, 0,
texture->bitmapWidth,
texture->bitmapHeight);
dglDrawBitmapStretchSR(texture,
dstRect,
subRegion,
in_flip);
}
void dglDrawBitmapSR(TextureObject *texture, const Point2I& in_rAt, const RectI& srcRect, const U32 in_flip)
{
AssertFatal(texture != NULL, "GSurface::drawBitmapSR: NULL Handle");
AssertFatal(srcRect.isValidRect() == true,
"GSurface::drawBitmapSR: routines assume normal rects");
RectI stretch(in_rAt.x, in_rAt.y,
srcRect.len_x(),
srcRect.len_y());
dglDrawBitmapStretchSR(texture,
stretch,
srcRect,
in_flip);
}
U32 dglDrawText(GFont* font,
const Point2I& ptDraw,
const void* in_string,
const ColorI* colorTable,
const U32 maxColorIndex)
{
return dglDrawTextN(font, ptDraw, in_string, dStrlen((const char *) in_string), colorTable, maxColorIndex);
}
struct TextVertex
{
Point3F p;
Point2F t;
ColorI c;
void set(F32 x, F32 y, F32 tx, F32 ty, ColorI color)
{
p.x = x;
p.y = y;
p.z = 0;
t.x = tx;
t.y = ty;
c = color;
}
};
U32 dglDrawTextN(GFont* font,
const Point2I& ptDraw,
const void* in_string,
U32 n,
const ColorI* colorTable,
const U32 maxColorIndex)
{
// return on zero length strings
if( n < 1 )
return ptDraw.x;
PROFILE_START(DrawText);
Point2I pt;
U8 c;
const U8 *str = (const U8*)in_string;
const U8 *endStr = str + n;
pt.x = ptDraw.x;
ColorI currentColor;
S32 currentPt = 0;
U32 storedWaterMark;
TextureObject *lastTexture = NULL;
storedWaterMark = FrameAllocator::getWaterMark();
currentColor = sg_bitmapModulation;
TextVertex *vert = (TextVertex *) FrameAllocator::alloc(4 * n * sizeof(TextVertex));
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnableClientState ( GL_VERTEX_ARRAY );
glVertexPointer ( 3, GL_FLOAT, sizeof(TextVertex), &(vert[0].p) );
glEnableClientState ( GL_COLOR_ARRAY );
glColorPointer ( 4, GL_UNSIGNED_BYTE, sizeof(TextVertex), &(vert[0].c) );
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer ( 2, GL_FLOAT, sizeof(TextVertex), &(vert[0].t) );
// first build the point, color, and coord arrays
for (c = *str; str < endStr; c = *(++str))
{
// We have to do a little dance here since \t = 0x9, \n = 0xa, and \r = 0xd
if ((c >= 2 && c <= 8) ||
(c >= 11 && c <= 12) ||
(c == 14))
{
// Color code
if (colorTable)
{
static U8 remap[15] =
{
0x0,
0x0,
0x0,
0x1,
0x2,
0x3,
0x4,
0x5,
0x6,
0x0,
0x0,
0x7,
0x8,
0x0,
0x9
};
U8 remapped = remap[c];
// Ignore if the color is greater than the specified max index:
if ( remapped <= maxColorIndex )
{
const ColorI &clr = colorTable[remapped];
currentColor = sg_bitmapModulation = clr;
}
}
continue;
}
// reset color?
if ( c == 15 )
{
currentColor = sg_textAnchorColor;
sg_bitmapModulation = sg_textAnchorColor;
continue;
}
// push color:
if ( c == 16 )
{
sg_stackColor = sg_bitmapModulation;
continue;
}
// pop color:
if ( c == 17 )
{
currentColor = sg_stackColor;
sg_bitmapModulation = sg_stackColor;
continue;
}
// Tab character
if( !font->isValidChar( c ) )
{
if ( c == '\t' )
{
const GFont::CharInfo &ci = font->getCharInfo( ' ' );
pt.x += ci.xIncrement * GFont::TabWidthInSpaces;
}
continue;
}
const GFont::CharInfo &ci = font->getCharInfo(c);
TextureObject *newObj = font->getTextureHandle(ci.bitmapIndex);
if(newObj != lastTexture)
{
if(currentPt)
{
glBindTexture(GL_TEXTURE_2D, lastTexture->texGLName);
glDrawArrays( GL_QUADS, 0, currentPt );
currentPt = 0;
}
lastTexture = newObj;
}
if(ci.width != 0 && ci.height != 0)
{
pt.y = ptDraw.y + font->getBaseline() - ci.yOrigin;
pt.x += ci.xOrigin;
F32 texLeft = F32(ci.xOffset) / F32(lastTexture->texWidth);
F32 texRight = F32(ci.xOffset + ci.width) / F32(lastTexture->texWidth);
F32 texTop = F32(ci.yOffset) / F32(lastTexture->texHeight);
F32 texBottom = F32(ci.yOffset + ci.height) / F32(lastTexture->texHeight);
F32 screenLeft = pt.x;
F32 screenRight = pt.x + ci.width;
F32 screenTop = pt.y;
F32 screenBottom = pt.y + ci.height;
vert[currentPt++].set(screenLeft, screenBottom, texLeft, texBottom, currentColor);
vert[currentPt++].set(screenRight, screenBottom, texRight, texBottom, currentColor);
vert[currentPt++].set(screenRight, screenTop, texRight, texTop, currentColor);
vert[currentPt++].set(screenLeft, screenTop, texLeft, texTop, currentColor);
pt.x += ci.xIncrement - ci.xOrigin;
}
else
pt.x += ci.xIncrement;
}
/* if (gOpenGLNoDrawArraysAlpha)
{
glBegin(GL_QUADS);
for (S32 i = 0; i < rd[page].count; ++i)
{
glColor4fv((float *) &colArray[rd[page].start+i]);
glTexCoord2f(texArray[rd[page].start+i].x, texArray[rd[page].start+i].y);
glVertex2f(ptArray[rd[page].start+i].x, ptArray[rd[page].start+i].y);
}
glEnd();
}
else*/
if(currentPt)
{
glBindTexture(GL_TEXTURE_2D, lastTexture->texGLName);
glDrawArrays( GL_QUADS, 0, currentPt );
}
glDisableClientState ( GL_VERTEX_ARRAY );
glDisableClientState ( GL_COLOR_ARRAY );
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
// restore the FrameAllocator
FrameAllocator::setWaterMark(storedWaterMark);
AssertFatal(pt.x >= ptDraw.x, "How did this happen?");
PROFILE_END();
return pt.x - ptDraw.x;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
// Drawing primitives
void dglDrawLine(S32 x1, S32 y1, S32 x2, S32 y2, const ColorI &color)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glColor4ub(color.red, color.green, color.blue, color.alpha);
glBegin(GL_LINES);
glVertex2f((F32)x1 + 0.5, (F32)y1 + 0.5);
glVertex2f((F32)x2 + 0.5, (F32)y2 + 0.5);
glEnd();
}
void dglDrawLine(const Point2I &startPt, const Point2I &endPt, const ColorI &color)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glColor4ub(color.red, color.green, color.blue, color.alpha);
glBegin(GL_LINES);
glVertex2f((F32)startPt.x + 0.5, (F32)startPt.y + 0.5);
glVertex2f((F32)endPt.x + 0.5, (F32)endPt.y + 0.5);
glEnd();
}
void dglDrawRect(const Point2I &upperL, const Point2I &lowerR, const ColorI &color)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glColor4ub(color.red, color.green, color.blue, color.alpha);
glBegin(GL_LINE_LOOP);
glVertex2f((F32)upperL.x + 0.5, (F32)upperL.y + 0.5);
glVertex2f((F32)lowerR.x + 0.5, (F32)upperL.y + 0.5);
glVertex2f((F32)lowerR.x + 0.5, (F32)lowerR.y + 0.5);
glVertex2f((F32)upperL.x + 0.5, (F32)lowerR.y + 0.5);
glEnd();
}
void dglDrawRect(const RectI &rect, const ColorI &color)
{
Point2I lowerR(rect.point.x + rect.extent.x - 1, rect.point.y + rect.extent.y - 1);
dglDrawRect(rect.point, lowerR, color);
}
void dglDrawRectFill(const Point2I &upperL, const Point2I &lowerR, const ColorI &color)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glColor4ub(color.red, color.green, color.blue, color.alpha);
glRecti((F32)upperL.x, (F32)upperL.y, (F32)lowerR.x, (F32)lowerR.y);
}
void dglDrawRectFill(const RectI &rect, const ColorI &color)
{
Point2I lowerR(rect.point.x + rect.extent.x - 1, rect.point.y + rect.extent.y - 1);
dglDrawRectFill(rect.point, lowerR, color);
}
void dglDraw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle )
{
width *= 0.5;
MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) );
Point3F offset( screenPoint.x, screenPoint.y, 0.0 );
Point3F points[4];
points[0] = Point3F(-width, -width, 0.0);
points[1] = Point3F(-width, width, 0.0);
points[2] = Point3F( width, width, 0.0);
points[3] = Point3F( width, -width, 0.0);
for( int i=0; i<4; i++ )
{
rotMatrix.mulP( points[i] );
points[i] += offset;
}
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.0, 0.0);
glVertex2fv(points[0]);
glTexCoord2f(0.0, 1.0);
glVertex2fv(points[1]);
glTexCoord2f(1.0, 1.0);
glVertex2fv(points[2]);
glTexCoord2f(1.0, 0.0);
glVertex2fv(points[3]);
glEnd();
}
void dglDrawBillboard( const Point3F &position, F32 width, F32 spinAngle )
{
MatrixF modelview;
dglGetModelview( &modelview );
modelview.transpose();
width *= 0.5;
Point3F points[4];
points[0] = Point3F(-width, 0.0, -width);
points[1] = Point3F(-width, 0.0, width);
points[2] = Point3F( width, 0.0, width);
points[3] = Point3F( width, 0.0, -width);
MatrixF rotMatrix( EulerF( 0.0, spinAngle, 0.0 ) );
for( int i=0; i<4; i++ )
{
rotMatrix.mulP( points[i] );
modelview.mulP( points[i] );
points[i] += position;
}
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.0, 0.0);
glVertex3fv(points[0]);
glTexCoord2f(0.0, 1.0);
glVertex3fv(points[1]);
glTexCoord2f(1.0, 1.0);
glVertex3fv(points[2]);
glTexCoord2f(1.0, 0.0);
glVertex3fv(points[3]);
glEnd();
}
void dglSetClipRect(const RectI &clipRect)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
U32 screenWidth = Platform::getWindowSize().x;
U32 screenHeight = Platform::getWindowSize().y;
glOrtho(clipRect.point.x, clipRect.point.x + clipRect.extent.x,
clipRect.extent.y, 0,
0, 1);
glTranslatef(0, -clipRect.point.y, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(clipRect.point.x, screenHeight - (clipRect.point.y + clipRect.extent.y),
clipRect.extent.x, clipRect.extent.y);
sgCurrentClipRect = clipRect;
}
const RectI& dglGetClipRect()
{
return sgCurrentClipRect;
}
bool dglPointToScreen( Point3F &point3D, Point3F &screenPoint )
{
GLdouble glMV[16];
GLdouble glPR[16];
GLint glVP[4];
glGetDoublev(GL_PROJECTION_MATRIX, glPR);
glGetDoublev(GL_MODELVIEW_MATRIX, glMV);
RectI viewport;
dglGetViewport(&viewport);
glVP[0] = viewport.point.x;
glVP[1] = viewport.point.y + viewport.extent.y;
glVP[2] = viewport.extent.x;
glVP[3] = -viewport.extent.y;
MatrixF mv;
dglGetModelview(&mv);
MatrixF pr;
dglGetProjection(&pr);
F64 x, y, z;
int result = gluProject( point3D.x, point3D.y, point3D.z, (const F64 *)&glMV, (const F64 *)&glPR, (const S32 *)&glVP, &x, &y, &z );
screenPoint.x = x;
screenPoint.y = y;
screenPoint.z = z;
return (result == GL_TRUE);
}
bool dglIsInCanonicalState()
{
bool ret = true;
// Canonical state:
// BLEND disabled
// TEXTURE_2D disabled on both texture units.
// ActiveTexture set to 0
// LIGHTING off
// winding : clockwise ?
// cullface : disabled
ret &= glIsEnabled(GL_BLEND) == GL_FALSE;
ret &= glIsEnabled(GL_CULL_FACE) == GL_FALSE;
GLint temp;
if (dglDoesSupportARBMultitexture() == true) {
glActiveTextureARB(GL_TEXTURE1_ARB);
ret &= glIsEnabled(GL_TEXTURE_2D) == GL_FALSE;
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &temp);
ret &= temp == GL_REPLACE;
glActiveTextureARB(GL_TEXTURE0_ARB);
ret &= glIsEnabled(GL_TEXTURE_2D) == GL_FALSE;
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &temp);
ret &= temp == GL_REPLACE;
glClientActiveTextureARB(GL_TEXTURE1_ARB);
ret &= glIsEnabled(GL_TEXTURE_COORD_ARRAY) == GL_FALSE;
glClientActiveTextureARB(GL_TEXTURE0_ARB);
ret &= glIsEnabled(GL_TEXTURE_COORD_ARRAY) == GL_FALSE;
} else {
ret &= glIsEnabled(GL_TEXTURE_2D) == GL_FALSE;
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &temp);
ret &= temp == GL_REPLACE;
ret &= glIsEnabled(GL_TEXTURE_COORD_ARRAY) == GL_FALSE;
}
ret &= glIsEnabled(GL_LIGHTING) == GL_FALSE;
ret &= glIsEnabled(GL_COLOR_ARRAY) == GL_FALSE;
ret &= glIsEnabled(GL_VERTEX_ARRAY) == GL_FALSE;
ret &= glIsEnabled(GL_NORMAL_ARRAY) == GL_FALSE;
if (dglDoesSupportFogCoord())
ret &= glIsEnabled(GL_FOG_COORDINATE_ARRAY_EXT) == GL_FALSE;
return ret;
}
void dglSetCanonicalState()
{
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
glBlendFunc(GL_ONE, GL_ZERO);
glDisable(GL_LIGHTING);
if (dglDoesSupportARBMultitexture() == true) {
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glActiveTextureARB(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
} else {
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (dglDoesSupportFogCoord())
glDisableClientState(GL_FOG_COORDINATE_ARRAY_EXT);
}
void dglGetTransformState(S32* mvDepth,
S32* pDepth,
S32* t0Depth,
F32* t0Matrix,
S32* t1Depth,
F32* t1Matrix,
S32* vp)
{
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, mvDepth);
glGetIntegerv(GL_PROJECTION_STACK_DEPTH, pDepth);
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, t0Depth);
glGetFloatv(GL_TEXTURE_MATRIX, t0Matrix);
if (dglDoesSupportARBMultitexture())
{
glActiveTextureARB(GL_TEXTURE1_ARB);
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, t1Depth);
glGetFloatv(GL_TEXTURE_MATRIX, t1Matrix);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
else
{
*t1Depth = 0;
for (U32 i = 0; i < 16; i++)
t1Matrix[i] = 0;
}
RectI v;
dglGetViewport(&v);
vp[0] = v.point.x;
vp[1] = v.point.y;
vp[2] = v.extent.x;
vp[3] = v.extent.y;
}
bool dglCheckState(const S32 mvDepth, const S32 pDepth,
const S32 t0Depth, const F32* t0Matrix,
const S32 t1Depth, const F32* t1Matrix,
const S32* vp)
{
GLint md, pd;
RectI v;
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &md);
glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &pd);
GLint t0d, t1d;
GLfloat t0m[16], t1m[16];
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &t0d);
glGetFloatv(GL_TEXTURE_MATRIX, t0m);
if (dglDoesSupportARBMultitexture())
{
glActiveTextureARB(GL_TEXTURE1_ARB);
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &t1d);
glGetFloatv(GL_TEXTURE_MATRIX, t1m);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
else
{
t1d = 0;
for (U32 i = 0; i < 16; i++)
t1m[i] = 0;
}
dglGetViewport(&v);
return ((md == mvDepth) &&
(pd == pDepth) &&
(t0d == t0Depth) &&
(dMemcmp(t0m, t0Matrix, sizeof(F32) * 16) == 0) &&
(t1d == t1Depth) &&
(dMemcmp(t1m, t1Matrix, sizeof(F32) * 16) == 0) &&
((v.point.x == vp[0]) &&
(v.point.y == vp[1]) &&
(v.extent.x == vp[2]) &&
(v.extent.y == vp[3])));
}