00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "PrimitiveUtils.hxx"
00023 #include <iostream>
00024 using namespace osg;
00025
00026 namespace
00027 {
00028 class GetPrimitive : public PrimitiveFunctor
00029 {
00030 public:
00031 simgear::Primitive result;
00032 GetPrimitive(unsigned int primitiveIndex)
00033 : _primitiveIndex(primitiveIndex), _primitivesSeen(0),
00034 _vertexArrayPtr(0), _modeCache(0)
00035 {
00036 result.numVerts = 0;
00037 }
00038
00039 virtual void setVertexArray(unsigned int,const Vec2*)
00040 {
00041 notify(WARN)<<"GetPrimitive does not support Vec2* vertex arrays"<<std::endl;
00042 }
00043
00044 virtual void setVertexArray(unsigned int count,const Vec3* vertices)
00045 {
00046 _vertexArrayPtr = vertices;
00047 }
00048
00049 virtual void setVertexArray(unsigned int,const Vec4* )
00050 {
00051 notify(WARN)<<"GetPrimitive does not support Vec4* vertex arrays"<<std::endl;
00052 }
00053
00054 virtual void setVertexArray(unsigned int,const Vec2d*)
00055 {
00056 notify(WARN)<<"GetPrimitive does not support Vec2d* vertex arrays"<<std::endl;
00057 }
00058
00059 virtual void setVertexArray(unsigned int,const Vec3d*)
00060 {
00061 notify(WARN)<<"GetPrimitive does not support Vec3d* vertex arrays"<<std::endl;
00062 }
00063
00064 virtual void setVertexArray(unsigned int,const Vec4d* )
00065 {
00066 notify(WARN)<<"GetPrimitive does not support Vec4d* vertex arrays"<<std::endl;
00067 }
00068
00069 void drawArrays(GLenum mode_, GLint first, GLsizei count)
00070 {
00071 if (_primitiveIndex < _primitivesSeen) {
00072 return;
00073 }
00074 int numPrims = getNumPrims(mode_, count);
00075 if (_primitivesSeen + numPrims < _primitiveIndex) {
00076 _primitivesSeen += numPrims;
00077 return;
00078 }
00079 int primInSet = _primitiveIndex - _primitivesSeen;
00080 switch (mode_) {
00081 case GL_POINTS:
00082 result.numVerts = 1;
00083 result.vertices[0] = _vertexArrayPtr[first + primInSet];
00084 break;
00085 case GL_LINES:
00086 result.numVerts = 2;
00087 result.vertices[0] = _vertexArrayPtr[first + primInSet * 2];
00088 result.vertices[1] = _vertexArrayPtr[first + primInSet * 2 + 1];
00089 break;
00090 case GL_TRIANGLES:
00091 result.numVerts = 3;
00092 for (int i = 0; i < 3; ++i)
00093 result.vertices[i] = _vertexArrayPtr[first + primInSet * 3 + i];
00094 break;
00095 case GL_QUADS:
00096 result.numVerts = 4;
00097 for (int i = 0; i < 4; ++i)
00098 result.vertices[i] = _vertexArrayPtr[first + primInSet * 4 + i];
00099 break;
00100 case GL_LINE_STRIP:
00101 result.numVerts = 2;
00102 result.vertices[0] = _vertexArrayPtr[first + primInSet];
00103 result.vertices[1] = _vertexArrayPtr[first + primInSet + 1];
00104 break;
00105 case GL_LINE_LOOP:
00106 result.numVerts = 2;
00107 if (primInSet < numPrims - 1) {
00108 result.vertices[0] = _vertexArrayPtr[first + primInSet];
00109 result.vertices[1] = _vertexArrayPtr[first + primInSet + 1];
00110 } else {
00111 result.vertices[0] = _vertexArrayPtr[first + count - 1];
00112 result.vertices[1] = _vertexArrayPtr[first];
00113 }
00114 break;
00115 case GL_TRIANGLE_STRIP:
00116 result.numVerts = 3;
00117 result.vertices[0] = _vertexArrayPtr[first + primInSet];
00118 if (primInSet % 2) {
00119 result.vertices[1] = _vertexArrayPtr[first + primInSet + 2];
00120 result.vertices[2] = _vertexArrayPtr[first + primInSet + 1];
00121 } else {
00122 result.vertices[1] = _vertexArrayPtr[first + primInSet + 1];
00123 result.vertices[2] = _vertexArrayPtr[first + primInSet + 2];
00124 }
00125 break;
00126 case GL_TRIANGLE_FAN:
00127 case GL_POLYGON:
00128 result.numVerts = 3;
00129 result.vertices[0] = _vertexArrayPtr[first];
00130 result.vertices[1] = _vertexArrayPtr[first + 1 + primInSet];
00131 result.vertices[2] = _vertexArrayPtr[first + 1 + primInSet + 1];
00132 break;
00133 case GL_QUAD_STRIP:
00134 result.numVerts = 4;
00135 result.vertices[0] = _vertexArrayPtr[first + primInSet / 2];
00136 result.vertices[1] = _vertexArrayPtr[first + primInSet / 2 + 1];
00137 result.vertices[2] = _vertexArrayPtr[first + primInSet / 2 + 3];
00138 result.vertices[3] = _vertexArrayPtr[first + primInSet / 2 + 2];
00139 break;
00140 default:
00141 break;
00142 }
00143 _primitivesSeen += numPrims;
00144 }
00145
00146 template<class IndexType>
00147 void drawElementsTemplate(GLenum mode_, GLsizei count,
00148 const IndexType* indices)
00149 {
00150 if (_primitiveIndex < _primitivesSeen) {
00151 return;
00152 }
00153 int numPrims = getNumPrims(mode_, count);
00154 if (_primitivesSeen + numPrims < _primitiveIndex) {
00155 _primitivesSeen += numPrims;
00156 return;
00157 }
00158 int primInSet = _primitiveIndex - _primitivesSeen;
00159 switch (mode_) {
00160 case GL_POINTS:
00161 result.numVerts = 1;
00162 result.vertices[0] = _vertexArrayPtr[indices[primInSet]];
00163 break;
00164 case GL_LINES:
00165 result.numVerts = 2;
00166 result.vertices[0] = _vertexArrayPtr[indices[primInSet * 2]];
00167 result.vertices[1] = _vertexArrayPtr[indices[primInSet * 2 + 1]];
00168 break;
00169 case GL_TRIANGLES:
00170 result.numVerts = 3;
00171 for (int i = 0; i < 3; ++i)
00172 result.vertices[i] = _vertexArrayPtr[indices[primInSet * 3 + i]];
00173 break;
00174 case GL_QUADS:
00175 result.numVerts = 4;
00176 for (int i = 0; i < 4; ++i)
00177 result.vertices[i] = _vertexArrayPtr[indices[primInSet * 4 + i]];
00178 break;
00179 case GL_LINE_STRIP:
00180 result.numVerts = 2;
00181 result.vertices[0] = _vertexArrayPtr[indices[primInSet]];
00182 result.vertices[1] = _vertexArrayPtr[indices[primInSet + 1]];
00183 break;
00184 case GL_LINE_LOOP:
00185 result.numVerts = 2;
00186 if (primInSet < numPrims - 1) {
00187 result.vertices[0] = _vertexArrayPtr[indices[primInSet]];
00188 result.vertices[1] = _vertexArrayPtr[indices[primInSet + 1]];
00189 } else {
00190 result.vertices[0] = _vertexArrayPtr[indices[count - 1]];
00191 result.vertices[1] = _vertexArrayPtr[indices[0]];
00192 }
00193 break;
00194 case GL_TRIANGLE_STRIP:
00195 result.numVerts = 3;
00196 result.vertices[0] = _vertexArrayPtr[indices[primInSet]];
00197 if (primInSet % 2) {
00198 result.vertices[1] = _vertexArrayPtr[indices[primInSet + 2]];
00199 result.vertices[2] = _vertexArrayPtr[indices[primInSet + 1]];
00200 } else {
00201 result.vertices[1] = _vertexArrayPtr[indices[primInSet + 1]];
00202 result.vertices[2] = _vertexArrayPtr[indices[primInSet + 2]];
00203 }
00204 break;
00205 case GL_TRIANGLE_FAN:
00206 case GL_POLYGON:
00207 result.numVerts = 3;
00208 result.vertices[0] = _vertexArrayPtr[indices[0]];
00209 result.vertices[1] = _vertexArrayPtr[indices[1 + primInSet]];
00210 result.vertices[2] = _vertexArrayPtr[indices[1 + primInSet + 1]];
00211 break;
00212 case GL_QUAD_STRIP:
00213 result.numVerts = 4;
00214 result.vertices[0] = _vertexArrayPtr[indices[primInSet / 2]];
00215 result.vertices[1] = _vertexArrayPtr[indices[primInSet / 2 + 1]];
00216 result.vertices[2] = _vertexArrayPtr[indices[primInSet / 2 + 3]];
00217 result.vertices[3] = _vertexArrayPtr[indices[primInSet / 2 + 2]];
00218 break;
00219 default:
00220 break;
00221 }
00222 _primitivesSeen += numPrims;
00223 }
00224
00225 void drawElements(GLenum mode_, GLsizei count, const GLubyte* indices)
00226 {
00227 drawElementsTemplate(mode_, count, indices);
00228 }
00229
00230 void drawElements(GLenum mode_, GLsizei count, const GLushort* indices)
00231 {
00232 drawElementsTemplate(mode_, count, indices);
00233 }
00234
00235 void drawElements(GLenum mode_,GLsizei count,const GLuint* indices)
00236 {
00237 drawElementsTemplate(mode_, count, indices);
00238 }
00239
00240 virtual void begin(GLenum mode)
00241 {
00242 _modeCache = mode;
00243 _vertexCache.clear();
00244 }
00245
00246 void vertex(const Vec2& vert)
00247 {
00248 _vertexCache.push_back(osg::Vec3(vert[0],vert[1],0.0f));
00249 }
00250 void vertex(const Vec3& vert)
00251 {
00252 _vertexCache.push_back(vert);
00253 }
00254 void vertex(const Vec4& vert)
00255 {
00256 _vertexCache.push_back(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]);
00257 }
00258 void vertex(float x,float y)
00259 {
00260 _vertexCache.push_back(osg::Vec3(x,y,0.0f));
00261 }
00262 void vertex(float x,float y,float z)
00263 {
00264 _vertexCache.push_back(osg::Vec3(x,y,z));
00265 }
00266 void vertex(float x,float y,float z,float w)
00267 {
00268 _vertexCache.push_back(osg::Vec3(x,y,z)/w);
00269
00270 }
00271
00272 void end()
00273 {
00274 if (!_vertexCache.empty()) {
00275 const Vec3* oldVert = _vertexArrayPtr;
00276 setVertexArray(_vertexCache.size(), &_vertexCache.front());
00277 drawArrays(_modeCache, 0, _vertexCache.size());
00278 _vertexArrayPtr = oldVert;
00279 }
00280 }
00281
00282 protected:
00283 int getNumPrims(GLenum mode, int count)
00284 {
00285 switch (mode) {
00286 case GL_POINTS:
00287 return count;
00288 case GL_LINES:
00289 return count / 2;
00290 case GL_TRIANGLES:
00291 return count / 3;
00292 case GL_QUADS:
00293 return count / 4;
00294 case GL_LINE_STRIP:
00295 return count - 1;
00296 case GL_LINE_LOOP:
00297 return count;
00298 case GL_TRIANGLE_STRIP:
00299 return count - 2;
00300 case GL_TRIANGLE_FAN:
00301 case GL_POLYGON:
00302 return count - 2;
00303 case GL_QUAD_STRIP:
00304 return (count - 2) / 2;
00305 default:
00306 std::cerr << "FATAL: unknown GL mode " << mode << std::endl;
00307 throw new std::exception();
00308 }
00309 }
00310 unsigned _primitiveIndex;
00311 unsigned _primitivesSeen;
00312 const Vec3* _vertexArrayPtr;
00313 GLenum _modeCache;
00314 std::vector<Vec3> _vertexCache;
00315 };
00316 }
00317
00318 namespace simgear
00319 {
00320 Primitive getPrimitive(Drawable* drawable, unsigned primitiveIndex)
00321 {
00322 GetPrimitive getPrim(primitiveIndex);
00323 drawable->accept(getPrim);
00324 return getPrim.result;
00325 }
00326 }