calculate screen bounding boxes for each mesh object

This commit is contained in:
Pawel Kolodziejski 2008-09-26 11:59:46 +00:00
parent f5d455b561
commit 9ad158effd
7 changed files with 193 additions and 3 deletions

View file

@ -84,6 +84,7 @@ public:
virtual void clearScreen() = 0; virtual void clearScreen() = 0;
virtual void flipBuffer() = 0; virtual void flipBuffer() = 0;
virtual void getBoundingBoxPos(const Model::Mesh *model, int *x1, int *y1, int *x2, int *y2) = 0;
virtual void startActorDraw(Vector3d pos, float yaw, float pitch, float roll) = 0; virtual void startActorDraw(Vector3d pos, float yaw, float pitch, float roll) = 0;
virtual void finishActorDraw() = 0; virtual void finishActorDraw() = 0;
virtual void setShadow(Shadow *shadow) = 0; virtual void setShadow(Shadow *shadow) = 0;

View file

@ -182,6 +182,72 @@ static void glShadowProjection(Vector3d light, Vector3d plane, Vector3d normal,
glMultMatrixf((GLfloat *)mat); glMultMatrixf((GLfloat *)mat);
} }
void DriverGL::getBoundingBoxPos(const Model::Mesh *model, int *x1, int *y1, int *x2, int *y2) {
if (_currentShadowArray)
return;
GLfloat top = 1000;
GLfloat right = -1000;
GLfloat left = 1000;
GLfloat bottom = -1000;
GLdouble winX, winY, winZ;
for (int i = 0; i < model->_numFaces; i++) {
Vector3d v;
float* pVertices;
for (int j = 0; j < model->_faces[i]._numVertices; j++) {
GLdouble modelView[16], projection[16];
GLint viewPort[4];
glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewPort);
pVertices = model->_vertices + 3 * model->_faces[i]._vertices[j];
v.set(*(pVertices), *(pVertices + 1), *(pVertices + 2));
gluProject(v.x(), v.y(), v.z(), modelView, projection, viewPort, &winX, &winY, &winZ);
if (winX > right)
right = winX;
if (winX < left)
left = winX;
if (winY < top)
top = winY;
if (winY > bottom)
bottom = winY;
}
}
float t = bottom;
bottom = 480 - top;
top = 480 - t;
if (left < 0)
left = 0;
if (right > 639)
right = 639;
if (top < 0)
top = 0;
if (bottom > 479)
bottom = 479;
if (top > 479 || left > 639 || bottom < 0 || right < 0) {
*x1 = -1;
*y1 = -1;
*x2 = -1;
*y2 = -1;
return;
}
*x1 = (int)left;
*y1 = (int)top;
*x2 = (int)right;
*y2 = (int)bottom;
}
void DriverGL::startActorDraw(Vector3d pos, float yaw, float pitch, float roll) { void DriverGL::startActorDraw(Vector3d pos, float yaw, float pitch, float roll) {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);

View file

@ -55,6 +55,8 @@ public:
bool isHardwareAccelerated(); bool isHardwareAccelerated();
void getBoundingBoxPos(const Model::Mesh *model, int *x1, int *y1, int *x2, int *y2);
void startActorDraw(Vector3d pos, float yaw, float pitch, float roll); void startActorDraw(Vector3d pos, float yaw, float pitch, float roll);
void finishActorDraw(); void finishActorDraw();
void setShadow(Shadow *shadow); void setShadow(Shadow *shadow);

View file

@ -36,7 +36,7 @@
#include "engine/tinygl/gl.h" #include "engine/tinygl/gl.h"
#include "engine/tinygl/zgl.h" #include "engine/tinygl/zgl.h"
// func below is from Mesa glu sources // below funcs lookAt, transformPoint and tgluProject are from Mesa glu sources
static void lookAt(TGLfloat eyex, TGLfloat eyey, TGLfloat eyez, TGLfloat centerx, static void lookAt(TGLfloat eyex, TGLfloat eyey, TGLfloat eyez, TGLfloat centerx,
TGLfloat centery, TGLfloat centerz, TGLfloat upx, TGLfloat upy, TGLfloat upz) { TGLfloat centery, TGLfloat centerz, TGLfloat upx, TGLfloat upy, TGLfloat upz) {
TGLfloat m[16]; TGLfloat m[16];
@ -102,6 +102,40 @@ static void lookAt(TGLfloat eyex, TGLfloat eyey, TGLfloat eyez, TGLfloat centerx
tglTranslatef(-eyex, -eyey, -eyez); tglTranslatef(-eyex, -eyey, -eyez);
} }
static void transformPoint(TGLfloat out[4], const TGLfloat m[16], const TGLfloat in[4]) {
#define M(row,col) m[col * 4 + row]
out[0] = M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
out[1] = M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
out[2] = M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
out[3] = M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
#undef M
}
TGLint tgluProject(TGLfloat objx, TGLfloat objy, TGLfloat objz, const TGLfloat model[16], const TGLfloat proj[16],
const TGLint viewport[4], TGLfloat *winx, TGLfloat *winy, TGLfloat *winz) {
TGLfloat in[4], out[4];
in[0] = objx;
in[1] = objy;
in[2] = objz;
in[3] = 1.0;
transformPoint(out, model, in);
transformPoint(in, proj, out);
if (in[3] == 0.0)
return TGL_FALSE;
in[0] /= in[3];
in[1] /= in[3];
in[2] /= in[3];
*winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
*winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
*winz = (1 + in[2]) / 2;
return TGL_TRUE;
}
DriverTinyGL::DriverTinyGL(int screenW, int screenH, int screenBPP, bool fullscreen) { DriverTinyGL::DriverTinyGL(int screenW, int screenH, int screenBPP, bool fullscreen) {
uint32 flags = SDL_HWSURFACE; uint32 flags = SDL_HWSURFACE;
@ -241,6 +275,87 @@ static void tglShadowProjection(Vector3d light, Vector3d plane, Vector3d normal,
tglMultMatrixf(mat); tglMultMatrixf(mat);
} }
void DriverTinyGL::getBoundingBoxPos(const Model::Mesh *model, int *x1, int *y1, int *x2, int *y2) {
if (_currentShadowArray)
return;
TGLfloat top = 1000;
TGLfloat right = -1000;
TGLfloat left = 1000;
TGLfloat bottom = -1000;
TGLfloat winX, winY, winZ;
for (int i = 0; i < model->_numFaces; i++) {
Vector3d v;
float* pVertices;
for (int j = 0; j < model->_faces[i]._numVertices; j++) {
TGLfloat modelView[16], projection[16];
TGLint viewPort[4];
tglGetFloatv(TGL_MODELVIEW_MATRIX, modelView);
tglGetFloatv(TGL_PROJECTION_MATRIX, projection);
tglGetIntegerv(TGL_VIEWPORT, viewPort);
pVertices = model->_vertices + 3 * model->_faces[i]._vertices[j];
v.set(*(pVertices), *(pVertices + 1), *(pVertices + 2));
tgluProject(v.x(), v.y(), v.z(), modelView, projection, viewPort, &winX, &winY, &winZ);
if (winX > right)
right = winX;
if (winX < left)
left = winX;
if (winY < top)
top = winY;
if (winY > bottom)
bottom = winY;
}
}
float t = bottom;
bottom = 480 - top;
top = 480 - t;
if (left < 0)
left = 0;
if (right > 639)
right = 639;
if (top < 0)
top = 0;
if (bottom > 479)
bottom = 479;
if (top > 479 || left > 639 || bottom < 0 || right < 0) {
*x1 = -1;
*y1 = -1;
*x2 = -1;
*y2 = -1;
return;
}
*x1 = (int)left;
*y1 = (int)top;
*x2 = (int)right;
*y2 = (int)bottom;
/*
uint16 *dst = (uint16 *)_zb->pbuf;
uint16 c = 0xffff;
for (int x = left; x <= right; x++) {
WRITE_LE_UINT16(dst + 640 * (int)top + x, c);
}
for (int x = left; x <= right; x++) {
WRITE_LE_UINT16(dst + 640 * (int)bottom + x, c);
}
for (int y = top; y <= bottom; y++) {
WRITE_LE_UINT16(dst + 640 * y + (int)left, c);
}
for (int y = top; y <= bottom; y++) {
WRITE_LE_UINT16(dst + 640 * y + (int)right, c);
}*/
}
void DriverTinyGL::startActorDraw(Vector3d pos, float yaw, float pitch, float roll) { void DriverTinyGL::startActorDraw(Vector3d pos, float yaw, float pitch, float roll) {
tglEnable(TGL_TEXTURE_2D); tglEnable(TGL_TEXTURE_2D);
tglMatrixMode(TGL_MODELVIEW); tglMatrixMode(TGL_MODELVIEW);
@ -254,6 +369,7 @@ void DriverTinyGL::startActorDraw(Vector3d pos, float yaw, float pitch, float ro
Sector *shadowSector = *i; Sector *shadowSector = *i;
tglShadowProjection(_currentShadowArray->pos, shadowSector->getVertices()[0], shadowSector->getNormal(), _currentShadowArray->dontNegate); tglShadowProjection(_currentShadowArray->pos, shadowSector->getVertices()[0], shadowSector->getNormal(), _currentShadowArray->dontNegate);
} }
tglTranslatef(pos.x(), pos.y(), pos.z()); tglTranslatef(pos.x(), pos.y(), pos.z());
tglRotatef(yaw, 0, 0, 1); tglRotatef(yaw, 0, 0, 1);
tglRotatef(pitch, 1, 0, 0); tglRotatef(pitch, 1, 0, 0);

View file

@ -55,6 +55,8 @@ public:
bool isHardwareAccelerated(); bool isHardwareAccelerated();
void getBoundingBoxPos(const Model::Mesh *model, int *x1, int *y1, int *x2, int *y2);
void startActorDraw(Vector3d pos, float yaw, float pitch, float roll); void startActorDraw(Vector3d pos, float yaw, float pitch, float roll);
void finishActorDraw(); void finishActorDraw();
void setShadow(Shadow *shadow); void setShadow(Shadow *shadow);

View file

@ -503,6 +503,9 @@ void Model::HierNode::update() {
} }
void Model::Mesh::draw() const { void Model::Mesh::draw() const {
int winX1, winY1, winX2, winY2;
g_driver->getBoundingBoxPos(this, &winX1, &winY1, &winX2, &winY2);
for (int i = 0; i < _numFaces; i++) for (int i = 0; i < _numFaces; i++)
_faces[i].draw(_vertices, _vertNormals, _textureVerts); _faces[i].draw(_vertices, _vertNormals, _textureVerts);
} }

View file

@ -1,7 +1,7 @@
#include "engine/tinygl/zgl.h" #include "engine/tinygl/zgl.h"
void glGetIntegerv(int pname,int *params) { void tglGetIntegerv(int pname,int *params) {
GLContext *c=gl_get_context(); GLContext *c=gl_get_context();
switch (pname) { switch (pname) {
@ -32,7 +32,7 @@ void glGetIntegerv(int pname,int *params) {
} }
} }
void glGetFloatv(int pname, float *v) { void tglGetFloatv(int pname, float *v) {
int i; int i;
int mnr = 0; // just a trick to return the correct matrix int mnr = 0; // just a trick to return the correct matrix
GLContext *c = gl_get_context(); GLContext *c = gl_get_context();