root/OpenSceneGraph/trunk/src/osgPlugins/bsp/Q3BSPReader.cpp @ 13041

Revision 13041, 19.0 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1#include <osg/TexEnv>
2#include <osg/CullFace>
3
4#include <osg/Geode>
5#include <osg/Geometry>
6#include <osg/Image>
7#include <osg/Texture2D>
8#include <osg/PolygonMode>
9#include <osg/BlendColor>
10
11#include <osgDB/ReadFile>
12#include <osgDB/FileNameUtils>
13#include <osgDB/FileUtils>
14
15#include <assert.h>
16#include <fstream>
17
18#include <string.h>
19
20#include "Q3BSPReader.h"
21#include "Q3BSPLoad.h"
22
23#ifndef GL_RGBA8
24    #define GL_RGBA8 0x8058
25#endif
26
27using namespace bsp;
28
29
30Q3BSPReader::Q3BSPReader()
31{
32    root_node = NULL;
33}
34
35
36bool Q3BSPReader::readFile(const std::string& file,
37                           const osgDB::ReaderWriter::Options* options)
38{
39    std::string ext = osgDB::getLowerCaseFileExtension(file);
40
41    Q3BSPLoad load_data;
42    load_data.Load(file,8);
43
44    osg::Geode* geode = convertFromBSP(load_data, options);
45    if (!geode)
46      return false;
47
48    //osg::StateSet* state_set=geode->getOrCreateStateSet();
49    //state_set->setMode(osg::CullFace::BACK,osg::StateAttribute::ON);
50
51    root_node = geode;
52
53    return true;
54}
55
56
57osg::ref_ptr<osg::Node>  Q3BSPReader::getRootNode()
58{
59    return root_node;
60}
61
62
63
64enum BSP_FACE_TYPE
65{
66  bspPolygonFace=1,
67  bspPatch,
68  bspMeshFace,
69  bspBillboard
70};
71
72
73
74
75
76class BSP_VERTEX
77{
78public:
79    osg::Vec3f m_position;
80    float m_decalS, m_decalT;
81    float m_lightmapS, m_lightmapT;
82
83    BSP_VERTEX operator+(const BSP_VERTEX & rhs) const
84      {
85        BSP_VERTEX result;
86        result.m_position=m_position+rhs.m_position;
87        result.m_decalS=m_decalS+rhs.m_decalS;
88        result.m_decalT=m_decalT+rhs.m_decalT;
89        result.m_lightmapS=m_lightmapS+rhs.m_lightmapS;
90        result.m_lightmapT=m_lightmapT+rhs.m_lightmapT;
91
92        return result;
93      }
94
95    BSP_VERTEX operator*(const float rhs) const
96      {
97        BSP_VERTEX result;
98        result.m_position=m_position*rhs;
99        result.m_decalS=m_decalS*rhs;
100        result.m_decalT=m_decalT*rhs;
101        result.m_lightmapS=m_lightmapS*rhs;
102        result.m_lightmapT=m_lightmapT*rhs;
103
104        return result;
105      }
106};
107
108
109
110
111
112//every patch (curved surface) is split into biquadratic (3x3) patches
113class BSP_BIQUADRATIC_PATCH
114{
115public:
116    BSP_BIQUADRATIC_PATCH():m_vertices(32),m_indices(32)
117    {
118    }
119    ~BSP_BIQUADRATIC_PATCH()
120    {
121    }
122
123    bool Tessellate(int newTessellation,osg::Geometry* aGeometry);
124
125    BSP_VERTEX m_controlPoints[9];  // Se accede a ellos en la carga
126
127protected:
128
129    int m_tessellation;
130    std::vector<BSP_VERTEX> m_vertices;
131    std::vector<GLuint> m_indices;
132
133    //arrays for multi_draw_arrays
134    std::vector<int>  m_trianglesPerRow;
135    std::vector<GLuint *>  m_rowIndexPointers;
136
137};
138
139
140//curved surface
141class BSP_PATCH
142{
143public:
144
145    BSP_PATCH():m_quadraticPatches(32)
146    {
147    }
148    ~BSP_PATCH()
149    {
150    }
151
152    int m_textureIndex;
153    int m_lightmapIndex;
154    int m_width, m_height;
155
156    int m_numQuadraticPatches;
157    std::vector<BSP_BIQUADRATIC_PATCH>  m_quadraticPatches;
158};
159
160
161
162
163
164
165
166
167
168osg::Geode* Q3BSPReader::convertFromBSP(
169                            Q3BSPLoad& aLoadData,
170                            const osgDB::ReaderWriter::Options* options) const
171{
172
173  std::vector<osg::Texture2D*> texture_array;
174  loadTextures(aLoadData,texture_array);
175
176  std::vector<osg::Texture2D*> lightmap_array;
177  loadLightMaps(aLoadData,lightmap_array);
178
179  osg::Geode* map_geode=new osg::Geode;
180
181  // Convertir los vertices
182  unsigned int num_load_vertices=aLoadData.m_loadVertices.size();
183  osg::Vec3Array* vertex_array = new osg::Vec3Array(num_load_vertices);
184  osg::Vec2Array* text_decal_array = new osg::Vec2Array(num_load_vertices);
185  osg::Vec2Array* text_lmap_array = new osg::Vec2Array(num_load_vertices);
186
187  float scale = 0.0254;
188  unsigned int i;
189  for(i=0; i<num_load_vertices; ++i)
190    {
191      BSP_LOAD_VERTEX& vtx=aLoadData.m_loadVertices[i];
192      //swap y and z and negate z
193      (*vertex_array)[i]=(osg::Vec3d(  vtx.m_position[0]*scale,
194                                       -vtx.m_position[1]*scale,
195                                       vtx.m_position[2]*scale ) );
196
197      //Transfer texture coordinates (Invert t)
198      (*text_decal_array)[i]=(osg::Vec2d(vtx.m_decalS,-vtx.m_decalT) );
199
200      //Transfer lightmap coordinates
201      (*text_lmap_array)[i]=(osg::Vec2d(vtx.m_lightmapS,vtx.m_lightmapT) );
202    }
203
204
205
206  unsigned int num_loadfaces=aLoadData.m_loadFaces.size();
207
208  //convert loadFaces to faces
209  for(i=0; i<num_loadfaces; ++i)
210    {
211      const BSP_LOAD_FACE& current_load_face=aLoadData.m_loadFaces[i];
212      if(current_load_face.m_type!=bspMeshFace)      //skip this loadFace if it is not a mesh face
213          continue;
214
215      osg::Geometry* mesh_geom=createMeshFace(current_load_face,texture_array,*vertex_array,aLoadData.m_loadMeshIndices,*text_decal_array,*text_lmap_array);
216      map_geode->addDrawable(mesh_geom);
217    }
218
219
220  for(i=0; i<num_loadfaces; ++i)
221    {
222      const BSP_LOAD_FACE& current_face=aLoadData.m_loadFaces[i];
223      if(current_face.m_type!=bspPolygonFace)      //skip this loadFace if it is not a polygon face
224          continue;
225
226      osg::Geometry* polygon_geom=createPolygonFace(current_face,texture_array,lightmap_array,*vertex_array,*text_decal_array,*text_lmap_array);
227      map_geode->addDrawable(polygon_geom);
228    }
229
230
231
232  for(i=0; i<num_loadfaces; ++i)
233    {
234      const BSP_LOAD_FACE& current_face=aLoadData.m_loadFaces[i];
235      if(current_face.m_type!=bspPatch)           //skip this loadFace if it is not a patch face
236          continue;
237
238
239      //osg::Group* patch_group=new osg::Group;
240
241      BSP_PATCH current_patch;
242
243      current_patch.m_textureIndex=current_face.m_texture;
244      current_patch.m_lightmapIndex=current_face.m_lightmapIndex;
245      current_patch.m_width=current_face.m_patchSize[0];
246      current_patch.m_height=current_face.m_patchSize[1];
247
248
249      osg::Texture2D *texture=texture_array[current_face.m_texture];
250      osg::Texture2D *lightmap_texture=NULL;
251      if(current_face.m_lightmapIndex>=0)
252        {
253          lightmap_texture=lightmap_array[current_face.m_lightmapIndex];
254        }
255      else
256        {
257          lightmap_texture=lightmap_array[lightmap_array.size()-1];
258        }
259
260      //Create space to hold quadratic patches
261      int numPatchesWide=(current_patch.m_width-1)/2;
262      int numPatchesHigh=(current_patch.m_height-1)/2;
263
264      current_patch.m_numQuadraticPatches =  numPatchesWide*numPatchesHigh;
265      current_patch.m_quadraticPatches.resize(current_patch.m_numQuadraticPatches);
266
267      //fill in the quadratic patches
268      for(int y=0; y<numPatchesHigh; ++y)
269        {
270          for(int x=0; x<numPatchesWide; ++x)
271            {
272              for(int row=0; row<3; ++row)
273                {
274                  for(int point=0; point<3; ++point)
275                    {
276                      BSP_BIQUADRATIC_PATCH& curr_quadraticpatch=current_patch.m_quadraticPatches[y*numPatchesWide+x];
277
278                      osg::Vec3f vtx= (*vertex_array) [aLoadData.m_loadFaces[i].m_firstVertexIndex+(y*2*current_patch.m_width+x*2)+
279                                                                                              row*current_patch.m_width+point];
280
281                      curr_quadraticpatch.m_controlPoints[row*3+point].m_position[0] = vtx.x();
282                      curr_quadraticpatch.m_controlPoints[row*3+point].m_position[1] = vtx.y();
283                      curr_quadraticpatch.m_controlPoints[row*3+point].m_position[2] = vtx.z();
284
285                    }
286                }
287
288
289
290              osg::Geometry* patch_geom = new osg::Geometry;
291              //tessellate the patch
292
293              osg::StateSet* stateset = patch_geom->getOrCreateStateSet();
294              if(texture)
295              {
296                stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
297              }
298
299              if(lightmap_texture)
300              {
301                  stateset->setTextureAttributeAndModes(1,lightmap_texture,osg::StateAttribute::ON);
302              }
303
304              //patch_group->addChild(map_geode);
305
306              current_patch.m_quadraticPatches[y*numPatchesWide+x].Tessellate(8/*aCurveTessellation*/,patch_geom);
307              map_geode->addDrawable(patch_geom);
308            }
309        }
310
311
312    }
313
314
315  //int num_primitive_sets=geom->getNumPrimitiveSets();
316  //const osg::BoundingSphere& bs=map_geom->getBound();
317
318
319  map_geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
320
321
322  return map_geode;
323}
324
325
326
327osg::Geometry* Q3BSPReader::createMeshFace( const BSP_LOAD_FACE& aLoadFace,const std::vector<osg::Texture2D*>& aTextureArray,
328                                                  osg::Vec3Array& aVertexArray,std::vector<GLuint>& aIndices,
329                                                  osg::Vec2Array& aTextureDecalCoords,osg::Vec2Array& aTextureLMapCoords
330                                                ) const
331{
332
333  osg::Geometry* obj_geom = new osg::Geometry;
334
335
336  osg::Vec3Array* obj_vertex_array = new osg::Vec3Array(aLoadFace.m_numMeshIndices,
337                                                        &(aVertexArray)[aLoadFace.m_firstVertexIndex]
338                                                        );
339  obj_geom->setVertexArray(obj_vertex_array);
340
341  osg::DrawElementsUInt* face_indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES,
342                                                  aLoadFace.m_numMeshIndices,
343                                                  &(aIndices)[0]+aLoadFace.m_firstMeshIndex
344                                                  );
345
346  obj_geom->addPrimitiveSet(face_indices);
347
348  osg::Texture2D *texture=aTextureArray[aLoadFace.m_texture];
349  if(texture)
350    {
351      osg::StateSet* stateset = obj_geom->getOrCreateStateSet();
352      stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
353      stateset->setTextureAttributeAndModes(1,texture,osg::StateAttribute::ON);
354
355      osg::Vec2Array* obj_texcoords_array = new osg::Vec2Array(aLoadFace.m_numMeshIndices,
356                                                        &(aTextureDecalCoords)[aLoadFace.m_firstVertexIndex]
357                                                        );
358      obj_geom->setTexCoordArray(0,obj_texcoords_array);
359
360      osg::Vec2Array* obj_lmapcoords_array = new osg::Vec2Array(aLoadFace.m_numMeshIndices,
361                                                        &(aTextureLMapCoords)[aLoadFace.m_firstVertexIndex]
362                                                        );
363      obj_geom->setTexCoordArray(1,obj_lmapcoords_array);
364    }
365
366  return obj_geom;
367
368
369}
370
371
372
373
374
375
376
377osg::Geometry* Q3BSPReader::createPolygonFace(const BSP_LOAD_FACE& aLoadFace,const std::vector<osg::Texture2D*>& aTextureArray,const std::vector<osg::Texture2D*>& aTextureLMapArray,
378                                  osg::Vec3Array& aVertexArray,
379                                  osg::Vec2Array& aTextureDecalCoords,osg::Vec2Array& aTextureLMapCoords
380                                 ) const
381{
382  osg::Texture2D *texture=aTextureArray[aLoadFace.m_texture];
383
384  osg::Geometry* polygon_geom = new osg::Geometry;
385  polygon_geom->setVertexArray(&aVertexArray);
386  polygon_geom->setTexCoordArray(0, &aTextureDecalCoords);
387  polygon_geom->setTexCoordArray(1, &aTextureLMapCoords);
388
389  osg::DrawArrays* face_indices = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN,
390                                                      aLoadFace.m_firstVertexIndex,
391                                                      aLoadFace.m_numVertices
392                                                     );
393
394  osg::StateSet* stateset = polygon_geom->getOrCreateStateSet();
395  if(texture)
396    {
397      stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
398      if(aLoadFace.m_lightmapIndex>=0)
399        {
400          texture=aTextureLMapArray[aLoadFace.m_lightmapIndex];
401          if(texture)
402            {
403              stateset->setTextureAttributeAndModes(1,texture,osg::StateAttribute::ON);
404            }
405        }
406      else
407        {
408          texture=aTextureLMapArray[aTextureLMapArray.size()-1];
409          if(texture)
410            {
411              stateset->setTextureAttributeAndModes(1,texture,osg::StateAttribute::ON);
412            }
413        }
414
415    }
416  else
417    {
418      osg::PolygonMode* polygon_mode=new osg::PolygonMode;
419      polygon_mode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
420      stateset->setAttributeAndModes(polygon_mode, osg::StateAttribute::ON);
421    }
422
423  polygon_geom->addPrimitiveSet(face_indices);
424  return polygon_geom;
425}
426
427
428
429
430
431
432
433
434
435
436
437
438bool Q3BSPReader::loadTextures(
439                           const Q3BSPLoad& aLoadData,
440                           std::vector<osg::Texture2D*>& aTextureArray) const
441{
442  int num_textures=aLoadData.m_loadTextures.size();
443
444  int i;
445  for(i=0;i<num_textures;i++)
446    {
447      //add file extension to the name
448      std::string tgaExtendedName(aLoadData.m_loadTextures[i].m_name);
449      tgaExtendedName+=".tga";
450      std::string jpgExtendedName(aLoadData.m_loadTextures[i].m_name);
451      jpgExtendedName+=".jpg";
452
453      osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile(tgaExtendedName);
454      if (!image)
455        {
456          image = osgDB::readRefImageFile(jpgExtendedName);
457          if (!image)
458            {
459              aTextureArray.push_back(NULL);
460              continue; //?
461            }
462        }
463
464      osg::Texture2D* texture= new osg::Texture2D;
465      texture->setImage(image.get());
466      texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
467      texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
468      texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
469      aTextureArray.push_back(texture);
470    }
471
472  return true;
473}
474
475
476
477
478
479bool Q3BSPReader::loadLightMaps(
480                            const Q3BSPLoad& aLoadData,
481                            std::vector<osg::Texture2D*>& aTextureArray) const
482{
483  int num_textures=aLoadData.m_loadLightmaps.size();
484
485  int i;
486  for(i=0;i<num_textures;i++)
487    {
488      osg::Image* image=new osg::Image;
489
490      unsigned char *data=new unsigned char[128*128*3];
491      memcpy(data,aLoadData.m_loadLightmaps[i].m_lightmapData,128*128*3);
492
493      image->setImage(128,128,1,GL_RGBA8,GL_RGB,GL_UNSIGNED_BYTE,data,osg::Image::USE_NEW_DELETE);
494
495      osg::Texture2D* texture= new osg::Texture2D;
496      texture->setImage(image);
497      texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
498      texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR_MIPMAP_LINEAR);
499      texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
500      texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
501      texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
502      aTextureArray.push_back(texture);
503    }
504
505
506
507  // A continuación, añado el blanco
508  osg::Image* image=new osg::Image;
509  unsigned char *data=new unsigned char[3];
510  for(int whiteidx=0;whiteidx<3;whiteidx++)
511  {
512      data[whiteidx]=255;
513  }
514
515  image->setImage(1,1,1,GL_RGBA8,GL_RGB,GL_UNSIGNED_BYTE,data,osg::Image::USE_NEW_DELETE);
516
517  osg::Texture2D* texture= new osg::Texture2D;
518  texture->setImage(image);
519  texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
520  texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR_MIPMAP_LINEAR);
521  texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
522  texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
523  texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
524  aTextureArray.push_back(texture);
525
526
527  return true;
528}
529
530
531//Tessellate a biquadratic patch
532bool BSP_BIQUADRATIC_PATCH::Tessellate(int newTessellation,osg::Geometry* aGeometry)
533{
534    m_tessellation=newTessellation;
535
536    float px, py;
537    BSP_VERTEX temp[3];
538    m_vertices.resize((m_tessellation+1)*(m_tessellation+1));
539
540    for(int v=0; v<=m_tessellation; ++v)
541      {
542        px=(float)v/m_tessellation;
543
544        m_vertices[v]=m_controlPoints[0]*((1.0f-px)*(1.0f-px))+
545                      m_controlPoints[3]*((1.0f-px)*px*2)+
546                      m_controlPoints[6]*(px*px);
547      }
548
549    for(int u=1; u<=m_tessellation; ++u)
550      {
551        py=(float)u/m_tessellation;
552
553        temp[0]=m_controlPoints[0]*((1.0f-py)*(1.0f-py))+
554                m_controlPoints[1]*((1.0f-py)*py*2)+
555                m_controlPoints[2]*(py*py);
556
557        temp[1]=m_controlPoints[3]*((1.0f-py)*(1.0f-py))+
558                m_controlPoints[4]*((1.0f-py)*py*2)+
559                m_controlPoints[5]*(py*py);
560
561        temp[2]=m_controlPoints[6]*((1.0f-py)*(1.0f-py))+
562                m_controlPoints[7]*((1.0f-py)*py*2)+
563                m_controlPoints[8]*(py*py);
564
565        for(int v=0; v<=m_tessellation; ++v)
566          {
567            px=(float)v/m_tessellation;
568
569            m_vertices[u*(m_tessellation+1)+v]=temp[0]*((1.0f-px)*(1.0f-px))+
570                                              temp[1]*((1.0f-px)*px*2)+
571                                              temp[2]*(px*px);
572          }
573      }
574
575    //Create indices
576    m_indices.resize(m_tessellation*(m_tessellation+1)*2);
577
578    int row;
579    for(row=0; row<m_tessellation; ++row)
580      {
581        for(int point=0; point<=m_tessellation; ++point)
582          {
583            //calculate indices
584            //reverse them to reverse winding
585            m_indices[(row*(m_tessellation+1)+point)*2+1]= row*(m_tessellation+1)+point;
586            m_indices[(row*(m_tessellation+1)+point)*2]=  (row+1)*(m_tessellation+1)+point;
587          }
588      }
589
590
591    //Fill in the arrays for multi_draw_arrays
592    m_trianglesPerRow.resize(m_tessellation);
593    m_rowIndexPointers.resize(m_tessellation);
594
595    for(row=0; row<m_tessellation; ++row)
596      {
597        m_trianglesPerRow[row]=2*(m_tessellation+1);
598        m_rowIndexPointers[row]=&m_indices[row*2*(m_tessellation+1)];
599      }
600
601
602    osg::Vec3Array* patch_vertex_array = new osg::Vec3Array( (m_tessellation+1)*(m_tessellation+1) );
603    osg::Vec2Array* patch_textcoord_array = new osg::Vec2Array( (m_tessellation+1)*(m_tessellation+1) );
604    osg::Vec2Array* patch_lmapcoord_array = new osg::Vec2Array( (m_tessellation+1)*(m_tessellation+1) );
605    for(int i=0;i<(m_tessellation+1)*(m_tessellation+1);i++)
606      {
607        (*patch_vertex_array)[i].set( m_vertices[ i ].m_position[0],
608                                      m_vertices[ i ].m_position[1],
609                                      m_vertices[ i ].m_position[2]
610                                    );
611
612        (*patch_textcoord_array)[i].set( m_vertices[ i ].m_decalS,
613                                         m_vertices[ i ].m_decalT
614                                       );
615
616        (*patch_lmapcoord_array)[i].set( m_vertices[ i ].m_lightmapS,
617                                         m_vertices[ i ].m_lightmapT
618                                       );
619
620
621      }
622    aGeometry->setVertexArray(patch_vertex_array);
623    aGeometry->setTexCoordArray(0,patch_textcoord_array);
624    aGeometry->setTexCoordArray(1,patch_lmapcoord_array);
625
626
627    for(row=0; row<m_tessellation; ++row)
628      {
629        osg::DrawElementsUInt* face_indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP,
630                                                        m_tessellation*(m_tessellation+1)*2,
631                                                        &m_indices[0]
632                                                        );
633        aGeometry->addPrimitiveSet(face_indices);
634
635      }
636
637
638
639    return true;
640}
641
642
643
644
Note: See TracBrowser for help on using the browser.