1 /* -*-c++-*-
2  *
3  * Copyright (C) 2011 Stuart Buchanan
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21 
22 #ifndef SG_BUILDING_BIN_HXX
23 #define SG_BUILDING_BIN_HXX
24 
25 #include <math.h>
26 
27 #include <vector>
28 #include <string>
29 
30 #include <osg/Geode>
31 #include <osg/Geometry>
32 #include <osg/Math>
33 #include <osg/MatrixTransform>
34 #include <osg/Matrix>
35 #include <osg/ShadeModel>
36 #include <osg/Material>
37 #include <osg/CullFace>
38 #include <osg/VertexAttribDivisor>
39 
40 #include <simgear/scene/util/OsgMath.hxx>
41 #include <simgear/scene/material/mat.hxx>
42 
43 #include <simgear/scene/material/Effect.hxx>
44 #include <simgear/scene/material/EffectGeode.hxx>
45 
46 #include <simgear/scene/util/QuadTreeBuilder.hxx>
47 #include <simgear/scene/util/RenderConstants.hxx>
48 #include <simgear/scene/util/StateAttributeFactory.hxx>
49 #include <simgear/structure/OSGUtils.hxx>
50 
51 #define SG_BUILDING_QUAD_TREE_DEPTH 2
52 #define SG_BUILDING_FADE_OUT_LEVELS 4
53 
54 // these correspond to building.eff
55 const int BUILDING_POSITION_ATTR = 10;  // (x,y,z)
56 const int BUILDING_SCALE_ATTR = 11; // (width, depth, height)
57 const int BUILDING_ATTR1 = 12;
58 const int BUILDING_ATTR2 = 13;
59 const int BUILDING_ATTR3 = 14;
60 const int BUILDING_ATTR4 = 15;
61 
62 using namespace osg;
63 
64 namespace simgear
65 {
66 
67 struct BuildingBoundingBoxCallback : public Drawable::ComputeBoundingBoxCallback
68 {
BuildingBoundingBoxCallbacksimgear::BuildingBoundingBoxCallback69     BuildingBoundingBoxCallback() {}
BuildingBoundingBoxCallbacksimgear::BuildingBoundingBoxCallback70     BuildingBoundingBoxCallback(const BuildingBoundingBoxCallback&, const CopyOp&) {}
71     META_Object(simgear, BuildingBoundingBoxCallback);
computeBoundsimgear::BuildingBoundingBoxCallback72     virtual BoundingBox computeBound(const Drawable& drawable) const
73     {
74         BoundingBox bb;
75         const Geometry* geom = static_cast<const Geometry*>(&drawable);
76         const Vec3Array* pos = static_cast<const Vec3Array*>(geom->getVertexAttribArray(BUILDING_POSITION_ATTR));
77 
78         for (unsigned int v=0; v<pos->size(); ++v) {
79             Vec3 pt = (*pos)[v];
80             bb.expandBy(pt);
81         }
82         return bb;
83     }
84 };
85 
86 class SGBuildingBin {
87 public:
88 
89   enum BuildingType {
90     SMALL = 0,
91     MEDIUM,
92     LARGE };
93 
94     struct BuildingInstance {
BuildingInstancesimgear::SGBuildingBin::BuildingInstance95       BuildingInstance(Vec3f p, float w, float d, float h, float ph, float r, Vec2f wt0, Vec2f rt0, Vec3f t1, Vec2f rs) :
96         position(p),
97         width(w),
98         depth(d),
99         height(h),
100         pitch_height(ph),
101         rotation(r),
102         walltex0(wt0),
103         rooftex0(rt0),
104         tex1(t1),
105         rooftop_scale(rs)
106       { }
107 
BuildingInstancesimgear::SGBuildingBin::BuildingInstance108       BuildingInstance(Vec3f p, BuildingInstance b) :
109         position(p),
110         width(b.width),
111         depth(b.depth),
112         height(b.height),
113         pitch_height(b.pitch_height),
114         rotation(b.rotation),
115         walltex0(b.walltex0),
116         rooftex0(b.rooftex0),
117         tex1(b.tex1),
118         rooftop_scale(b.rooftop_scale)
119       { }
120 
121 
122       Vec3f position;
123       float width;
124       float depth;
125       float height;
126       float pitch_height;
127       float rotation;
128 
129       Vec2f walltex0;
130       Vec2f rooftex0;
131       Vec3f tex1; // Texture gains for the front, roof and sides
132 
133       Vec2f rooftop_scale;
134 
135       // References to allow the QuadTreeBuilder to work
136       //const BuildingList* buildingList;
137       //ref_ptr<Geometry> sharedGeometry;
138 
getPositionsimgear::SGBuildingBin::BuildingInstance139       Vec3f getPosition() { return position; }
getRotationsimgear::SGBuildingBin::BuildingInstance140       float getRotation() { return rotation; }
141 
getDistSqrsimgear::SGBuildingBin::BuildingInstance142       float getDistSqr(Vec3f p) {
143         return (p - position) * (p - position);
144       }
145     };
146 
147 private:
148     const SGSharedPtr<SGMaterial> _material;
149 
150     std::string _materialName;
151     std::string _textureName;
152     std::string _lightMapName;
153 
154     // Visibility range for buildings
155     float buildingRange;
156 
157 
158     // Information for an instance of a building - position and orientation
159     typedef std::vector<BuildingInstance> BuildingInstanceList;
160     BuildingInstanceList buildingLocations;
161 
162 public:
163 
164   SGBuildingBin(const SGMaterial *mat, bool useVBOs);
165   SGBuildingBin(const SGPath& absoluteFileName, const SGMaterial *mat, bool useVBOs);
166 
167   ~SGBuildingBin();
168 
169   // Generate a building specifying the exact position, dimensions and texture index.
170   void insert(SGVec3f p,
171               float r,
172               BuildingType buildingtype,
173               float width,
174               float depth,
175               float height,
176               float pitch_height,
177               int floors,
178               int roof_shape,
179               int roof_orientation,
180               int wall_tex_index,
181               int roof_tex_index);
182 
183   // Generate a building of a given type at a specified position, using the random building material definition to determine the dimensions and texture index.
184   void insert(SGVec3f p, float r, BuildingType type);
185   int getNumBuildings();
186 
187   bool checkMinDist (SGVec3f p, float radius);
188 
getMaterialName() const189   const std::string& getMaterialName() const { return _materialName; }
190 
191   BuildingType getBuildingType(float roll);
192   float getBuildingMaxRadius(BuildingType);
193   float getBuildingMaxDepth(BuildingType);
194 
195   ref_ptr<Group> createBuildingsGroup(Matrix transInv, const SGReaderWriterOptions* options);
196 
197 };
198 
199 // List of buildings
200 typedef std::list<SGBuildingBin*> SGBuildingBinList;
201 
202 
203 osg::Group* createRandomBuildings(SGBuildingBinList& buildinglist, const osg::Matrix& transform,
204                          const SGReaderWriterOptions* options);
205 }
206 #endif
207