3 * Copyright (C) 2008 Stuart Buchanan
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.
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.
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,
22 #include <osgDB/Registry>
23 #include <osgDB/Input>
24 #include <osgDB/ParameterOutput>
26 #include "CloudShaderGeometry.hxx"
28 #include <simgear/props/props.hxx>
31 using namespace osgDB;
32 using namespace simgear;
36 void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
38 if (!_cloudsprites.size()) return;
40 osg::State& state = *renderInfo.getState();
42 // If the cloud is already sorted, then it is likely to still be sorted.
43 // Therefore we can avoid re-sorting it for a period. If it is still
44 // sorted after that period, then we can wait for a longer period before
45 // checking again. In this way, only clouds that are changing regularly
48 skip_info->skip_count = (skip_info->skip_count + 1) % skip_info->skip_limit;
50 if (skip_info->skip_count == 0)
52 osg::Matrix vm = state.getModelViewMatrix();
55 // Transform the viewing direction, represented by the eye space vector (0,0,-1, 0), into model-space
56 // (here we simply take the opposite direction and reverse the ordering when sorting)
57 osg::Vec3f view_dir(vm(0, 2), vm(1, 2), vm(2, 2)); // Caveat: OpenSceneGraph matrices are transposed!
59 float p = view_dir*_cloudsprites[0]->position.osg();
60 // Do a single iteration of a bubble sort, sorting
62 for(int i = 0; i < _cloudsprites.size() - 1; i++)
64 float q = view_dir*_cloudsprites[i+1]->position.osg();
66 CloudSprite c = *_cloudsprites[i];
67 *_cloudsprites[i] = *_cloudsprites[i+1];
68 *_cloudsprites[i+1] = c;
79 // This cloud is sorted, so no need to re-sort.
80 skip_info->skip_limit = skip_info->skip_limit * 2;
82 if (skip_info->skip_limit > 30)
84 // Jitter the skip frames to avoid synchronized sorts
85 // which will cause periodic frame-rate drops
86 skip_info->skip_limit += sg_random() * 10;
89 if (skip_info->skip_limit > 128)
91 // Maximum of every 128 frames (2 - 4 seconds)
92 skip_info->skip_limit = 128 + sg_random() * 10;
97 // This cloud is unsorted, so we need to sort next frame
98 skip_info->skip_limit = 1;
102 const Extensions* extensions = getExtensions(state.getContextID(),true);
104 for(CloudSpriteList::const_iterator t = _cloudsprites.begin(); t != _cloudsprites.end(); ++t)
106 extensions->glVertexAttrib1f(TEXTURE_INDEX_X, (GLfloat) (*t)->texture_index_x/varieties_x);
107 extensions->glVertexAttrib1f(TEXTURE_INDEX_Y, (GLfloat) (*t)->texture_index_y/varieties_y);
108 extensions->glVertexAttrib1f(WIDTH, (GLfloat) (*t)->width);
109 extensions->glVertexAttrib1f(HEIGHT, (GLfloat) (*t)->height);
110 extensions->glVertexAttrib1f(SHADE, (GLfloat) (*t)->shade);
111 extensions->glVertexAttrib1f(CLOUD_HEIGHT, (GLfloat) (*t)->cloud_height);
112 glColor4f((*t)->position.x(), (*t)->position.y(), (*t)->position.z(), 1.0);
113 _geometry->draw(renderInfo);
117 bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
119 bool iteratorAdvanced = false;
121 CloudShaderGeometry& geom = static_cast<CloudShaderGeometry&>(obj);
123 if ((fr[0].matchWord("geometry"))) {
125 iteratorAdvanced = true;
126 osg::Drawable* drawable = fr.readDrawable();
128 geom._geometry = drawable;
131 if ((fr.matchSequence("instances %i"))) {
132 int entry = fr[0].getNoNestedBrackets();
134 fr[1].getInt(capacity);
135 geom._cloudsprites.reserve(capacity);
137 iteratorAdvanced = true;
139 while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
143 if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
144 && fr[2].getFloat(v.z()) && fr[3].getInt(tx) && fr[4].getInt(ty) &&
145 fr[5].getFloat(w) && fr[6].getFloat(h)&& fr[7].getFloat(s) && fr[8].getFloat(ch)) {
147 //SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z());
148 geom._cloudsprites.push_back(new CloudShaderGeometry::CloudSprite(v, tx, ty, w, h,s,ch));
154 return iteratorAdvanced;
157 bool CloudShaderGeometry_writeLocalData(const Object& obj, Output& fw)
159 const CloudShaderGeometry& geom = static_cast<const CloudShaderGeometry&>(obj);
161 fw.indent() << "geometry" << std::endl;
162 fw.writeObject(*geom._geometry);
163 fw.indent() << "instances " << geom._cloudsprites.size() << std::endl;
164 fw.indent() << "{" << std::endl;
166 for (CloudShaderGeometry::CloudSpriteList::const_iterator itr
167 = geom._cloudsprites.begin();
168 itr != geom._cloudsprites.end();
170 fw.indent() << (*itr)->position.x() << " " << (*itr)->position.y() << " "
171 << (*itr)->position.z() << " " << (*itr)->texture_index_x << " "
172 << (*itr)->texture_index_y << " " << (*itr)->width << " "
173 << (*itr)->height << " " << (*itr)->shade
174 << (*itr)->cloud_height << " "<< std::endl;
177 fw.indent() << "}" << std::endl;
182 osgDB::RegisterDotOsgWrapperProxy cloudShaderGeometryProxy
184 new CloudShaderGeometry,
185 "CloudShaderGeometry",
186 "Object Drawable CloudShaderGeometry",
187 &CloudShaderGeometry_readLocalData,
188 &CloudShaderGeometry_writeLocalData