NURBSPrimitive.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 "NURBSPrimitive.h"
00019 #include "State.h"
00020 
00021 using namespace Fluxus;
00022     
00023 NURBSPrimitive::NURBSPrimitive() :
00024 m_UOrder(0),
00025 m_VOrder(0),
00026 m_UCVCount(0),
00027 m_VCVCount(0),
00028 m_Stride(sizeof(dVector)/sizeof(float))
00029 {
00030     AddData("p",new TypedPData<dVector>);
00031     AddData("t",new TypedPData<dVector>);
00032     AddData("n",new TypedPData<dVector>);
00033     
00034     // direct access for speed
00035     PDataDirty();
00036     
00037     SetupSurface();
00038 }
00039 
00040 NURBSPrimitive::NURBSPrimitive(const NURBSPrimitive &other) :
00041 Primitive(other),
00042 m_UKnotVec(other.m_UKnotVec),
00043 m_VKnotVec(other.m_VKnotVec),
00044 m_UOrder(other.m_UOrder),
00045 m_VOrder(other.m_VOrder),
00046 m_UCVCount(other.m_UCVCount),
00047 m_VCVCount(other.m_VCVCount),
00048 m_Stride(other.m_Stride)
00049 {
00050     SetupSurface();
00051     PDataDirty();
00052 }
00053 
00054 NURBSPrimitive::~NURBSPrimitive()
00055 {
00056     gluDeleteNurbsRenderer(m_Surface);
00057 }
00058 
00059 NURBSPrimitive* NURBSPrimitive::Clone() const 
00060 {
00061     return new NURBSPrimitive(*this); 
00062 }
00063 
00064 void NURBSPrimitive::PDataDirty()
00065 {
00066     // reset pointers
00067     m_CVVec=GetDataVec<dVector>("p");
00068     m_STVec=GetDataVec<dVector>("t");
00069     m_NVec=GetDataVec<dVector>("n");
00070 }
00071 
00072 void NURBSPrimitive::SetupSurface()
00073 {
00074     m_Surface = gluNewNurbsRenderer();
00075     //gluNurbsProperty(m_Surface, GLU_SAMPLING_METHOD, GLU_PARAMETRIC_ERROR);
00076     //gluNurbsProperty(m_Surface, GLU_PARAMETRIC_TOLERANCE, 5.0);
00077     gluNurbsProperty(m_Surface, GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
00078     gluNurbsProperty(m_Surface, GLU_U_STEP, 20);
00079     gluNurbsProperty(m_Surface, GLU_DISPLAY_MODE, GLU_FILL);
00080     gluNurbsProperty(m_Surface, GLU_CULLING, GLU_TRUE);
00081 }
00082 
00083 void NURBSPrimitive::Render()
00084 {   
00085     if (m_State.Hints & HINT_UNLIT) glDisable(GL_LIGHTING);
00086     
00087     if (m_State.Hints & HINT_AALIAS) glEnable(GL_LINE_SMOOTH);      
00088     else glDisable(GL_LINE_SMOOTH);     
00089         
00090     if (m_State.Hints & HINT_SOLID)
00091     {
00092         gluNurbsProperty(m_Surface, GLU_DISPLAY_MODE, GLU_FILL);
00093     
00094         gluBeginSurface(m_Surface);
00095 
00096         if (!m_STVec->empty())
00097         {
00098             gluNurbsSurface(m_Surface,m_UKnotVec.size(),&(*m_UKnotVec.begin()),m_VKnotVec.size(),&(*m_VKnotVec.begin()),
00099                                      m_VCVCount*m_Stride,m_Stride,
00100                                      m_STVec->begin()->arr(),m_UOrder,m_VOrder,GL_MAP2_TEXTURE_COORD_2);
00101         }
00102         
00103         if (!m_NVec->empty())
00104         {
00105             gluNurbsSurface(m_Surface,m_UKnotVec.size(),&(*m_UKnotVec.begin()),m_VKnotVec.size(),&(*m_VKnotVec.begin()),
00106                                      m_VCVCount*m_Stride,m_Stride,
00107                                      m_NVec->begin()->arr(),m_UOrder,m_VOrder,GL_MAP2_NORMAL);
00108         }
00109         
00110         gluNurbsSurface(m_Surface,m_UKnotVec.size(),&(*m_UKnotVec.begin()),m_VKnotVec.size(),&(*m_VKnotVec.begin()),
00111                                  m_VCVCount*m_Stride,m_Stride,
00112                                  m_CVVec->begin()->arr(),m_UOrder,m_VOrder,GL_MAP2_VERTEX_3);
00113 
00114         gluEndSurface(m_Surface);
00115     }
00116 
00117     if (m_State.Hints & HINT_WIRE)
00118     {
00119         glDisable(GL_LIGHTING);
00120         glColor4fv(m_State.WireColour.arr());
00121         gluNurbsProperty(m_Surface, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
00122 
00123         gluBeginSurface(m_Surface);
00124         gluNurbsSurface(m_Surface,m_UKnotVec.size(),&(*m_UKnotVec.begin()),m_VKnotVec.size(),&(*m_VKnotVec.begin()),
00125                         m_VCVCount*m_Stride,m_Stride,
00126                         m_CVVec->begin()->arr(),m_UOrder,m_VOrder,GL_MAP2_VERTEX_3);
00127 
00128         gluEndSurface(m_Surface);
00129         glEnable(GL_LIGHTING);
00130     }
00131 
00132     if (m_State.Hints & HINT_POINTS)
00133     {
00134         glColor3f(0,0,1);
00135         glDisable(GL_LIGHTING);
00136         glBegin(GL_POINTS);
00137         for (unsigned int n=0; n<m_CVVec->size(); n++)
00138         {
00139             glVertex3fv((*m_CVVec)[n].arr());
00140         }
00141         glEnd();
00142         glEnable(GL_LIGHTING);
00143     }
00144     
00145     if (m_State.Hints & HINT_NORMAL)
00146     {
00147         glColor3f(1,0,0);
00148         glDisable(GL_LIGHTING);
00149         glBegin(GL_LINES);
00150         for (unsigned int i=0; i!=m_CVVec->size(); i++)
00151         {
00152             glVertex3fv((*m_CVVec)[i].arr());
00153             glVertex3fv(((*m_CVVec)[i]+(*m_NVec)[i]).arr());
00154         }
00155         glEnd();
00156         glEnable(GL_LIGHTING);
00157     }
00158     
00159     if (m_State.Hints & HINT_UNLIT) glEnable(GL_LIGHTING);
00160 
00161 }
00162 
00163 void NURBSPrimitive::RecalculateNormals(bool smooth)
00164 {
00165     for (int n=0; n<(int)m_NVec->size(); n++)
00166     {
00167         int u=n-1;
00168         bool flip=false;
00169         if (n%m_VCVCount==0) 
00170         {
00171             u=n+1;
00172             flip=true;
00173         }
00174         
00175         int v=n-m_VCVCount;
00176         
00177         if (n<m_VCVCount) 
00178         {
00179             v=n+m_VCVCount;
00180             flip=true;
00181         }
00182         
00183         dVector a=(*m_CVVec)[n]-(*m_CVVec)[u];
00184         dVector b=(*m_CVVec)[v]-(*m_CVVec)[n];
00185         
00186         a.normalise();
00187         b.normalise();
00188         (*m_NVec)[n]=a.cross(b);
00189         (*m_NVec)[n].normalise();
00190         
00191         if (flip)
00192         {
00193             (*m_NVec)[n]=-(*m_NVec)[n];
00194         }
00195 
00196     }
00197 }
00198 
00199 dBoundingBox NURBSPrimitive::GetBoundingBox()
00200 {   
00201     dBoundingBox box;
00202     for (vector<dVector>::iterator i=m_CVVec->begin();  i!=m_CVVec->end(); ++i)
00203     {
00204         box.expand(*i);
00205     }
00206     return box;
00207 }
00208 
00209 void NURBSPrimitive::ApplyTransform(bool ScaleRotOnly)
00210 {
00211     if (!ScaleRotOnly)
00212     {
00213         for (vector<dVector>::iterator i=m_CVVec->begin(); i!=m_CVVec->end(); ++i)
00214         {
00215             *i=GetState()->Transform.transform(*i);
00216         }
00217     }
00218     else
00219     {
00220         for (vector<dVector>::iterator i=m_CVVec->begin(); i!=m_CVVec->end(); ++i)
00221         {
00222             *i=GetState()->Transform.transform_no_trans(*i);
00223         }
00224     }
00225     
00226     GetState()->Transform.init();
00227 }

Generated on Mon Feb 11 06:54:25 2008 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1