Now we can know the position of each node/polygon/point of the animated model before it's even drawn on screen. We can also know the position of the points on screen (and the depth of those points). The dirty box of the models is now computed (in a debug fashion). Somehow, models head are still bugged but it's probably due to the fact that they are not animated (and not initialised). The debug display is left activated to let Endy see the results and implement a better zbuffer refresh system
648 lines
18 KiB
C++
648 lines
18 KiB
C++
// Residual - Virtual machine to run LucasArts' 3D adventure games
|
|
// Copyright (C) 2003 The ScummVM-Residual Team (www.scummvm.org)
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
// This library 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
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#include "stdafx.h"
|
|
#include "model.h"
|
|
#include "bits.h"
|
|
#include "resource.h"
|
|
#include "material.h"
|
|
#include "debug.h"
|
|
#include "textsplit.h"
|
|
#include <cstring>
|
|
#include <SDL.h>
|
|
#include <SDL_opengl.h>
|
|
|
|
Model::Model(const char *filename, const char *data, int len,
|
|
const Colormap &cmap) : Resource(filename)
|
|
{
|
|
if (len >= 4 && std::memcmp(data, "LDOM", 4) == 0)
|
|
loadBinary(data, cmap);
|
|
else {
|
|
TextSplitter ts(data, len);
|
|
loadText(ts, cmap);
|
|
}
|
|
}
|
|
|
|
void Model::loadBinary(const char *data, const Colormap &cmap) {
|
|
numMaterials_ = get_LE_uint32(data + 4);
|
|
data += 8;
|
|
materials_ = new ResPtr<Material>[numMaterials_];
|
|
for (int i = 0; i < numMaterials_; i++) {
|
|
materials_[i] = ResourceLoader::instance()->loadMaterial(data, cmap);
|
|
data += 32;
|
|
}
|
|
data += 32; // skip name
|
|
numGeosets_ = get_LE_uint32(data + 4);
|
|
data += 8;
|
|
geosets_ = new Geoset[numGeosets_];
|
|
for (int i = 0; i < numGeosets_; i++)
|
|
geosets_[i].loadBinary(data, materials_);
|
|
numHierNodes_ = get_LE_uint32(data + 4);
|
|
data += 8;
|
|
rootHierNode_ = new HierNode[numHierNodes_];
|
|
for (int i = 0; i < numHierNodes_; i++)
|
|
rootHierNode_[i].loadBinary(data, rootHierNode_, geosets_[0]);
|
|
radius_ = get_float(data);
|
|
insertOffset_ = get_vector3d(data + 40);
|
|
}
|
|
|
|
Model::~Model() {
|
|
delete[] materials_;
|
|
delete[] geosets_;
|
|
delete[] rootHierNode_;
|
|
}
|
|
|
|
void Model::Geoset::loadBinary(const char *&data,
|
|
ResPtr<Material> *materials) {
|
|
numMeshes_ = get_LE_uint32(data);
|
|
data += 4;
|
|
meshes_ = new Mesh[numMeshes_];
|
|
for (int i = 0; i < numMeshes_; i++)
|
|
meshes_[i].loadBinary(data, materials);
|
|
}
|
|
|
|
Model::Geoset::~Geoset() {
|
|
delete[] meshes_;
|
|
}
|
|
|
|
void Model::Mesh::loadBinary(const char *&data,
|
|
ResPtr<Material> *materials) {
|
|
memcpy(name_, data, 32);
|
|
geometryMode_ = get_LE_uint32(data + 36);
|
|
lightingMode_ = get_LE_uint32(data + 40);
|
|
textureMode_ = get_LE_uint32(data + 44);
|
|
numVertices_ = get_LE_uint32(data + 48);
|
|
numTextureVerts_ = get_LE_uint32(data + 52);
|
|
numFaces_ = get_LE_uint32(data + 56);
|
|
vertices_ = new float[3 * numVertices_];
|
|
verticesI_ = new float[numVertices_];
|
|
vertNormals_ = new float[3 * numVertices_];
|
|
textureVerts_ = new float[2 * numTextureVerts_];
|
|
data += 60;
|
|
for (int i = 0; i < 3 * numVertices_; i++) {
|
|
vertices_[i] = get_float(data);
|
|
data += 4;
|
|
}
|
|
for (int i = 0; i < 2 * numTextureVerts_; i++) {
|
|
textureVerts_[i] = get_float(data);
|
|
data += 4;
|
|
}
|
|
for (int i = 0; i < numVertices_; i++) {
|
|
verticesI_[i] = get_float(data);
|
|
data += 4;
|
|
}
|
|
data += numVertices_ * 4;
|
|
faces_ = new Face[numFaces_];
|
|
for (int i = 0; i < numFaces_; i++)
|
|
faces_[i].loadBinary(data, materials);
|
|
vertNormals_ = new float[3 * numVertices_];
|
|
for (int i = 0; i < 3 * numVertices_; i++) {
|
|
vertNormals_[i] = get_float(data);
|
|
data += 4;
|
|
}
|
|
shadow_ = get_LE_uint32(data);
|
|
radius_ = get_float(data + 8);
|
|
data += 36;
|
|
}
|
|
|
|
Model::Mesh::~Mesh() {
|
|
delete[] vertices_;
|
|
delete[] verticesI_;
|
|
delete[] vertNormals_;
|
|
delete[] textureVerts_;
|
|
delete[] faces_;
|
|
}
|
|
|
|
void Model::Face::loadBinary(const char *&data, ResPtr<Material> *materials) {
|
|
type_ = get_LE_uint32(data + 4);
|
|
geo_ = get_LE_uint32(data + 8);
|
|
light_ = get_LE_uint32(data + 12);
|
|
tex_ = get_LE_uint32(data + 16);
|
|
numVertices_ = get_LE_uint32(data + 20);
|
|
int texPtr = get_LE_uint32(data + 28);
|
|
int materialPtr = get_LE_uint32(data + 32);
|
|
extraLight_ = get_float(data + 48);
|
|
normal_ = get_vector3d(data + 64);
|
|
data += 76;
|
|
|
|
vertices_ = new int[numVertices_];
|
|
for (int i = 0; i < numVertices_; i++) {
|
|
vertices_[i] = get_LE_uint32(data);
|
|
data += 4;
|
|
}
|
|
if (texPtr == 0)
|
|
texVertices_ = NULL;
|
|
else {
|
|
texVertices_ = new int[numVertices_];
|
|
for (int i = 0; i < numVertices_; i++) {
|
|
texVertices_[i] = get_LE_uint32(data);
|
|
data += 4;
|
|
}
|
|
}
|
|
if (materialPtr == 0)
|
|
material_ = 0;
|
|
else {
|
|
material_ = materials[get_LE_uint32(data)];
|
|
data += 4;
|
|
}
|
|
}
|
|
|
|
Model::Face::~Face() {
|
|
delete[] vertices_;
|
|
delete[] texVertices_;
|
|
}
|
|
|
|
void Model::HierNode::loadBinary(const char *&data,
|
|
Model::HierNode *hierNodes,
|
|
const Geoset &g) {
|
|
memcpy(name_, data, 64);
|
|
flags_ = get_LE_uint32(data + 64);
|
|
type_ = get_LE_uint32(data + 72);
|
|
int meshNum = get_LE_uint32(data + 76);
|
|
if (meshNum < 0)
|
|
mesh_ = NULL;
|
|
else
|
|
mesh_ = g.meshes_ + meshNum;
|
|
depth_ = get_LE_uint32(data + 80);
|
|
int parentPtr = get_LE_uint32(data + 84);
|
|
numChildren_ = get_LE_uint32(data + 88);
|
|
int childPtr = get_LE_uint32(data + 92);
|
|
int siblingPtr = get_LE_uint32(data + 96);
|
|
pivot_ = get_vector3d(data + 100);
|
|
pos_ = get_vector3d(data + 112);
|
|
pitch_ = get_float(data + 124);
|
|
yaw_ = get_float(data + 128);
|
|
roll_ = get_float(data + 132);
|
|
data += 184;
|
|
|
|
if (parentPtr != 0) {
|
|
parent_ = hierNodes + get_LE_uint32(data);
|
|
data += 4;
|
|
}
|
|
else
|
|
parent_ = NULL;
|
|
if (childPtr != 0) {
|
|
child_ = hierNodes + get_LE_uint32(data);
|
|
data += 4;
|
|
}
|
|
else
|
|
child_ = NULL;
|
|
if (siblingPtr != 0) {
|
|
sibling_ = hierNodes + get_LE_uint32(data);
|
|
data += 4;
|
|
}
|
|
else
|
|
sibling_ = NULL;
|
|
|
|
meshVisible_ = hierVisible_ = true;
|
|
totalWeight_ = 1;
|
|
}
|
|
|
|
void Model::draw() const {
|
|
rootHierNode_->draw();
|
|
}
|
|
|
|
Model::HierNode *Model::copyHierarchy() {
|
|
HierNode *result = new HierNode[numHierNodes_];
|
|
std::memcpy(result, rootHierNode_, numHierNodes_ * sizeof(HierNode));
|
|
// Now adjust pointers
|
|
for (int i = 0; i < numHierNodes_; i++) {
|
|
if (result[i].parent_ != NULL)
|
|
result[i].parent_ = result + (rootHierNode_[i].parent_ - rootHierNode_);
|
|
if (result[i].child_ != NULL)
|
|
result[i].child_ = result + (rootHierNode_[i].child_ - rootHierNode_);
|
|
if (result[i].sibling_ != NULL)
|
|
result[i].sibling_ = result + (rootHierNode_[i].sibling_ -
|
|
rootHierNode_);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Model::loadText(TextSplitter &ts, const Colormap &cmap) {
|
|
ts.expectString("section: header");
|
|
int major, minor;
|
|
ts.scanString("3do %d.%d", 2, &major, &minor);
|
|
|
|
ts.expectString("section: modelresource");
|
|
ts.scanString("materials %d", 1, &numMaterials_);
|
|
materials_ = new ResPtr<Material>[numMaterials_];
|
|
for (int i = 0; i < numMaterials_; i++) {
|
|
int num;
|
|
char name[32];
|
|
ts.scanString("%d: %32s", 2, &num, name);
|
|
materials_[num] = ResourceLoader::instance()->loadMaterial(name, cmap);
|
|
}
|
|
|
|
ts.expectString("section: geometrydef");
|
|
ts.scanString("radius %f", 1, &radius_);
|
|
ts.scanString("insert offset %f %f %f", 3,
|
|
&insertOffset_.x(), &insertOffset_.y(), &insertOffset_.z());
|
|
ts.scanString("geosets %d", 1, &numGeosets_);
|
|
geosets_ = new Geoset[numGeosets_];
|
|
for (int i = 0; i < numGeosets_; i++) {
|
|
int num;
|
|
ts.scanString("geoset %d", 1, &num);
|
|
geosets_[num].loadText(ts, materials_);
|
|
}
|
|
|
|
ts.expectString("section: hierarchydef");
|
|
ts.scanString("hierarchy nodes %d", 1, &numHierNodes_);
|
|
rootHierNode_ = new HierNode[numHierNodes_];
|
|
for (int i = 0; i < numHierNodes_; i++) {
|
|
int num, flags, type, mesh, parent, child, sibling, numChildren;
|
|
float x, y, z, pitch, yaw, roll, pivotx, pivoty, pivotz;
|
|
char name[64];
|
|
ts.scanString(" %d: %i %i %d %d %d %d %d %f %f %f %f %f %f %f %f %f %64s",
|
|
18, &num, &flags, &type, &mesh, &parent, &child, &sibling,
|
|
&numChildren, &x, &y, &z, &pitch, &yaw, &roll,
|
|
&pivotx, &pivoty, &pivotz, name);
|
|
rootHierNode_[num].flags_ = flags;
|
|
rootHierNode_[num].type_ = type;
|
|
if (mesh < 0)
|
|
rootHierNode_[num].mesh_ = NULL;
|
|
else
|
|
rootHierNode_[num].mesh_ = geosets_[0].meshes_ + mesh;
|
|
if (parent >= 0) {
|
|
rootHierNode_[num].parent_ = rootHierNode_ + parent;
|
|
rootHierNode_[num].depth_ = rootHierNode_[parent].depth_ + 1;
|
|
}
|
|
else {
|
|
rootHierNode_[num].parent_ = NULL;
|
|
rootHierNode_[num].depth_ = 0;
|
|
}
|
|
if (child >= 0)
|
|
rootHierNode_[num].child_ = rootHierNode_ + child;
|
|
else
|
|
rootHierNode_[num].child_ = NULL;
|
|
if (sibling >= 0)
|
|
rootHierNode_[num].sibling_ = rootHierNode_ + sibling;
|
|
else
|
|
rootHierNode_[num].sibling_ = NULL;
|
|
rootHierNode_[num].numChildren_ = numChildren;
|
|
rootHierNode_[num].pos_ = Vector3d(x, y, z);
|
|
rootHierNode_[num].pitch_ = pitch;
|
|
rootHierNode_[num].yaw_ = yaw;
|
|
rootHierNode_[num].roll_ = roll;
|
|
rootHierNode_[num].pivot_ = Vector3d(pivotx, pivoty, pivotz);
|
|
|
|
rootHierNode_[num].meshVisible_ =
|
|
rootHierNode_[num].hierVisible_ = true;
|
|
rootHierNode_[num].totalWeight_ = 1;
|
|
}
|
|
if (! ts.eof())
|
|
warning("Unexpected junk at end of model text\n");
|
|
}
|
|
|
|
void Model::Geoset::loadText(TextSplitter &ts, ResPtr<Material> *materials) {
|
|
ts.scanString("meshes %d", 1, &numMeshes_);
|
|
meshes_ = new Mesh[numMeshes_];
|
|
for (int i = 0; i < numMeshes_; i++) {
|
|
int num;
|
|
ts.scanString("mesh %d", 1, &num);
|
|
meshes_[num].loadText(ts, materials);
|
|
}
|
|
}
|
|
|
|
void Model::Mesh::loadText(TextSplitter &ts, ResPtr<Material> *materials) {
|
|
ts.scanString("name %32s", 1, name_);
|
|
ts.scanString("radius %f", 1, &radius_);
|
|
|
|
// In data001/rope_scale.3do, the shadow line is missing
|
|
if (std::sscanf(ts.currentLine(), "shadow %d", &shadow_) < 1) {
|
|
shadow_ = 0;
|
|
warning("Missing shadow directive in model\n");
|
|
}
|
|
else
|
|
ts.nextLine();
|
|
ts.scanString("geometrymode %d", 1, &geometryMode_);
|
|
ts.scanString("lightingmode %d", 1, &lightingMode_);
|
|
ts.scanString("texturemode %d", 1, &textureMode_);
|
|
ts.scanString("vertices %d", 1, &numVertices_);
|
|
vertices_ = new float[3 * numVertices_];
|
|
verticesI_ = new float[numVertices_];
|
|
vertNormals_ = new float[3 * numVertices_];
|
|
|
|
for (int i = 0; i < numVertices_; i++) {
|
|
int num;
|
|
float x, y, z, ival;
|
|
ts.scanString(" %d: %f %f %f %f", 5, &num, &x, &y, &z, &ival);
|
|
vertices_[3 * num] = x;
|
|
vertices_[3 * num + 1] = y;
|
|
vertices_[3 * num + 2] = z;
|
|
verticesI_[num] = ival;
|
|
}
|
|
|
|
ts.scanString("texture vertices %d", 1, &numTextureVerts_);
|
|
textureVerts_ = new float[2 * numTextureVerts_];
|
|
|
|
for (int i = 0; i < numTextureVerts_; i++) {
|
|
int num;
|
|
float x, y;
|
|
ts.scanString(" %d: %f %f", 3, &num, &x, &y);
|
|
textureVerts_[2 * num] = x;
|
|
textureVerts_[2 * num + 1] = y;
|
|
}
|
|
|
|
ts.expectString("vertex normals");
|
|
for (int i = 0; i < numVertices_; i++) {
|
|
int num;
|
|
float x, y, z;
|
|
ts.scanString(" %d: %f %f %f", 4, &num, &x, &y, &z);
|
|
vertNormals_[3 * num] = x;
|
|
vertNormals_[3 * num + 1] = y;
|
|
vertNormals_[3 * num + 2] = z;
|
|
}
|
|
|
|
ts.scanString("faces %d", 1, &numFaces_);
|
|
faces_ = new Face[numFaces_];
|
|
for (int i = 0; i < numFaces_; i++) {
|
|
int num, material, type, geo, light, tex, verts;
|
|
float extralight;
|
|
int readlen;
|
|
if (ts.eof())
|
|
error("Expected face data, got EOF\n");
|
|
if (std::sscanf(ts.currentLine(), " %d: %d %i %d %d %d %f %d%n",
|
|
&num, &material, &type, &geo, &light, &tex, &extralight,
|
|
&verts, &readlen) < 8)
|
|
error("Expected face data, got `%s'\n", ts.currentLine());
|
|
faces_[num].material_ = materials[material];
|
|
faces_[num].type_ = type;
|
|
faces_[num].geo_ = geo;
|
|
faces_[num].light_ = light;
|
|
faces_[num].tex_ = tex;
|
|
faces_[num].extraLight_ = extralight;
|
|
faces_[num].numVertices_ = verts;
|
|
faces_[num].vertices_ = new int[verts];
|
|
faces_[num].texVertices_ = new int[verts];
|
|
for (int j = 0; j < verts; j++) {
|
|
int readlen2;
|
|
if (std::sscanf(ts.currentLine() + readlen, " %d, %d%n",
|
|
faces_[num].vertices_ + j,
|
|
faces_[num].texVertices_ + j, &readlen2) < 2)
|
|
error("Could not read vertex indices in line `%s'\n",
|
|
ts.currentLine());
|
|
readlen += readlen2;
|
|
}
|
|
ts.nextLine();
|
|
}
|
|
|
|
ts.expectString("face normals");
|
|
for (int i = 0; i < numFaces_; i++) {
|
|
int num;
|
|
float x, y, z;
|
|
ts.scanString(" %d: %f %f %f", 4, &num, &x, &y, &z);
|
|
faces_[num].normal_ = Vector3d(x, y, z);
|
|
}
|
|
}
|
|
|
|
void Model::HierNode::draw() const {
|
|
if (hierVisible_) {
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
|
|
glTranslatef(animPos_.x() / totalWeight_, animPos_.y() / totalWeight_,
|
|
animPos_.z() / totalWeight_);
|
|
glRotatef(animYaw_ / totalWeight_, 0, 0, 1);
|
|
glRotatef(animPitch_ / totalWeight_, 1, 0, 0);
|
|
glRotatef(animRoll_ / totalWeight_, 0, 1, 0);
|
|
|
|
if (mesh_ != NULL && meshVisible_) {
|
|
glPushMatrix();
|
|
glTranslatef(pivot_.x(), pivot_.y(), pivot_.z());
|
|
mesh_->draw();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
}
|
|
if (child_ != NULL) {
|
|
child_->draw();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
glPopMatrix();
|
|
}
|
|
if (sibling_ != NULL)
|
|
sibling_->draw();
|
|
}
|
|
|
|
void Model::HierNode::addChild(HierNode *child) {
|
|
HierNode **childPos = &child_;
|
|
while (*childPos != NULL)
|
|
childPos = &(*childPos)->sibling_;
|
|
*childPos = child;
|
|
child->parent_ = this;
|
|
}
|
|
|
|
void Model::HierNode::removeChild(HierNode *child) {
|
|
HierNode **childPos = &child_;
|
|
while (*childPos != NULL && *childPos != child)
|
|
childPos = &(*childPos)->sibling_;
|
|
if (*childPos != NULL) {
|
|
*childPos = child->sibling_;
|
|
child->parent_ = NULL;
|
|
}
|
|
}
|
|
|
|
void Model::HierNode::setMatrix(Matrix4 matrix) {
|
|
matrix_ = matrix;
|
|
}
|
|
|
|
void Model::HierNode::update() {
|
|
localMatrix_.pos_.set( animPos_.x() / totalWeight_, animPos_.y() / totalWeight_, animPos_.z() / totalWeight_ );
|
|
localMatrix_.rot_.buildFromPitchYawRoll( animPitch_ / totalWeight_, animYaw_ / totalWeight_, animRoll_ / totalWeight_);
|
|
|
|
matrix_ *= localMatrix_;
|
|
|
|
pivotMatrix = matrix_;
|
|
|
|
pivotMatrix.translate( pivot_.x(), pivot_.y(), pivot_.z() );
|
|
|
|
if( mesh_ != NULL )
|
|
{
|
|
mesh_->matrix_ = pivotMatrix;
|
|
}
|
|
|
|
if( child_ != NULL )
|
|
{
|
|
child_->setMatrix( matrix_ );
|
|
child_->update();
|
|
}
|
|
}
|
|
|
|
|
|
void Model::Mesh::draw() const {
|
|
for (int i = 0; i < numFaces_; i++)
|
|
faces_[i].draw(vertices_, vertNormals_, textureVerts_);
|
|
|
|
// Yaz: debug
|
|
// this draw the model node in red
|
|
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glDisable(GL_DEPTH_TEST);
|
|
glPointSize( 3.f );
|
|
glColor4f( 1.f, 0.f, 0.f, 1.f );
|
|
glDisable(GL_TEXTURE_2D );
|
|
glBegin( GL_POINTS );
|
|
glVertex3f( matrix_.pos_.x(), matrix_.pos_.y(), matrix_.pos_.z() );
|
|
glEnd();
|
|
glEnable(GL_DEPTH_TEST);
|
|
glPopMatrix();
|
|
glEnable(GL_TEXTURE_2D );
|
|
|
|
// Yaz: debug
|
|
// this draw the poly points
|
|
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glPointSize( 3.f );
|
|
glColor4f( 0.f, 1.f, 0.f, 1.f );
|
|
glDisable(GL_TEXTURE_2D );
|
|
glBegin( GL_POINTS );
|
|
|
|
for (int i = 0; i < numFaces_; i++)
|
|
{
|
|
Vector3d v;
|
|
Matrix4 tempMatrix = matrix_;
|
|
float* pVertices;
|
|
int j;
|
|
|
|
for( j =0; j< faces_[i].numVertices_; j++ )
|
|
{
|
|
pVertices = vertices_ + 3 * faces_[i].vertices_[j];
|
|
|
|
v.set( *(pVertices), *(pVertices+1), *(pVertices+2) );
|
|
|
|
tempMatrix.rot_.transform( v );
|
|
v+= tempMatrix.pos_;
|
|
|
|
glVertex3f( v.x(), v.y(), v.z() );
|
|
|
|
}
|
|
}
|
|
|
|
glEnd();
|
|
glEnable(GL_DEPTH_TEST);
|
|
glPopMatrix();
|
|
glEnable(GL_TEXTURE_2D );
|
|
|
|
// Yaz: debug
|
|
// this compute the dirty rect for the mesh
|
|
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
GLdouble modelView[500];
|
|
GLdouble projection[500];
|
|
GLint viewPort[500];
|
|
|
|
glGetDoublev( GL_MODELVIEW_MATRIX, modelView );
|
|
glGetDoublev( GL_PROJECTION_MATRIX, projection );
|
|
glGetIntegerv( GL_VIEWPORT, viewPort);
|
|
|
|
GLdouble top = 1000;
|
|
GLdouble right = -1000;
|
|
GLdouble left = 1000;
|
|
GLdouble bottom = -1000;
|
|
|
|
for (int i = 0; i < numFaces_; i++)
|
|
{
|
|
Vector3d v;
|
|
Matrix4 tempMatrix = matrix_;
|
|
float* pVertices;
|
|
int j;
|
|
|
|
for( j =0; j< faces_[i].numVertices_; j++ )
|
|
{
|
|
pVertices = vertices_ + 3 * faces_[i].vertices_[j];
|
|
|
|
v.set( *(pVertices), *(pVertices+1), *(pVertices+2) );
|
|
|
|
tempMatrix.rot_.transform( v );
|
|
v+= tempMatrix.pos_;
|
|
|
|
GLdouble winX;
|
|
GLdouble winY;
|
|
GLdouble winZ;
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
glPointSize( 3.f );
|
|
glColor4f( 1.f, 1.f, 0.f, 1.f );
|
|
glDisable(GL_TEXTURE_2D );
|
|
|
|
glBegin(GL_LINES);
|
|
|
|
GLdouble objx;
|
|
GLdouble objy;
|
|
GLdouble objz;
|
|
|
|
// top
|
|
gluUnProject( left, top, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
|
|
glVertex3f( objx, objy, objz );
|
|
gluUnProject( right, top, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
|
|
glVertex3f( objx, objy, objz );
|
|
|
|
// bottom
|
|
gluUnProject( left, bottom, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
|
|
glVertex3f( objx, objy, objz );
|
|
gluUnProject( right, bottom, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
|
|
glVertex3f( objx, objy, objz );
|
|
|
|
// left
|
|
gluUnProject( left, top, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
|
|
glVertex3f( objx, objy, objz );
|
|
gluUnProject( left, bottom, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
|
|
glVertex3f( objx, objy, objz );
|
|
|
|
// right
|
|
gluUnProject( right, top, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
|
|
glVertex3f( objx, objy, objz );
|
|
gluUnProject( right, bottom, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
|
|
glVertex3f( objx, objy, objz );
|
|
|
|
glEnd();
|
|
glEnable(GL_DEPTH_TEST);
|
|
glEnable(GL_TEXTURE_2D );
|
|
glPopMatrix();
|
|
}
|
|
|
|
void Model::Face::draw(float *vertices, float *vertNormals,
|
|
float *textureVerts) const {
|
|
material_->select();
|
|
glNormal3fv(normal_.coords_);
|
|
glBegin(GL_POLYGON);
|
|
for (int i = 0; i < numVertices_; i++) {
|
|
glNormal3fv(vertNormals + 3 * vertices_[i]);
|
|
if (texVertices_ != NULL)
|
|
glTexCoord2fv(textureVerts + 2 * texVertices_[i]);
|
|
glVertex3fv(vertices + 3 * vertices_[i]);
|
|
}
|
|
glEnd();
|
|
}
|