00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <algorithm>
00028 # ifdef FC_OS_MACOSX
00029 # include <OpenGL/gl.h>
00030 # include <OpenGL/glu.h>
00031 # else
00032 # include <GL/gl.h>
00033 # include <GL/glu.h>
00034 # endif
00035 # include <Inventor/actions/SoGLRenderAction.h>
00036 # include <Inventor/bundles/SoMaterialBundle.h>
00037 # include <Inventor/elements/SoCoordinateElement.h>
00038 # include <Inventor/elements/SoGLCoordinateElement.h>
00039 # include <Inventor/elements/SoMaterialBindingElement.h>
00040 # include <Inventor/elements/SoProjectionMatrixElement.h>
00041 # include <Inventor/elements/SoViewingMatrixElement.h>
00042 #endif
00043
00044 #include <Gui/SoFCInteractiveElement.h>
00045 #include <Gui/SoFCSelectionAction.h>
00046 #include "SoFCIndexedFaceSet.h"
00047
00048 using namespace MeshGui;
00049
00050
00051 SO_NODE_SOURCE(SoFCIndexedFaceSet);
00052
00053 void SoFCIndexedFaceSet::initClass()
00054 {
00055 SO_NODE_INIT_CLASS(SoFCIndexedFaceSet, SoIndexedFaceSet, "IndexedFaceSet");
00056 }
00057
00058 SoFCIndexedFaceSet::SoFCIndexedFaceSet() : renderTriangleLimit(100000), selectBuf(0)
00059 {
00060 SO_NODE_CONSTRUCTOR(SoFCIndexedFaceSet);
00061 setName(SoFCIndexedFaceSet::getClassTypeId().getName());
00062 }
00063
00067 void SoFCIndexedFaceSet::GLRender(SoGLRenderAction *action)
00068 {
00069 if (this->coordIndex.getNum() < 3)
00070 return;
00071
00072 if (!this->shouldGLRender(action))
00073 return;
00074
00075 SoState * state = action->getState();
00076 SbBool mode = Gui::SoFCInteractiveElement::get(state);
00077
00078 unsigned int num = this->coordIndex.getNum()/4;
00079 if (mode == false || num <= this->renderTriangleLimit) {
00080 inherited::GLRender(action);
00081 }
00082 else {
00083 SoMaterialBindingElement::Binding matbind =
00084 SoMaterialBindingElement::get(state);
00085 int32_t binding = (int32_t)(matbind);
00086
00087 const SoCoordinateElement * coords;
00088 const SbVec3f * normals;
00089 const int32_t * cindices;
00090 int numindices;
00091 const int32_t * nindices;
00092 const int32_t * tindices;
00093 const int32_t * mindices;
00094 SbBool normalCacheUsed;
00095
00096 SoMaterialBundle mb(action);
00097
00098 SoTextureCoordinateBundle tb(action, TRUE, FALSE);
00099 SbBool sendNormals = !mb.isColorOnly() || tb.isFunction();
00100
00101 this->getVertexData(state, coords, normals, cindices,
00102 nindices, tindices, mindices, numindices,
00103 sendNormals, normalCacheUsed);
00104
00105 mb.sendFirst();
00106
00107 drawCoords(static_cast<const SoGLCoordinateElement*>(coords), cindices, numindices,
00108 normals, nindices, &mb, mindices, binding, &tb, tindices);
00109
00110 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
00111 }
00112 }
00113
00114 void SoFCIndexedFaceSet::drawCoords(const SoGLCoordinateElement * const vertexlist,
00115 const int32_t *vertexindices,
00116 int numindices,
00117 const SbVec3f *normals,
00118 const int32_t *normalindices,
00119 SoMaterialBundle *materials,
00120 const int32_t *matindices,
00121 const int32_t binding,
00122 const SoTextureCoordinateBundle * const texcoords,
00123 const int32_t *texindices)
00124 {
00125 const SbVec3f * coords3d = 0;
00126 coords3d = vertexlist->getArrayPtr3();
00127
00128 int mod = numindices/(4*this->renderTriangleLimit)+1;
00129 float size = std::min<float>((float)mod,3.0f);
00130 glPointSize(size);
00131
00132 SbBool per_face = FALSE;
00133 SbBool per_vert = FALSE;
00134 switch (binding) {
00135 case SoMaterialBindingElement::PER_FACE:
00136 per_face = TRUE;
00137 break;
00138 case SoMaterialBindingElement::PER_VERTEX:
00139 per_vert = TRUE;
00140 break;
00141 default:
00142 break;
00143 }
00144
00145 int ct=0;
00146 const int32_t *viptr = vertexindices;
00147 int32_t v1, v2, v3;
00148 SbVec3f dummynormal(0,0,1);
00149 const SbVec3f *currnormal = &dummynormal;
00150 if (normals) currnormal = normals;
00151
00152 glBegin(GL_POINTS);
00153 for (int index=0; index<numindices; ct++) {
00154 if (ct%mod==0) {
00155 if (per_face)
00156 materials->send(ct, TRUE);
00157 v1 = *viptr++; index++;
00158 if (per_vert)
00159 materials->send(v1, TRUE);
00160 if (normals)
00161 currnormal = &normals[*normalindices++];
00162 glNormal3fv((const GLfloat*)currnormal);
00163 glVertex3fv((const GLfloat*)(coords3d + v1));
00164
00165 v2 = *viptr++; index++;
00166 if (per_vert)
00167 materials->send(v2, TRUE);
00168 if (normals)
00169 currnormal = &normals[*normalindices++];
00170 glNormal3fv((const GLfloat*)currnormal);
00171 glVertex3fv((const GLfloat*)(coords3d + v2));
00172
00173 v3 = *viptr++; index++;
00174 if (per_vert)
00175 materials->send(v3, TRUE);
00176 if (normals)
00177 currnormal = &normals[*normalindices++];
00178 glNormal3fv((const GLfloat*)currnormal);
00179 glVertex3fv((const GLfloat*)(coords3d + v3));
00180 }
00181 else {
00182 viptr++; index++; normalindices++;
00183 viptr++; index++; normalindices++;
00184 viptr++; index++; normalindices++;
00185 }
00186
00187 viptr++; index++; normalindices++;
00188 }
00189 glEnd();
00190 }
00191
00192 void SoFCIndexedFaceSet::doAction(SoAction * action)
00193 {
00194 if (action->getTypeId() == Gui::SoGLSelectAction::getClassTypeId()) {
00195 SoNode* node = action->getNodeAppliedTo();
00196 if (!node) return;
00197
00198
00199
00200 SoSearchAction sa;
00201 sa.setInterest(SoSearchAction::FIRST);
00202 sa.setSearchingAll(FALSE);
00203 sa.setType(SoCoordinate3::getClassTypeId(), 1);
00204 sa.apply(node);
00205 SoPath * path = sa.getPath();
00206 if (!path) return;
00207
00208
00209 SoNode* coords = path->getNodeFromTail(0);
00210 if (!(coords && coords->getTypeId().isDerivedFrom(SoCoordinate3::getClassTypeId())))
00211 return;
00212 startSelection(action);
00213 renderSelectionGeometry(static_cast<SoCoordinate3*>(coords)->point.getValues(0));
00214 stopSelection(action);
00215 }
00216 else if (action->getTypeId() == Gui::SoVisibleFaceAction::getClassTypeId()) {
00217 SoNode* node = action->getNodeAppliedTo();
00218 if (!node) return;
00219
00220
00221
00222 SoSearchAction sa;
00223 sa.setInterest(SoSearchAction::FIRST);
00224 sa.setSearchingAll(FALSE);
00225 sa.setType(SoCoordinate3::getClassTypeId(), 1);
00226 sa.apply(node);
00227 SoPath * path = sa.getPath();
00228 if (!path) return;
00229
00230
00231 SoNode* coords = path->getNodeFromTail(0);
00232 if (!(coords && coords->getTypeId().isDerivedFrom(SoCoordinate3::getClassTypeId())))
00233 return;
00234 startVisibility(action);
00235 renderVisibleFaces(static_cast<SoCoordinate3*>(coords)->point.getValues(0));
00236 stopVisibility(action);
00237 }
00238
00239 inherited::doAction(action);
00240 }
00241
00242 void SoFCIndexedFaceSet::startSelection(SoAction * action)
00243 {
00244 Gui::SoGLSelectAction *doaction = static_cast<Gui::SoGLSelectAction*>(action);
00245 const SbViewportRegion& vp = doaction->getViewportRegion();
00246 int x = vp.getViewportOriginPixels()[0];
00247 int y = vp.getViewportOriginPixels()[1];
00248 int w = vp.getViewportSizePixels()[0];
00249 int h = vp.getViewportSizePixels()[1];
00250
00251 int bufSize = 5*(this->coordIndex.getNum()/4);
00252 this->selectBuf = new GLuint[bufSize];
00253
00254 SbMatrix view = SoViewingMatrixElement::get(action->getState());
00255 SbMatrix proj = SoProjectionMatrixElement::get(action->getState());
00256
00257 glSelectBuffer(bufSize, selectBuf);
00258 glRenderMode(GL_SELECT);
00259
00260 glInitNames();
00261 glPushName(-1);
00262
00263
00264 GLint viewport[4];
00265 glGetIntegerv(GL_VIEWPORT,viewport);
00266 glMatrixMode(GL_PROJECTION);
00267
00268 glPushMatrix();
00269 glLoadIdentity();
00270 gluPickMatrix(x, y, w, h, viewport);
00271 glMultMatrixf((float*)proj);
00272 glMatrixMode(GL_MODELVIEW);
00273 glPushMatrix();
00274 glLoadMatrixf((float*)view);
00275 }
00276
00277 void SoFCIndexedFaceSet::stopSelection(SoAction * action)
00278 {
00279
00280 glPopMatrix();
00281 glMatrixMode(GL_PROJECTION);
00282 glPopMatrix();
00283 glMatrixMode(GL_MODELVIEW);
00284 glFlush();
00285
00286
00287 GLint hits = glRenderMode(GL_RENDER);
00288
00289 int bufSize = 5*(this->coordIndex.getNum()/4);
00290 std::vector< std::pair<double,unsigned int> > hit;
00291 GLint index=0;
00292 for (GLint ii=0;ii<hits && index<bufSize;ii++) {
00293 GLint ct = (GLint)selectBuf[index];
00294 hit.push_back(std::pair<double,unsigned int>
00295 (selectBuf[index+1]/4294967295.0,selectBuf[index+3]));
00296 index = index+ct+3;
00297 }
00298
00299 delete [] selectBuf;
00300 selectBuf = 0;
00301 bool sorted = true;
00302 if(sorted) std::sort(hit.begin(),hit.end());
00303
00304 Gui::SoGLSelectAction *doaction = static_cast<Gui::SoGLSelectAction*>(action);
00305 doaction->indices.reserve(hit.size());
00306 for (GLint ii=0;ii<hits;ii++) {
00307 doaction->indices.push_back(hit[ii].second);
00308 }
00309 }
00310
00311 void SoFCIndexedFaceSet::renderSelectionGeometry(const SbVec3f * coords3d)
00312 {
00313 int numfaces = this->coordIndex.getNum()/4;
00314 const int32_t * cindices = this->coordIndex.getValues(0);
00315
00316 int fcnt=0;
00317 int32_t v1, v2, v3;
00318 for (int index=0; index<numfaces;index++,cindices++) {
00319 glLoadName(fcnt);
00320 glBegin(GL_TRIANGLES);
00321 v1 = *cindices++;
00322 glVertex3fv((const GLfloat*)(coords3d + v1));
00323 v2 = *cindices++;
00324 glVertex3fv((const GLfloat*)(coords3d + v2));
00325 v3 = *cindices++;
00326 glVertex3fv((const GLfloat*)(coords3d + v3));
00327 glEnd();
00328 fcnt++;
00329 }
00330 }
00331
00332 void SoFCIndexedFaceSet::startVisibility(SoAction * action)
00333 {
00334 SbMatrix view = SoViewingMatrixElement::get(action->getState());
00335 SbMatrix proj = SoProjectionMatrixElement::get(action->getState());
00336
00337 glMatrixMode(GL_PROJECTION);
00338 glPushMatrix();
00339 glLoadIdentity();
00340 glMultMatrixf((float*)proj);
00341 glMatrixMode(GL_MODELVIEW);
00342 glPushMatrix();
00343 glLoadMatrixf((float*)view);
00344 }
00345
00346 void SoFCIndexedFaceSet::stopVisibility(SoAction * action)
00347 {
00348
00349 glPopMatrix();
00350 glMatrixMode(GL_PROJECTION);
00351 glPopMatrix();
00352 glMatrixMode(GL_MODELVIEW);
00353 glFlush();
00354 }
00355
00356 void SoFCIndexedFaceSet::renderVisibleFaces(const SbVec3f * coords3d)
00357 {
00358
00359
00360
00361
00362
00363 glDisable (GL_BLEND);
00364 glDisable (GL_DITHER);
00365 glDisable (GL_FOG);
00366 glDisable (GL_LIGHTING);
00367 glDisable (GL_TEXTURE_1D);
00368 glDisable (GL_TEXTURE_2D);
00369 glShadeModel (GL_FLAT);
00370
00371 uint32_t numfaces = this->coordIndex.getNum()/4;
00372 const int32_t * cindices = this->coordIndex.getValues(0);
00373
00374 int32_t v1, v2, v3;
00375 for (uint32_t index=0; index<numfaces;index++,cindices++) {
00376 glBegin(GL_TRIANGLES);
00377 float t;
00378 SbColor c;
00379 c.setPackedValue(index<<8,t);
00380 glColor3f(c[0],c[1],c[2]);
00381 v1 = *cindices++;
00382 glVertex3fv((const GLfloat*)(coords3d + v1));
00383 v2 = *cindices++;
00384 glVertex3fv((const GLfloat*)(coords3d + v2));
00385 v3 = *cindices++;
00386 glVertex3fv((const GLfloat*)(coords3d + v3));
00387 glEnd();
00388 }
00389 }