Skip to content
Snippets Groups Projects
Commit 8fff42de authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

reimplemented VertexArrays with std::vector (it's a bit faster)
parent a7d1db8a
No related branches found
No related tags found
No related merge requests found
// $Id: VertexArray.cpp,v 1.13 2006-08-22 01:58:32 geuzaine Exp $
// $Id: VertexArray.cpp,v 1.14 2006-08-22 15:34:34 geuzaine Exp $
//
// Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
//
......@@ -19,7 +19,7 @@
//
// Please report all bugs and problems to <gmsh@geuz.org>.
#include "Gmsh.h"
#include <algorithm>
#include "VertexArray.h"
#include "Context.h"
#include "Numeric.h"
......@@ -27,166 +27,142 @@
extern Context_T CTX;
VertexArray::VertexArray(int numNodesPerElement, int numElements)
: fill(0), _type(numNodesPerElement)
{
type = numNodesPerElement;
if(type < 1 || type > 4){
Msg(GERROR, "Vertex arrays not done for %d-node element", type);
type = 3;
}
fill = 0;
if(!numElements)
numElements = 1;
int nb = numElements * numNodesPerElement;
vertices = List_Create(nb * 3, 3000, sizeof(float));
normals = List_Create(nb * 3, 3000, sizeof(char));
colors = List_Create(nb * 4, 4000, sizeof(unsigned char));
}
VertexArray::~VertexArray()
{
List_Delete(vertices);
List_Delete(normals);
List_Delete(colors);
}
int VertexArray::n()
{
return List_Nbr(vertices) / 3;
}
template<class T>
inline void List_Add_3(List_T * liste, T *data1, T *data2, T *data3)
{
liste->n += 3;
List_Realloc(liste, liste->n);
liste->isorder = 0;
T* dest1 = (T*)&liste->array[(liste->n - 3) * liste->size];
T* dest2 = (T*)&liste->array[(liste->n - 2) * liste->size];
T* dest3 = (T*)&liste->array[(liste->n - 1) * liste->size];
*dest1 = *data1;
*dest2 = *data2;
*dest3 = *data3;
}
template<class T>
inline void List_Add_4(List_T * liste, T *data1, T *data2, T *data3, T *data4)
{
liste->n += 4;
List_Realloc(liste, liste->n);
liste->isorder = 0;
T* dest1 = (T*)&liste->array[(liste->n - 4) * liste->size];
T* dest2 = (T*)&liste->array[(liste->n - 3) * liste->size];
T* dest3 = (T*)&liste->array[(liste->n - 2) * liste->size];
T* dest4 = (T*)&liste->array[(liste->n - 1) * liste->size];
*dest1 = *data1;
*dest2 = *data2;
*dest3 = *data3;
*dest4 = *data4;
int nb = (numElements ? numElements : 1) * numNodesPerElement;
_vertices.reserve(nb * 3);
_normals.reserve(nb * 3);
_colors.reserve(nb *4);
}
void VertexArray::add(float x, float y, float z,
float n0, float n1, float n2, unsigned int col)
{
List_Add_3(vertices, &x, &y, &z);
_vertices.push_back(x);
_vertices.push_back(y);
_vertices.push_back(z);
// Warning: storing the normals as bytes WILL hurt rendering
// performance... but it reduces significantly the memory footprint.
char c0 = float2char(n0);
char c1 = float2char(n1);
char c2 = float2char(n2);
List_Add_3(normals, &c0, &c1, &c2);
_normals.push_back(c0);
_normals.push_back(c1);
_normals.push_back(c2);
unsigned char r = CTX.UNPACK_RED(col);
unsigned char g = CTX.UNPACK_GREEN(col);
unsigned char b = CTX.UNPACK_BLUE(col);
unsigned char a = CTX.UNPACK_ALPHA(col);
List_Add_4(colors, &r, &g, &b, &a);
_colors.push_back(r);
_colors.push_back(g);
_colors.push_back(b);
_colors.push_back(a);
}
void VertexArray::add(float x, float y, float z, unsigned int col)
{
List_Add_3(vertices, &x, &y, &z);
_vertices.push_back(x);
_vertices.push_back(y);
_vertices.push_back(z);
unsigned char r = CTX.UNPACK_RED(col);
unsigned char g = CTX.UNPACK_GREEN(col);
unsigned char b = CTX.UNPACK_BLUE(col);
unsigned char a = CTX.UNPACK_ALPHA(col);
List_Add_4(colors, &r, &g, &b, &a);
}
static double theeye[3];
int compareTriEye(const void *a, const void *b)
_colors.push_back(r);
_colors.push_back(g);
_colors.push_back(b);
_colors.push_back(a);
}
class AlphaElement {
public:
AlphaElement(float *vp, char *np, unsigned char *cp) : v(vp), n(np), c(cp) {}
float *v;
char *n;
unsigned char *c;
};
class AlphaElementLessThan {
public:
static int numVertices;
static double eye[3];
bool operator()(const AlphaElement &e1, const AlphaElement &e2) const
{
float *q = (float*)a;
float *w = (float*)b;
double d, dq, dw, cgq[3] = { 0., 0., 0. }, cgw[3] = { 0., 0., 0.};
for(int i = 0; i < 3; i++) {
cgq[0] += q[3*i];
cgq[1] += q[3*i + 1];
cgq[2] += q[3*i + 2];
cgw[0] += w[3*i];
cgw[1] += w[3*i + 1];
cgw[2] += w[3*i + 2];
}
prosca(theeye, cgq, &dq);
prosca(theeye, cgw, &dw);
d = dq - dw;
if(d > 0)
return 1;
if(d < 0)
return -1;
return 0;
}
double cg1[3] = { 0., 0., 0. }, cg2[3] = { 0., 0., 0.};
for(int i = 0; i < numVertices; i++) {
cg1[0] += e1.v[3 * i];
cg1[1] += e1.v[3 * i + 1];
cg1[2] += e1.v[3 * i + 2];
cg2[0] += e2.v[3 * i];
cg2[1] += e2.v[3 * i + 1];
cg2[2] += e2.v[3 * i + 2];
}
double d1, d2;
prosca(eye, cg1, &d1);
prosca(eye, cg2, &d2);
if(d1 < d2)
return true;
return false;
}
};
int AlphaElementLessThan::numVertices = 0;
double AlphaElementLessThan::eye[3] = {0., 0., 0.};
void VertexArray::sort(double eye[3])
{
// sort assumes that the all the arrays are filled
if(!List_Nbr(vertices) || !List_Nbr(normals) || !List_Nbr(colors))
return;
if(type != 3){
Msg(GERROR, "VertexArray sort only implemented for triangles");
return;
}
theeye[0] = eye[0];
theeye[1] = eye[1];
theeye[2] = eye[2];
int num = n() / 3;
int nb = List_Nbr(vertices) + List_Nbr(normals) + List_Nbr(colors);
float *tmp = new float[nb];
int iv = 0, in = 0, ic = 0, k = 0;
for(int i = 0; i < num; i++){
for(int j = 0; j < 9; j++)
List_Read(vertices, iv++, &tmp[k++]);
for(int j = 0; j < 9; j++)
List_Read(normals, in++, &tmp[k++]);
for(int j = 0; j < 12; j++){
unsigned char c;
List_Read(colors, ic++, &c);
tmp[k++] = c;
}
}
List_Reset(vertices);
List_Reset(normals);
List_Reset(colors);
qsort(tmp, num, (9+9+12)*sizeof(float), compareTriEye);
k = 0;
for(int i = 0; i < num; i++){
for(int j = 0; j < 9; j++)
List_Add(vertices, &tmp[k++]);
for(int j = 0; j < 9; j++)
List_Add(normals, &tmp[k++]);
for(int j = 0; j < 12; j++){
unsigned char c = (unsigned char)tmp[k++];
List_Add(colors, &c);
}
}
delete [] tmp;
// This simplementation is pretty bad: it copies the whole data
// twice. We should think about a more efficient way to sort the
// three arrays in place.
AlphaElementLessThan::numVertices = getType();
AlphaElementLessThan::eye[0] = eye[0];
AlphaElementLessThan::eye[1] = eye[1];
AlphaElementLessThan::eye[2] = eye[2];
int n = getNumVertices() / getType();
std::vector<AlphaElement> elements;
elements.reserve(n);
if(_normals.size())
for(int i = 0; i < n; i++)
elements.push_back(AlphaElement(&_vertices[3 * getType() * i],
&_normals[3 * getType() * i],
&_colors[4 * getType() * i]));
else
for(int i = 0; i < n; i++)
elements.push_back(AlphaElement(&_vertices[3 * getType() * i],
0,
&_colors[4 * getType() * i]));
std::sort(elements.begin(), elements.end(), AlphaElementLessThan());
std::vector<float> sortedVertices;
std::vector<char> sortedNormals;
std::vector<unsigned char> sortedColors;
sortedVertices.reserve(_vertices.size());
sortedNormals.reserve(_normals.size());
sortedColors.reserve(_colors.size());
for(int i = 0; i < n; i++){
for(int j = 0; j < getType(); j++){
for(int k = 0; k < 3; k++){
sortedVertices.push_back(elements[i].v[3 * j + k]);
if(elements[i].v)
sortedNormals.push_back(elements[i].n[3 * j + k]);
}
for(int k = 0; k < 4; k++){
sortedColors.push_back(elements[i].c[4 * j + k]);
}
}
}
_vertices = sortedVertices;
_normals = sortedNormals;
_colors = sortedColors;
}
......@@ -20,21 +20,34 @@
//
// Please report all bugs and problems to <gmsh@geuz.org>.
#include "List.h"
#include "vector"
class VertexArray{
public:
int type, fill;
List_T *vertices, *normals, *colors;
int fill; // this must/will be removed
private:
int _type;
std::vector<float> _vertices;
std::vector<char> _normals;
std::vector<unsigned char> _colors;
public:
VertexArray(int numNodesPerElement, int numElements);
~VertexArray();
// return the number of nodes in the array
int n();
// add a node in the array
~VertexArray(){}
// returns the number of nodes in the array
int getNumVertices() { return _vertices.size() / 3; }
// returns the type of the array
int getType() { return _type; }
// returns a pointer to the raw vertex array
float *getVertexArray(){ return &_vertices[0]; }
// returns a pointer to the raw normal array
char *getNormalArray(){ return &_normals[0]; }
// returns a pointer to the raw color array
unsigned char *getColorArray(){ return &_colors[0]; }
// adds a vertex in the arrays
void add(float x, float y, float z,
float n0, float n1, float n2, unsigned int col);
void add(float x, float y, float z, unsigned int col);
// sort the elements back to fron wrt the eye position
// sorts the elements back to front wrt the eye position
void sort(double eye[3]);
};
......
// $Id: Mesh.cpp,v 1.182 2006-08-22 01:58:34 geuzaine Exp $
// $Id: Mesh.cpp,v 1.183 2006-08-22 15:34:34 geuzaine Exp $
//
// Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
//
......@@ -435,9 +435,9 @@ static void drawArrays(GEntity *e, VertexArray *va, GLint type, bool useNormalAr
{
if(!va) return;
glVertexPointer(3, GL_FLOAT, 0, va->vertices->array);
glNormalPointer(GL_BYTE, 0, va->normals->array);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, va->colors->array);
glVertexPointer(3, GL_FLOAT, 0, va->getVertexArray());
glNormalPointer(GL_BYTE, 0, va->getNormalArray());
glColorPointer(4, GL_UNSIGNED_BYTE, 0, va->getColorArray());
glEnableClientState(GL_VERTEX_ARRAY);
......@@ -462,13 +462,13 @@ static void drawArrays(GEntity *e, VertexArray *va, GLint type, bool useNormalAr
glColor4ubv((GLubyte *) & color);
}
if(va->type > 2 && !drawOutline && CTX.polygon_offset)
if(va->getType() > 2 && !drawOutline && CTX.polygon_offset)
glEnable(GL_POLYGON_OFFSET_FILL);
if(drawOutline)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawArrays(type, 0, va->n());
glDrawArrays(type, 0, va->getNumVertices());
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_POLYGON_OFFSET_FILL);
......@@ -591,7 +591,9 @@ class initMeshGFace {
// Further optimizations are possible when useEdges is true:
// 1) store the unique vertices in the vertex array and use
// glDrawElements() instead of glDrawArrays().
// glDrawElements() instead of glDrawArrays(). Question:
// which normal do you choose for each vertex, and so how
// can you achieve accurate "flat shading" rendering?
// 2) use tc to stripe the triangles and draw strips instead of
// individual triangles
......@@ -624,7 +626,7 @@ class drawMeshGFace {
MRep *m = f->meshRep;
if(CTX.mesh.surfaces_edges){
if(m->va_lines && m->va_lines->n()){
if(m->va_lines && m->va_lines->getNumVertices()){
drawArrays(f, m->va_lines, GL_LINES, CTX.mesh.light && CTX.mesh.light_lines,
CTX.mesh.surfaces_faces, CTX.color.mesh.line);
}
......@@ -732,7 +734,7 @@ class drawMeshGRegion {
MRep *m = r->meshRep;
if(CTX.mesh.volumes_edges){
if(m->va_lines && m->va_lines->n()){
if(m->va_lines && m->va_lines->getNumVertices()){
drawArrays(r, m->va_lines, GL_LINES, CTX.mesh.light && CTX.mesh.light_lines,
CTX.mesh.volumes_faces, CTX.color.mesh.line);
}
......
// $Id: Post.cpp,v 1.111 2006-08-18 21:11:43 geuzaine Exp $
// $Id: Post.cpp,v 1.112 2006-08-22 15:34:34 geuzaine Exp $
//
// Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
//
......@@ -749,25 +749,27 @@ void Draw_Post(void)
pass_1:
if(v->TriVertexArray && v->TriVertexArray->fill){
Msg(DEBUG, "View[%d]; %d tris in vertex array", v->Index, v->TriVertexArray->n()/3);
Msg(DEBUG, "View[%d]; %d tris in vertex array",
v->Index, v->TriVertexArray->getNumVertices()/3);
v->TriVertexArray->fill = 0;
}
if(v->LinVertexArray && v->LinVertexArray->fill){
Msg(DEBUG, "View[%d]; %d segs in vertex array", v->Index, v->LinVertexArray->n()/2);
Msg(DEBUG, "View[%d]; %d segs in vertex array",
v->Index, v->LinVertexArray->getNumVertices()/2);
v->LinVertexArray->fill = 0;
}
}
if(v->TriVertexArray && v->TriVertexArray->n()){
if(v->TriVertexArray && v->TriVertexArray->getNumVertices()){
if(CTX.alpha && ColorTable_IsAlpha(&v->CT) && !v->FakeTransparency &&
(changedEye() || v->Changed)){
Msg(DEBUG, "Sorting View[%d] for transparency (WITH vertex array)", v->Index);
v->TriVertexArray->sort(storedEye);
}
glVertexPointer(3, GL_FLOAT, 0, v->TriVertexArray->vertices->array);
glNormalPointer(GL_BYTE, 0, v->TriVertexArray->normals->array);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, v->TriVertexArray->colors->array);
glVertexPointer(3, GL_FLOAT, 0, v->TriVertexArray->getVertexArray());
glNormalPointer(GL_BYTE, 0, v->TriVertexArray->getNormalArray());
glColorPointer(4, GL_UNSIGNED_BYTE, 0, v->TriVertexArray->getColorArray());
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
......@@ -778,7 +780,7 @@ void Draw_Post(void)
else
glDisableClientState(GL_NORMAL_ARRAY);
if(CTX.polygon_offset) glEnable(GL_POLYGON_OFFSET_FILL);
glDrawArrays(GL_TRIANGLES, 0, v->TriVertexArray->n());
glDrawArrays(GL_TRIANGLES, 0, v->TriVertexArray->getNumVertices());
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_LIGHTING);
......@@ -787,12 +789,12 @@ void Draw_Post(void)
glDisableClientState(GL_COLOR_ARRAY);
}
if(v->LinVertexArray && v->LinVertexArray->n()){
glVertexPointer(3, GL_FLOAT, 0, v->LinVertexArray->vertices->array);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, v->LinVertexArray->colors->array);
if(v->LinVertexArray && v->LinVertexArray->getNumVertices()){
glVertexPointer(3, GL_FLOAT, 0, v->LinVertexArray->getVertexArray());
glColorPointer(4, GL_UNSIGNED_BYTE, 0, v->LinVertexArray->getColorArray());
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_LINES, 0, v->LinVertexArray->n());
glDrawArrays(GL_LINES, 0, v->LinVertexArray->getNumVertices());
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment