1 /* -*-c++-*-
2  *
3  * Copyright (C) 2008 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 #include <osgDB/Registry>
23 #include <osgDB/Input>
24 #include <osgDB/ParameterOutput>
25 
26 #include "ShaderGeometry.hxx"
27 
28 #include <algorithm>
29 
30 using namespace osg;
31 using namespace osgDB;
32 
33 namespace simgear
34 {
addObject(const Vec3 & position,float scale,int texture_index)35 void ShaderGeometry::addObject(const Vec3& position, float scale,
36                                int texture_index)
37 {
38     if (!_posScaleArray.valid()) {
39         _posScaleArray = new Vec4Array();
40         _vertexAttribArray = new FloatArray();
41     }
42     _posScaleArray->push_back(Vec4(position, scale));
43     _vertexAttribArray->push_back((float)texture_index / varieties);
44     dirtyBound();
45 }
46 
drawImplementation(osg::RenderInfo & renderInfo) const47 void ShaderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
48 {
49     State& state = *renderInfo.getState();
50 #if OSG_VERSION_LESS_THAN(3,3,4)
51     const Extensions* extensions = getExtensions(state.getContextID(), true);
52 #else
53     const GLExtensions* extensions = GLExtensions::Get(state.getContextID(), true);
54 #endif
55     Vec4Array::const_iterator citer = _posScaleArray->begin();
56     Vec4Array::const_iterator cend = _posScaleArray->end();
57     FloatArray::const_iterator viter = _vertexAttribArray->begin();
58     for (; citer != cend; ++citer, ++viter) {
59         const Vec4& color = *citer;
60         const float attrib = *viter;
61         glColor4fv(color.ptr());
62         extensions->glVertexAttrib1f(1, attrib);
63         _geometry->draw(renderInfo);
64     }
65 }
66 
67 BoundingBox
68 #if OSG_VERSION_LESS_THAN(3,3,2)
computeBound() const69 ShaderGeometry::computeBound()
70 #else
71 ShaderGeometry::computeBoundingBox()
72 #endif
73 const
74 {
75     const BoundingBox& geom_box =
76 #if OSG_VERSION_LESS_THAN(3,3,2)
77       _geometry->getBound();
78 #else
79       _geometry->getBoundingBox();
80 #endif
81 
82     BoundingBox bb;
83     const Vec4Array* posScales = _posScaleArray.get();
84     if (!posScales)
85         return bb;
86 //    size_t numPosScales = posScales->size();
87     for (Vec4Array::const_iterator iter = _posScaleArray->begin(),
88              e = _posScaleArray->end();
89          iter != e;
90          ++iter) {
91         const Vec4& posScale = *iter;
92         const float scale = posScale.w();
93         const Vec3 pos(posScale.x(), posScale.y(), posScale.z());
94         for (unsigned j = 0; j < 7; ++j)
95             bb.expandBy(geom_box.corner(j) * scale + pos);
96     }
97     return bb;
98 }
99 
ShaderGeometry_readLocalData(Object & obj,Input & fr)100 bool ShaderGeometry_readLocalData(Object& obj, Input& fr)
101 {
102     bool iteratorAdvanced = false;
103 
104     ShaderGeometry& geom = static_cast<ShaderGeometry&>(obj);
105 
106     if ((fr[0].matchWord("geometry"))) {
107         ++fr;
108         iteratorAdvanced = true;
109         osg::Geometry* drawable = dynamic_cast<osg::Geometry*>(fr.readDrawable());
110         if (drawable) {
111             geom._geometry = drawable;
112         }
113     }
114 //    int capacity = 0;
115     if (fr.matchSequence("posScale %i {")) {
116         int entry = fr[1].getNoNestedBrackets();
117         int capacity;
118         fr[1].getInt(capacity);
119         Vec4Array* posScale = new Vec4Array;
120         posScale->reserve(capacity);
121         fr += 3;
122         while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
123             Vec4 v;
124             if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
125                 && fr[2].getFloat(v.z()) && fr[3].getFloat(v.w())) {
126                 fr += 4;
127                 posScale->push_back(v);
128             }
129             else ++fr;
130         }
131         ++fr;
132         geom._posScaleArray = posScale;
133     }
134     if (fr.matchSequence("variety %i {")) {
135         int entry = fr[1].getNoNestedBrackets();
136         int capacity;
137         fr[1].getInt(capacity);
138         FloatArray* variety = new FloatArray;
139         variety->reserve(capacity);
140         fr += 3;
141         while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
142             float val;
143             if (fr[0].getFloat(val)) {
144                 ++fr;
145                 variety->push_back(val);
146             }
147             else ++fr;
148         }
149         ++fr;
150         geom._vertexAttribArray = variety;
151     }
152 
153     return iteratorAdvanced;
154 }
155 
ShaderGeometry_writeLocalData(const Object & obj,Output & fw)156 bool ShaderGeometry_writeLocalData(const Object& obj, Output& fw)
157 {
158     const ShaderGeometry& geom = static_cast<const ShaderGeometry&>(obj);
159 
160     fw.indent() << "geometry" << std::endl;
161     fw.writeObject(*geom._geometry);
162     if (geom._posScaleArray.valid()) {
163         fw.indent() << "posScale " << geom._posScaleArray->size() << " {\n";
164         fw.moveIn();
165         for (Vec4Array::const_iterator iter = geom._posScaleArray->begin();
166              iter != geom._posScaleArray->end();
167              ++iter) {
168             fw.indent() << iter->x() << " " << iter->y() << " " << iter->z() << " "
169                         << iter->w() << "\n";
170         }
171         fw.moveOut();
172         fw.indent() << "}\n";
173     }
174     if (geom._vertexAttribArray.valid()) {
175         fw.indent() << "variety" << geom._vertexAttribArray->size() << " {\n";
176         fw.moveIn();
177         for (FloatArray::const_iterator iter = geom._vertexAttribArray->begin();
178              iter != geom._vertexAttribArray->end();
179              ++iter) {
180             fw.indent() << *iter << "\n";
181         }
182         fw.moveOut();
183         fw.indent() << "}\n";
184     }
185     return true;
186 }
187 
188 osgDB::RegisterDotOsgWrapperProxy shaderGeometryProxy
189 (
190     new ShaderGeometry,
191     "ShaderGeometry",
192     "Object Drawable ShaderGeometry",
193     &ShaderGeometry_readLocalData,
194     &ShaderGeometry_writeLocalData
195     );
196 }
197 
198