]> git.mxchange.org Git - simgear.git/blob - simgear/scene/sky/CloudShaderGeometry.cxx
Ugly hack to fix a memory corruption problem
[simgear.git] / simgear / scene / sky / CloudShaderGeometry.cxx
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 "CloudShaderGeometry.hxx"
27
28 #include <simgear/props/props.hxx>
29
30 using namespace osg;
31 using namespace osgDB;
32 using namespace simgear;
33
34 namespace simgear
35 {
36 void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
37 {
38     if (!_cloudsprites.size()) return;
39     
40     osg::State& state = *renderInfo.getState();
41     
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
46     // are sorted.
47     
48     skip_info->skip_count = (skip_info->skip_count + 1) % skip_info->skip_limit;
49     
50     if (skip_info->skip_count == 0)
51     {
52         osg::Matrix vm = state.getModelViewMatrix();
53         bool sorted = true;
54         
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!
58     
59         float p = view_dir*_cloudsprites[0]->position.osg();
60         // Do a single iteration of a bubble sort, sorting
61         // back to front.
62         for(int i = 0; i < _cloudsprites.size() - 1; i++)
63         {
64             float q = view_dir*_cloudsprites[i+1]->position.osg();
65             if (p > q) {  
66                 CloudSprite c = *_cloudsprites[i];
67                 *_cloudsprites[i] = *_cloudsprites[i+1];
68                 *_cloudsprites[i+1] = c;
69                 
70                 sorted = false;
71             }
72             else
73                 p = q;
74         }
75         
76         
77         if (sorted)
78         {
79             // This cloud is sorted, so no need to re-sort.
80             skip_info->skip_limit = skip_info->skip_limit * 2;
81             
82             if (skip_info->skip_limit > 30) 
83             {
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;
87             }
88             
89             if (skip_info->skip_limit > 128) 
90             {
91                 // Maximum of every 128 frames (2 - 4 seconds)
92                 skip_info->skip_limit = 128 + sg_random() * 10;
93             }
94         }
95         else
96         {
97             // This cloud is unsorted, so we need to sort next frame
98             skip_info->skip_limit = 1;
99         }
100     }
101
102     const Extensions* extensions = getExtensions(state.getContextID(),true);
103
104     for(CloudSpriteList::const_iterator t = _cloudsprites.begin(); t != _cloudsprites.end(); ++t)
105     {
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);
114     }
115 }
116     
117 bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
118 {
119     bool iteratorAdvanced = false;
120
121     CloudShaderGeometry& geom = static_cast<CloudShaderGeometry&>(obj);
122
123     if ((fr[0].matchWord("geometry"))) {
124         ++fr;
125         iteratorAdvanced = true;
126         osg::Drawable* drawable = fr.readDrawable();
127         if (drawable) {
128             geom._geometry = drawable;
129         }
130     }
131     if ((fr.matchSequence("instances %i"))) {
132         int entry = fr[0].getNoNestedBrackets();
133         int capacity;
134         fr[1].getInt(capacity);
135         geom._cloudsprites.reserve(capacity);
136         fr += 3;
137         iteratorAdvanced = true;
138         // skip {
139         while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
140             SGVec3f v;
141             int tx, ty;
142             float w, h, s, ch;
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)) {
146                     fr += 5;
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));
149             } else {
150                 ++fr;
151             }
152         }
153     }
154     return iteratorAdvanced;
155 }
156
157 bool CloudShaderGeometry_writeLocalData(const Object& obj, Output& fw)
158 {
159     const CloudShaderGeometry& geom = static_cast<const CloudShaderGeometry&>(obj);
160
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;
165     fw.moveIn();
166     for (CloudShaderGeometry::CloudSpriteList::const_iterator itr
167              = geom._cloudsprites.begin();
168          itr != geom._cloudsprites.end();
169          ++itr) {
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;
175     }
176     fw.moveOut();
177     fw.indent() << "}" << std::endl;
178     return true;
179 }
180
181
182 osgDB::RegisterDotOsgWrapperProxy cloudShaderGeometryProxy
183 (
184     new CloudShaderGeometry,
185     "CloudShaderGeometry",
186     "Object Drawable CloudShaderGeometry",
187     &CloudShaderGeometry_readLocalData,
188     &CloudShaderGeometry_writeLocalData
189     );
190 }