429 lines
7.9 KiB
C++
429 lines
7.9 KiB
C++
/*
|
|
* Copyright 2008 Haiku Inc. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Alexandre Deckner
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Original Be Sample source modified to use a quaternion for the object's orientation
|
|
*/
|
|
|
|
/*
|
|
Copyright 1999, Be Incorporated. All Rights Reserved.
|
|
This file may be used under the terms of the Be Sample Code License.
|
|
*/
|
|
|
|
|
|
#include "GLObject.h"
|
|
|
|
#include <Application.h>
|
|
#include <GL/gl.h>
|
|
#include <InterfaceKit.h>
|
|
#include <Resources.h>
|
|
|
|
#include "glob.h"
|
|
|
|
|
|
struct material {
|
|
float ambient[3], diffuse[3], specular[3];
|
|
};
|
|
|
|
float *colors[] = {NULL, white, yellow, blue, red, green};
|
|
|
|
material materials[] = {
|
|
// Null
|
|
{
|
|
{0.1745, 0.03175, 0.03175},
|
|
{0.61424, 0.10136, 0.10136},
|
|
{0.727811, 0.626959, 0.626959}
|
|
},
|
|
// White
|
|
{
|
|
{0.1745, 0.1745, 0.1745},
|
|
{0.61424, 0.61424, 0.61424},
|
|
{0.727811, 0.727811, 0.727811}
|
|
},
|
|
// Yellow
|
|
{
|
|
{0.1745, 0.1745, 0.03175},
|
|
{0.61424, 0.61424, 0.10136},
|
|
{0.727811, 0.727811, 0.626959}
|
|
},
|
|
// Blue
|
|
{
|
|
{0.03175, 0.03175, 0.1745},
|
|
{0.10136, 0.10136, 0.61424},
|
|
{0.626959, 0.626959, 0.727811}
|
|
},
|
|
// Red
|
|
{
|
|
{0.1745, 0.03175, 0.03175},
|
|
{0.61424, 0.10136, 0.10136},
|
|
{0.727811, 0.626959, 0.626959}
|
|
},
|
|
// Green
|
|
{
|
|
{0.03175, 0.1745, 0.03175},
|
|
{0.10136, 0.61424, 0.10136},
|
|
{0.626959, 0.727811, 0.626959}
|
|
},
|
|
};
|
|
|
|
#define USE_QUAD_STRIPS 1
|
|
|
|
extern long setEvent(sem_id event);
|
|
|
|
|
|
GLObject::GLObject(ObjectView* ov)
|
|
:
|
|
x(0),
|
|
y(0),
|
|
z(-2.0),
|
|
fRotation(0.0f, 0.0f, 0.0f, 1.0f),
|
|
spinX(2),
|
|
spinY(2),
|
|
solidity(0),
|
|
color(4),
|
|
changed(false),
|
|
fObjView(ov)
|
|
{
|
|
}
|
|
|
|
|
|
GLObject::~GLObject()
|
|
{
|
|
}
|
|
|
|
|
|
void
|
|
GLObject::MenuInvoked(BPoint point)
|
|
{
|
|
BPopUpMenu* m = new BPopUpMenu("Object",false,false);
|
|
BMenuItem* i;
|
|
|
|
int c = 1;
|
|
m->AddItem(i = new BMenuItem("White",NULL));
|
|
if (color == c++)
|
|
i->SetMarked(true);
|
|
m->AddItem(i = new BMenuItem("Yellow",NULL));
|
|
if (color == c++)
|
|
i->SetMarked(true);
|
|
m->AddItem(i = new BMenuItem("Blue",NULL));
|
|
if (color == c++)
|
|
i->SetMarked(true);
|
|
m->AddItem(i = new BMenuItem("Red",NULL));
|
|
if (color == c++)
|
|
i->SetMarked(true);
|
|
m->AddItem(i = new BMenuItem("Green",NULL));
|
|
if (color == c++)
|
|
i->SetMarked(true);
|
|
m->AddSeparatorItem();
|
|
|
|
c = 0;
|
|
m->AddItem(i = new BMenuItem("Solid",NULL));
|
|
if (solidity == c++)
|
|
i->SetMarked(true);
|
|
m->AddItem(i = new BMenuItem("Translucent",NULL));
|
|
if (solidity == c++)
|
|
i->SetMarked(true);
|
|
m->AddItem(i = new BMenuItem("Transparent",NULL));
|
|
if (solidity == c++)
|
|
i->SetMarked(true);
|
|
|
|
i = m->Go(point);
|
|
int32 index = m->IndexOf(i);
|
|
delete m;
|
|
|
|
if (index < 5) {
|
|
color = index+1;
|
|
} else if (index > 5) {
|
|
solidity = index-6;
|
|
}
|
|
changed = true;
|
|
setEvent(fObjView->drawEvent);
|
|
}
|
|
|
|
|
|
int
|
|
GLObject::Solidity() const
|
|
{
|
|
return solidity;
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
GLObject::SpinIt()
|
|
{
|
|
bool c = changed;
|
|
c = c || ((spinX != 0.0f) || (spinY != 0.0f));
|
|
|
|
if (c)
|
|
RotateWorldSpace(spinY, spinX);
|
|
|
|
return c;
|
|
}
|
|
|
|
|
|
void
|
|
GLObject::Spin(float rx, float ry)
|
|
{
|
|
spinX = rx;
|
|
spinY = ry;
|
|
}
|
|
|
|
|
|
void
|
|
GLObject::RotateWorldSpace(float rx, float ry)
|
|
{
|
|
fRotation = Quaternion(Vector3(0.0f, 1.0f, 0.0f), 0.01f * rx) * fRotation;
|
|
fRotation = Quaternion(Vector3(1.0f, 0.0f, 0.0f), 0.01f * ry) * fRotation;
|
|
fRotation.normalize();
|
|
changed = true;
|
|
}
|
|
|
|
|
|
void
|
|
GLObject::Draw(bool forID, float IDcolor[])
|
|
{
|
|
glPushMatrix();
|
|
glTranslatef(x, y, z);
|
|
|
|
float mat[4][4];
|
|
fRotation.toOpenGLMatrix(mat);
|
|
glMultMatrixf((GLfloat*)mat);
|
|
|
|
if (forID) {
|
|
glColor3fv(IDcolor);
|
|
}
|
|
|
|
DoDrawing(forID);
|
|
|
|
glPopMatrix();
|
|
|
|
changed = false;
|
|
}
|
|
|
|
|
|
TriangleObject::TriangleObject(ObjectView* ov)
|
|
:
|
|
GLObject(ov),
|
|
fStatus(B_NO_INIT),
|
|
fPoints(100, 100),
|
|
fTriangles(100, 100),
|
|
fQs(50, 50)
|
|
{
|
|
BResources *res = BApplication::AppResources();
|
|
if (res == NULL)
|
|
return;
|
|
|
|
size_t size = 0;
|
|
int32 *arrayOfPoints
|
|
= (int32*)res->LoadResource(B_RAW_TYPE, "points", &size);
|
|
if (arrayOfPoints == NULL)
|
|
return;
|
|
|
|
float maxp = 0;
|
|
size_t numPt = size / sizeof(int32);
|
|
for (size_t i = 0; i < numPt; i += 6) {
|
|
point p;
|
|
p.x = 1e-6 * arrayOfPoints[i];
|
|
p.y = 1e-6 * arrayOfPoints[i + 1];
|
|
p.z = 1e-6 * arrayOfPoints[i + 2];
|
|
p.nx = 1e-6 * arrayOfPoints[i + 3];
|
|
p.ny = 1e-6 * arrayOfPoints[i + 4];
|
|
p.nz = 1e-6 * arrayOfPoints[i + 5];
|
|
|
|
if (fabs(p.x) > maxp)
|
|
maxp = fabs(p.x);
|
|
if (fabs(p.y) > maxp)
|
|
maxp = fabs(p.y);
|
|
if (fabs(p.z) > maxp)
|
|
maxp = fabs(p.z);
|
|
|
|
fPoints.add(p);
|
|
}
|
|
|
|
for (int i = 0; i < fPoints.num_items; i++) {
|
|
fPoints[i].x /= maxp;
|
|
fPoints[i].y /= maxp;
|
|
fPoints[i].z /= maxp;
|
|
}
|
|
|
|
int32 *arrayOfTriangles
|
|
= (int32*)res->LoadResource(B_RAW_TYPE, "triangles", &size);
|
|
if (arrayOfTriangles == NULL)
|
|
return;
|
|
|
|
size_t numTriPoints = size / sizeof(int32);
|
|
for (size_t i = 0; i < numTriPoints; i += 3) {
|
|
tri t;
|
|
t.p1 = arrayOfTriangles[i];
|
|
t.p2 = arrayOfTriangles[i + 1];
|
|
t.p3 = arrayOfTriangles[i + 2];
|
|
fTriangles.add(t);
|
|
}
|
|
|
|
size_t numTri = numTriPoints / 3;
|
|
|
|
int qpts = 4;
|
|
int qp[1024];
|
|
quadStrip q;
|
|
q.pts = qp;
|
|
q.numpts = 4;
|
|
q.pts[2] = fTriangles[0].p1;
|
|
q.pts[0] = fTriangles[0].p2;
|
|
q.pts[1] = fTriangles[0].p3;
|
|
q.pts[3] = fTriangles[1].p3;
|
|
|
|
for (size_t i = 2; i < numTri; i += 2) {
|
|
if ((fTriangles[i - 1].p1 == fTriangles[i].p2) &&
|
|
(fTriangles[i - 1].p3 == fTriangles[i].p3)) {
|
|
q.pts[q.numpts++] = fTriangles[i + 1].p1;
|
|
q.pts[q.numpts++] = fTriangles[i + 1].p3;
|
|
qpts+=2;
|
|
} else {
|
|
int *np = (int*)malloc(sizeof(int)*q.numpts);
|
|
memcpy(np, qp, q.numpts * sizeof(int));
|
|
quadStrip nqs;
|
|
nqs.numpts = q.numpts;
|
|
nqs.pts = np;
|
|
fQs.add(nqs);
|
|
|
|
qpts += 4;
|
|
q.numpts = 4;
|
|
q.pts[2] = fTriangles[i].p1;
|
|
q.pts[0] = fTriangles[i].p2;
|
|
q.pts[1] = fTriangles[i].p3;
|
|
q.pts[3] = fTriangles[i + 1].p3;
|
|
}
|
|
}
|
|
|
|
int* np = (int*)malloc(sizeof(int)*q.numpts);
|
|
memcpy(np, qp, q.numpts * sizeof(int));
|
|
quadStrip nqs;
|
|
nqs.numpts = q.numpts;
|
|
nqs.pts = np;
|
|
fQs.add(nqs);
|
|
|
|
fStatus = B_OK;
|
|
}
|
|
|
|
|
|
TriangleObject::~TriangleObject()
|
|
{
|
|
for (int i = 0; i < fQs.num_items; i++) {
|
|
free(fQs[i].pts);
|
|
}
|
|
}
|
|
|
|
|
|
status_t
|
|
TriangleObject::InitCheck() const
|
|
{
|
|
return fStatus;
|
|
}
|
|
|
|
|
|
void
|
|
TriangleObject::DoDrawing(bool forID)
|
|
{
|
|
if (!forID) {
|
|
float c[3][4];
|
|
c[0][0] = materials[color].ambient[0];
|
|
c[0][1] = materials[color].ambient[1];
|
|
c[0][2] = materials[color].ambient[2];
|
|
c[1][0] = materials[color].diffuse[0];
|
|
c[1][1] = materials[color].diffuse[1];
|
|
c[1][2] = materials[color].diffuse[2];
|
|
c[2][0] = materials[color].specular[0];
|
|
c[2][1] = materials[color].specular[1];
|
|
c[2][2] = materials[color].specular[2];
|
|
|
|
float alpha = 1;
|
|
if (solidity == 0)
|
|
alpha = 1.0;
|
|
else if (solidity == 1)
|
|
alpha = 0.95;
|
|
else if (solidity == 2)
|
|
alpha = 0.6;
|
|
c[0][3] = c[1][3] = c[2][3] = alpha;
|
|
if (solidity != 0) {
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
|
glEnable(GL_BLEND);
|
|
glDepthMask(GL_FALSE);
|
|
glDisable(GL_CULL_FACE);
|
|
} else {
|
|
glDisable(GL_BLEND);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
glMaterialfv(GL_FRONT, GL_AMBIENT, c[0]);
|
|
glMaterialfv(GL_FRONT, GL_DIFFUSE, c[1]);
|
|
glMaterialfv(GL_FRONT, GL_SPECULAR, c[2]);
|
|
} else {
|
|
glDisable(GL_BLEND);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
|
|
#if USE_QUAD_STRIPS
|
|
for (int i = 0; i < fQs.num_items; i++) {
|
|
glBegin(GL_QUAD_STRIP);
|
|
for (int j = 0; j < fQs[i].numpts; j++) {
|
|
glNormal3f(
|
|
fPoints[fQs[i].pts[j]].nx,
|
|
fPoints[fQs[i].pts[j]].ny,
|
|
fPoints[fQs[i].pts[j]].nz
|
|
);
|
|
glVertex3f(
|
|
fPoints[fQs[i].pts[j]].x,
|
|
fPoints[fQs[i].pts[j]].y,
|
|
fPoints[fQs[i].pts[j]].z
|
|
);
|
|
}
|
|
glEnd();
|
|
}
|
|
#else
|
|
glBegin(GL_TRIANGLES);
|
|
for (int i = 0; i < fTriangles.num_items; i++) {
|
|
int v3 = fTriangles[i].p1;
|
|
int v1 = fTriangles[i].p2;
|
|
int v2 = fTriangles[i].p3;
|
|
glNormal3f(
|
|
fPoints[v1].nx,
|
|
fPoints[v1].ny,
|
|
fPoints[v1].nz
|
|
);
|
|
glVertex3f(
|
|
fPoints[v1].x,
|
|
fPoints[v1].y,
|
|
fPoints[v1].z
|
|
);
|
|
glNormal3f(
|
|
fPoints[v2].nx,
|
|
fPoints[v2].ny,
|
|
fPoints[v2].nz
|
|
);
|
|
glVertex3f(
|
|
fPoints[v2].x,
|
|
fPoints[v2].y,
|
|
fPoints[v2].z
|
|
);
|
|
glNormal3f(
|
|
fPoints[v3].nx,
|
|
fPoints[v3].ny,
|
|
fPoints[v3].nz
|
|
);
|
|
glVertex3f(
|
|
fPoints[v3].x,
|
|
fPoints[v3].y,
|
|
fPoints[v3].z
|
|
);
|
|
}
|
|
glEnd();
|
|
#endif
|
|
}
|
|
|