calculate screen bounding boxes for each mesh object
This commit is contained in:
parent
f5d455b561
commit
9ad158effd
7 changed files with 193 additions and 3 deletions
|
@ -84,6 +84,7 @@ public:
|
|||
virtual void clearScreen() = 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 finishActorDraw() = 0;
|
||||
virtual void setShadow(Shadow *shadow) = 0;
|
||||
|
|
|
@ -182,6 +182,72 @@ static void glShadowProjection(Vector3d light, Vector3d plane, Vector3d normal,
|
|||
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) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
|
||||
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 finishActorDraw();
|
||||
void setShadow(Shadow *shadow);
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "engine/tinygl/gl.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,
|
||||
TGLfloat centery, TGLfloat centerz, TGLfloat upx, TGLfloat upy, TGLfloat upz) {
|
||||
TGLfloat m[16];
|
||||
|
@ -102,6 +102,40 @@ static void lookAt(TGLfloat eyex, TGLfloat eyey, TGLfloat eyez, TGLfloat centerx
|
|||
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) {
|
||||
uint32 flags = SDL_HWSURFACE;
|
||||
|
||||
|
@ -241,6 +275,87 @@ static void tglShadowProjection(Vector3d light, Vector3d plane, Vector3d normal,
|
|||
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) {
|
||||
tglEnable(TGL_TEXTURE_2D);
|
||||
tglMatrixMode(TGL_MODELVIEW);
|
||||
|
@ -254,6 +369,7 @@ void DriverTinyGL::startActorDraw(Vector3d pos, float yaw, float pitch, float ro
|
|||
Sector *shadowSector = *i;
|
||||
tglShadowProjection(_currentShadowArray->pos, shadowSector->getVertices()[0], shadowSector->getNormal(), _currentShadowArray->dontNegate);
|
||||
}
|
||||
|
||||
tglTranslatef(pos.x(), pos.y(), pos.z());
|
||||
tglRotatef(yaw, 0, 0, 1);
|
||||
tglRotatef(pitch, 1, 0, 0);
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
|
||||
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 finishActorDraw();
|
||||
void setShadow(Shadow *shadow);
|
||||
|
|
|
@ -503,6 +503,9 @@ void Model::HierNode::update() {
|
|||
}
|
||||
|
||||
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++)
|
||||
_faces[i].draw(_vertices, _vertNormals, _textureVerts);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#include "engine/tinygl/zgl.h"
|
||||
|
||||
void glGetIntegerv(int pname,int *params) {
|
||||
void tglGetIntegerv(int pname,int *params) {
|
||||
GLContext *c=gl_get_context();
|
||||
|
||||
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 mnr = 0; // just a trick to return the correct matrix
|
||||
GLContext *c = gl_get_context();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue