BlobbyPrimitive.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2005 Dave Griffiths
00002 //
00003 // This program is free software; you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation; either version 2 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016 
00017 #include "Renderer.h"
00018 #include "BlobbyPrimitive.h"
00019 #include "State.h"
00020 #include "ImplicitSurface.h"
00021 
00022 using namespace Fluxus;
00023     
00024 BlobbyPrimitive::BlobbyPrimitive(int dimx, int dimy, int dimz, dVector size) 
00025 {
00026     AddData("p",new TypedPData<dVector>);
00027     AddData("c",new TypedPData<dColour>);
00028     AddData("s",new TypedPData<float>);
00029     
00030     // setup the direct access for speed
00031     PDataDirty();
00032     
00033     float sx=size.x/(float)dimx;
00034     float sy=size.y/(float)dimy;
00035     float sz=size.z/(float)dimz;
00036         
00037     for (int x=0; x<dimx; x++)
00038     {
00039         for (int y=0; y<dimy; y++)
00040         {
00041             for (int z=0; z<dimz; z++)
00042             {
00043                 Cell cell;
00044             
00045                 cell.p[0]=dVector(sx*x,sy*y+sy,sz*z);
00046                 cell.p[1]=dVector(sx*x,sy*y+sy,sz*z+sz);
00047                 cell.p[2]=dVector(sx*x,sy*y,sz*z+sz);
00048                 cell.p[3]=dVector(sx*x,sy*y,sz*z);
00049                 
00050                 cell.p[4]=dVector(sx*x+sx,sy*y+sy,sz*z);
00051                 cell.p[5]=dVector(sx*x+sx,sy*y+sy,sz*z+sz);
00052                 cell.p[6]=dVector(sx*x+sx,sy*y,sz*z+sz);
00053                 cell.p[7]=dVector(sx*x+sx,sy*y,sz*z);
00054             
00055                 cell.val[0]=0;
00056                 cell.val[1]=0;
00057                 cell.val[2]=0;
00058                 cell.val[3]=0;
00059                 cell.val[4]=0;
00060                 cell.val[5]=0;
00061                 cell.val[6]=0;
00062                 cell.val[7]=0;
00063             
00064                 m_Voxels.push_back(cell);
00065             }
00066         }
00067     }
00068 }
00069 
00070 BlobbyPrimitive::BlobbyPrimitive(const BlobbyPrimitive &other) :
00071 Primitive(other), 
00072 m_Voxels(other.m_Voxels)
00073 {
00074     PDataDirty();
00075 }
00076 
00077 BlobbyPrimitive* BlobbyPrimitive::Clone() const 
00078 {
00079     return new BlobbyPrimitive(*this); 
00080 }
00081 
00082 BlobbyPrimitive::~BlobbyPrimitive()
00083 {
00084 }
00085 
00086 void BlobbyPrimitive::PDataDirty()
00087 {
00088     // reset pointers
00089     m_PosData=GetDataVec<dVector>("p");
00090     m_StrengthData=GetDataVec<float>("s");
00091     m_ColData=GetDataVec<dColour>("c");
00092 }
00093 
00094 void BlobbyPrimitive::AddInfluence(const dVector &Vert, float Strength)
00095 { 
00096     m_PosData->push_back(Vert); 
00097     m_StrengthData->push_back(Strength); 
00098     m_ColData->push_back(dColour(1,1,1)); 
00099 }   
00100 
00101 float BlobbyPrimitive::Sample(const dVector &pos)
00102 {
00103     float val=0;
00104     for (unsigned int n=0; n<m_PosData->size(); n++)
00105     {
00106         float distance=fabs((*m_PosData)[n].distsq(pos));
00107         if (distance>0)
00108         {
00109             val+=(*m_StrengthData)[n]*(1/distance);
00110         }
00111     }       
00112     return val; 
00113 }
00114 
00115 float BlobbyPrimitive::SampleCol(const dVector &pos, dColour &col)
00116 {
00117     float val=0;
00118     col=dColour(0,0,0);
00119     
00120     for (unsigned int n=0; n<m_PosData->size(); n++)
00121     {
00122         float distance=fabs((*m_PosData)[n].distsq(pos));
00123         if (distance>0)
00124         {
00125             float mul=1/distance;
00126             val+=(*m_StrengthData)[n]*mul;
00127             
00128             //col+=(*m_ColData)[n]*mul;
00129 
00130             col.r+=(*m_ColData)[n].r*mul;
00131             col.g+=(*m_ColData)[n].g*mul;
00132             col.b+=(*m_ColData)[n].b*mul;
00133         }
00134     }       
00135     return val; 
00136 }
00137 
00138 void BlobbyPrimitive::Render()
00139 {   
00140     for (unsigned int i=0; i<m_Voxels.size(); i++)
00141     {
00142         for (int c=0; c<8; c++)
00143         {
00144             dVector pos = m_Voxels[i].p[c];
00145             
00146             if (m_State.Hints & HINT_VERTCOLS)
00147             {
00148                 m_Voxels[i].val[c]=SampleCol(pos,m_Voxels[i].col[c]);
00149             }
00150             else
00151             {
00152                 m_Voxels[i].val[c]=Sample(pos);
00153             }   
00154         }
00155     }
00156     
00157     if (m_State.Hints & HINT_SOLID)
00158     {
00159         glBegin(GL_TRIANGLES);
00160         Draw(1, true, m_State.Hints & HINT_VERTCOLS);   
00161         glEnd();
00162     }
00163     
00164     if (m_State.Hints & HINT_WIRE)
00165     {
00166         glPolygonOffset(1,1);
00167         glColor3fv(m_State.WireColour.arr());
00168         glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
00169         glDisable(GL_LIGHTING); 
00170         glBegin(GL_TRIANGLES);
00171         Draw(1, false, false);  
00172         glEnd();
00173         glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
00174         glEnable(GL_LIGHTING);
00175     }
00176     
00177 }
00178 
00179 void BlobbyPrimitive::RecalculateNormals(bool smooth)
00180 {
00181 
00182 }
00183 
00184 dBoundingBox BlobbyPrimitive::GetBoundingBox()
00185 {   
00186     dBoundingBox box;
00187     for (vector<dVector>::iterator i=m_PosData->begin(); i!=m_PosData->end(); ++i)
00188     {
00189         box.expand(*i);
00190     }
00191     return box;
00192 }
00193 
00194 void BlobbyPrimitive::ApplyTransform(bool ScaleRotOnly)
00195 {
00196     if (!ScaleRotOnly)
00197     {
00198         for (vector<dVector>::iterator i=m_PosData->begin(); i!=m_PosData->end(); ++i)
00199         {
00200             *i=GetState()->Transform.transform(*i);
00201             // why not normals?
00202         }
00203     }
00204     else
00205     {
00206         for (unsigned int i=0; i<m_PosData->size(); i++)
00207         {
00208             (*m_PosData)[i]=GetState()->Transform.transform_no_trans((*m_PosData)[i]);
00209         }
00210     }
00211     
00212     GetState()->Transform.init();
00213 }
00214 
00215 // this implicit surface implementation is modified from Paul Bourke's which can be found here:
00216 // http://astronomy.swin.edu.au/~pbourke/modelling/polygonise/
00217 
00218 void BlobbyPrimitive::Draw(float isolevel, bool calcnormals, bool colour)
00219 {
00220    int i;
00221    int cubeindex;
00222    dVertex vertlist[12];
00223 
00224     for (unsigned int cell=0; cell<m_Voxels.size(); cell++)
00225     { 
00226         //  Determine the index into the edge table which
00227         //  tells us which vertices are inside of the surface
00228         cubeindex = 0;
00229         if (m_Voxels[cell].val[0] < isolevel) cubeindex |= 1;
00230         if (m_Voxels[cell].val[1] < isolevel) cubeindex |= 2;
00231         if (m_Voxels[cell].val[2] < isolevel) cubeindex |= 4;
00232         if (m_Voxels[cell].val[3] < isolevel) cubeindex |= 8;
00233         if (m_Voxels[cell].val[4] < isolevel) cubeindex |= 16;
00234         if (m_Voxels[cell].val[5] < isolevel) cubeindex |= 32;
00235         if (m_Voxels[cell].val[6] < isolevel) cubeindex |= 64;
00236         if (m_Voxels[cell].val[7] < isolevel) cubeindex |= 128;
00237 
00238         // Cube is entirely in/out of the surface 
00239         if (ImplicitSurfaceEdges[cubeindex] != 0)
00240         {
00241 
00242             // Find the vertices where the surface intersects the cube
00243             if (ImplicitSurfaceEdges[cubeindex] & 1) Interpolate(vertlist[0],isolevel,cell,0,1);
00244             if (ImplicitSurfaceEdges[cubeindex] & 2) Interpolate(vertlist[1],isolevel,cell,1,2);
00245             if (ImplicitSurfaceEdges[cubeindex] & 4) Interpolate(vertlist[2],isolevel,cell,2,3);
00246             if (ImplicitSurfaceEdges[cubeindex] & 8) Interpolate(vertlist[3],isolevel,cell,3,0);
00247             if (ImplicitSurfaceEdges[cubeindex] & 16) Interpolate(vertlist[4],isolevel,cell,4,5);
00248             if (ImplicitSurfaceEdges[cubeindex] & 32) Interpolate(vertlist[5],isolevel,cell,5,6);
00249             if (ImplicitSurfaceEdges[cubeindex] & 64) Interpolate(vertlist[6],isolevel,cell,6,7);
00250             if (ImplicitSurfaceEdges[cubeindex] & 128) Interpolate(vertlist[7],isolevel,cell,7,4);
00251             if (ImplicitSurfaceEdges[cubeindex] & 256) Interpolate(vertlist[8],isolevel,cell,0,4);
00252             if (ImplicitSurfaceEdges[cubeindex] & 512) Interpolate(vertlist[9],isolevel,cell,1,5);
00253             if (ImplicitSurfaceEdges[cubeindex] & 1024) Interpolate(vertlist[10],isolevel,cell,2,6);
00254             if (ImplicitSurfaceEdges[cubeindex] & 2048) Interpolate(vertlist[11],isolevel,cell,3,7);
00255 
00256             // Create the triangle 
00257             for (i=0; ImplicitSurfaceTriangles[cubeindex][i]!=-1; i+=3) 
00258             {
00259                 dVertex a=vertlist[ImplicitSurfaceTriangles[cubeindex][i]];
00260                 dVertex b=vertlist[ImplicitSurfaceTriangles[cubeindex][i+1]];
00261                 dVertex c=vertlist[ImplicitSurfaceTriangles[cubeindex][i+2]];
00262             
00263                 dVector normal;
00264                 float val=0;
00265                 
00266                 if (calcnormals)
00267                 {
00268                     val=Sample(a.point);
00269                     normal.x=val-Sample(a.point+dVector(0.001,0,0));
00270                     normal.y=val-Sample(a.point+dVector(0,0.001,0));
00271                     normal.z=val-Sample(a.point+dVector(0,0,0.001));
00272                     normal.normalise();
00273                     glNormal3fv(normal.arr());
00274                 }
00275                 
00276                 if (colour) glColor3fv(a.col.arr());
00277                 glVertex3fv(a.point.arr());
00278                 
00279                 if (calcnormals)
00280                 {
00281                     val=Sample(b.point);
00282                     normal.x=val-Sample(b.point+dVector(0.001,0,0));
00283                     normal.y=val-Sample(b.point+dVector(0,0.001,0));
00284                     normal.z=val-Sample(b.point+dVector(0,0,0.001));
00285                     normal.normalise();
00286                     glNormal3fv(normal.arr());
00287                 }
00288                 
00289                 if (colour) glColor3fv(b.col.arr());
00290                 glVertex3fv(b.point.arr());
00291                 
00292                 if (calcnormals)
00293                 {
00294                     val=Sample(c.point);
00295                     normal.x=val-Sample(c.point+dVector(0.001,0,0));
00296                     normal.y=val-Sample(c.point+dVector(0,0.001,0));
00297                     normal.z=val-Sample(c.point+dVector(0,0,0.001));
00298                     normal.normalise();
00299                     glNormal3fv(normal.arr());
00300                 }
00301                 
00302                 if (colour) glColor3fv(c.col.arr());
00303                 glVertex3fv(c.point.arr());
00304             }
00305         }
00306     }
00307 }
00308 
00309 // generate a poly mesh
00310 void BlobbyPrimitive::ConvertToPoly(PolyPrimitive &poly, float isolevel)
00311 {
00312     // evaluate the field
00313     for (unsigned int i=0; i<m_Voxels.size(); i++)
00314     {
00315         for (int c=0; c<8; c++)
00316         {
00317             dVector pos = m_Voxels[i].p[c];
00318             
00319             if (m_State.Hints & HINT_VERTCOLS)
00320             {
00321                 m_Voxels[i].val[c]=SampleCol(pos,m_Voxels[i].col[c]);
00322             }
00323             else
00324             {
00325                 m_Voxels[i].val[c]=Sample(pos);
00326             }   
00327         }
00328     }
00329     
00330    int i;
00331    int cubeindex;
00332    dVertex vertlist[12];
00333 
00334     for (unsigned int cell=0; cell<m_Voxels.size(); cell++)
00335     { 
00336         //  Determine the index into the edge table which
00337         //  tells us which vertices are inside of the surface
00338         cubeindex = 0;
00339         if (m_Voxels[cell].val[0] < isolevel) cubeindex |= 1;
00340         if (m_Voxels[cell].val[1] < isolevel) cubeindex |= 2;
00341         if (m_Voxels[cell].val[2] < isolevel) cubeindex |= 4;
00342         if (m_Voxels[cell].val[3] < isolevel) cubeindex |= 8;
00343         if (m_Voxels[cell].val[4] < isolevel) cubeindex |= 16;
00344         if (m_Voxels[cell].val[5] < isolevel) cubeindex |= 32;
00345         if (m_Voxels[cell].val[6] < isolevel) cubeindex |= 64;
00346         if (m_Voxels[cell].val[7] < isolevel) cubeindex |= 128;
00347 
00348         // Cube is entirely in/out of the surface 
00349         if (ImplicitSurfaceEdges[cubeindex] != 0)
00350         {
00351 
00352             // Find the vertices where the surface intersects the cube
00353             if (ImplicitSurfaceEdges[cubeindex] & 1) Interpolate(vertlist[0],isolevel,cell,0,1);
00354             if (ImplicitSurfaceEdges[cubeindex] & 2) Interpolate(vertlist[1],isolevel,cell,1,2);
00355             if (ImplicitSurfaceEdges[cubeindex] & 4) Interpolate(vertlist[2],isolevel,cell,2,3);
00356             if (ImplicitSurfaceEdges[cubeindex] & 8) Interpolate(vertlist[3],isolevel,cell,3,0);
00357             if (ImplicitSurfaceEdges[cubeindex] & 16) Interpolate(vertlist[4],isolevel,cell,4,5);
00358             if (ImplicitSurfaceEdges[cubeindex] & 32) Interpolate(vertlist[5],isolevel,cell,5,6);
00359             if (ImplicitSurfaceEdges[cubeindex] & 64) Interpolate(vertlist[6],isolevel,cell,6,7);
00360             if (ImplicitSurfaceEdges[cubeindex] & 128) Interpolate(vertlist[7],isolevel,cell,7,4);
00361             if (ImplicitSurfaceEdges[cubeindex] & 256) Interpolate(vertlist[8],isolevel,cell,0,4);
00362             if (ImplicitSurfaceEdges[cubeindex] & 512) Interpolate(vertlist[9],isolevel,cell,1,5);
00363             if (ImplicitSurfaceEdges[cubeindex] & 1024) Interpolate(vertlist[10],isolevel,cell,2,6);
00364             if (ImplicitSurfaceEdges[cubeindex] & 2048) Interpolate(vertlist[11],isolevel,cell,3,7);
00365 
00366             // Create the triangle 
00367             for (i=0; ImplicitSurfaceTriangles[cubeindex][i]!=-1; i+=3) 
00368             {
00369                 dVertex a=vertlist[ImplicitSurfaceTriangles[cubeindex][i]];
00370                 dVertex b=vertlist[ImplicitSurfaceTriangles[cubeindex][i+1]];
00371                 dVertex c=vertlist[ImplicitSurfaceTriangles[cubeindex][i+2]];
00372             
00373                 dVector normal;
00374                 float val=0;
00375                 
00376                 val=Sample(a.point);
00377                 normal.x=val-Sample(a.point+dVector(0.001,0,0));
00378                 normal.y=val-Sample(a.point+dVector(0,0.001,0));
00379                 normal.z=val-Sample(a.point+dVector(0,0,0.001));
00380                 normal.normalise();
00381                 
00382                 poly.AddVertex(dVertex(a.point,normal,a.col));
00383                 
00384                 val=Sample(b.point);
00385                 normal.x=val-Sample(b.point+dVector(0.001,0,0));
00386                 normal.y=val-Sample(b.point+dVector(0,0.001,0));
00387                 normal.z=val-Sample(b.point+dVector(0,0,0.001));
00388                 normal.normalise();
00389                 
00390                 poly.AddVertex(dVertex(b.point,normal,b.col));
00391                             
00392                 val=Sample(c.point);
00393                 normal.x=val-Sample(c.point+dVector(0.001,0,0));
00394                 normal.y=val-Sample(c.point+dVector(0,0.001,0));
00395                 normal.z=val-Sample(c.point+dVector(0,0,0.001));
00396                 normal.normalise();
00397                 
00398                 poly.AddVertex(dVertex(c.point,normal,c.col));
00399             }
00400         }
00401     }
00402 }
00403 
00404 //   Linearly interpolate the position where an isosurface cuts
00405 //   an edge between two vertices, each with their own scalar value
00406 void BlobbyPrimitive::Interpolate(dVertex &vert, float isolevel, int cell, int a, int b)
00407 {
00408     float mu;
00409 
00410     dVector posa = m_Voxels[cell].p[a];
00411     dVector posb = m_Voxels[cell].p[b];
00412     dColour cola = m_Voxels[cell].col[a];
00413     dColour colb = m_Voxels[cell].col[b];
00414     float vala = m_Voxels[cell].val[a];
00415     float valb = m_Voxels[cell].val[b];
00416 
00417 
00418     mu = (isolevel - vala) / (valb - vala);
00419     vert.point.x = posa.x + mu * (posb.x - posa.x);
00420     vert.point.y = posa.y + mu * (posb.y - posa.y);
00421     vert.point.z = posa.z + mu * (posb.z - posa.z);
00422 
00423     vert.col.r = cola.r + mu * (colb.r - cola.r);
00424     vert.col.g = cola.g + mu * (colb.g - cola.g);
00425     vert.col.b = cola.b + mu * (colb.b - cola.b);
00426 }

Generated on Tue Sep 4 23:22:18 2007 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1