NS/dev/performance-3.0.5/source/particles/opengl.cpp

150 lines
3.6 KiB
C++

// opengl.cpp
//
// Copyright 1998 by David K. McAllister
//
// This file implements the API calls that draw particle groups in OpenGL.
#include "general.h"
#ifdef WIN32
// This is for something in gl.h.
#include <windows.h>
#endif
#include <GL/gl.h>
// XXX #include <iostream.h>
// Emit OpenGL calls to draw the particles. These are drawn with
// whatever primitive type the user specified(GL_POINTS, for
// example). The color and radius are set per primitive, by default.
// For GL_LINES, the other vertex of the line is the velocity vector.
// XXX const_size is ignored.
PARTICLEDLL_API void pDrawGroupp(int primitive, bool const_size, bool const_color)
{
_ParticleState &_ps = _GetPState();
// Get a pointer to the particles in gp memory
ParticleGroup *pg = _ps.pgrp;
if(pg == NULL)
return; // ERROR
if(pg->p_count < 1)
return;
if(primitive == GL_POINTS)
{
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
if(!const_color)
{
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, sizeof(Particle), &pg->list[0].color);
}
glVertexPointer(3, GL_FLOAT, sizeof(Particle), &pg->list[0].pos);
glDrawArrays((GLenum)primitive, 0, pg->p_count);
glPopClientAttrib();
// XXX For E&S
glDisableClientState(GL_COLOR_ARRAY);
}
else
{
// Assume GL_LINES
glBegin((GLenum)primitive);
if(!const_color)
{
for(int i = 0; i < pg->p_count; i++)
{
Particle &m = pg->list[i];
// Warning: this depends on alpha following color in the Particle struct.
glColor4fv((GLfloat *)&m.color);
glVertex3fv((GLfloat *)&m.pos);
// For lines, make a tail with the velocity vector's direction and
// a length of radius.
pVector tail = m.pos - m.vel;
glVertex3fv((GLfloat *)&tail);
}
}
else
{
for(int i = 0; i < pg->p_count; i++)
{
Particle &m = pg->list[i];
glVertex3fv((GLfloat *)&m.pos);
// For lines, make a tail with the velocity vector's direction and
// a length of radius.
pVector tail = m.pos - m.vel;
glVertex3fv((GLfloat *)&tail);
}
}
glEnd();
}
}
PARTICLEDLL_API void pDrawGroupl(int dlist, bool const_size, bool const_color, bool const_rotation)
{
_ParticleState &_ps = _GetPState();
// Get a pointer to the particles in gp memory
ParticleGroup *pg = _ps.pgrp;
if(pg == NULL)
return; // ERROR
if(pg->p_count < 1)
return;
//if(const_color)
// glColor4fv((GLfloat *)&pg->list[0].color);
for(int i = 0; i < pg->p_count; i++)
{
Particle &m = pg->list[i];
glPushMatrix();
glTranslatef(m.pos.x, m.pos.y, m.pos.z);
if(!const_size)
glScalef(m.size.x, m.size.y, m.size.z);
else
glScalef(pg->list[i].size.x, pg->list[i].size.y, pg->list[i].size.z);
// Expensive! A sqrt, cross prod and acos. Yow.
if(!const_rotation)
{
pVector vN(m.vel);
vN.normalize();
pVector voN(m.velB);
voN.normalize();
pVector biN;
if(voN.x == vN.x && voN.y == vN.y && voN.z == vN.z)
biN = pVector(0, 1, 0);
else
biN = vN ^ voN;
biN.normalize();
pVector N(vN ^ biN);
double M[16];
M[0] = vN.x; M[4] = biN.x; M[8] = N.x; M[12] = 0;
M[1] = vN.y; M[5] = biN.y; M[9] = N.y; M[13] = 0;
M[2] = vN.z; M[6] = biN.z; M[10] = N.z; M[14] = 0;
M[3] = 0; M[7] = 0; M[11] = 0; M[15] = 1;
glMultMatrixd(M);
}
// Warning: this depends on alpha following color in the Particle struct.
if(!const_color)
glColor4fv((GLfloat *)&m.color);
glCallList(dlist);
glPopMatrix();
}
}