00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <algorithm>
00023
00024 #include <osgDB/Registry>
00025 #include <osgDB/Input>
00026 #include <osgDB/ParameterOutput>
00027
00028 #include "CloudShaderGeometry.hxx"
00029
00030 #include <simgear/props/props.hxx>
00031
00032 using namespace osg;
00033 using namespace osgDB;
00034 using namespace simgear;
00035
00036 namespace
00037 {
00038 struct SpriteComp
00039 {
00040 bool operator() (const CloudShaderGeometry::SortData::SortItem& lhs,
00041 const CloudShaderGeometry::SortData::SortItem& rhs) const
00042 {
00043 return lhs.depth > rhs.depth;
00044 }
00045 };
00046 }
00047 namespace simgear
00048 {
00049 void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
00050 {
00051 if (!_cloudsprites.size()) return;
00052
00053 osg::State& state = *renderInfo.getState();
00054 unsigned int contextID = state.getContextID();
00055 SortData& sortData = _sortData[contextID];
00056 int frameNumber = state.getFrameStamp()->getFrameNumber();
00057
00058 if (!sortData.spriteIdx)
00059 sortData.spriteIdx = new SortData::SortItemList;
00060 if (sortData.spriteIdx->size() < _cloudsprites.size()) {
00061 for (unsigned i = sortData.spriteIdx->size(); i < (unsigned)_cloudsprites.size(); ++i)
00062 sortData.spriteIdx->push_back(SortData::SortItem(i, 0.0f));
00063 sortData.frameSorted = frameNumber - (sortData.skip_limit + 1);
00064 }
00065
00066
00067
00068
00069
00070 if (frameNumber - sortData.skip_limit >= sortData.frameSorted) {
00071 Matrix mvp = state.getModelViewMatrix() * state.getProjectionMatrix();
00072 for (SortData::SortItemList::iterator itr = sortData.spriteIdx->begin(),
00073 end = sortData.spriteIdx->end();
00074 itr != end;
00075 ++itr) {
00076 Vec4f projPos
00077 = Vec4f(toOsg(_cloudsprites[itr->idx].position), 1.0f) * mvp;
00078 itr->depth = projPos.z() / projPos.w();
00079 }
00080
00081 if (std::adjacent_find(sortData.spriteIdx->rbegin(),
00082 sortData.spriteIdx->rend(), SpriteComp())
00083 == sortData.spriteIdx->rend()) {
00084
00085 sortData.skip_limit = sortData.skip_limit * 2;
00086 if (sortData.skip_limit > 30) {
00087
00088
00089 sortData.skip_limit += sg_random() * 10;
00090 }
00091 if (sortData.skip_limit > 128) {
00092
00093 sortData.skip_limit = 128 + sg_random() * 10;
00094 }
00095
00096 } else {
00097 std::sort(sortData.spriteIdx->begin(), sortData.spriteIdx->end(),
00098 SpriteComp());
00099 sortData.skip_limit = 1;
00100 }
00101 sortData.frameSorted = frameNumber;
00102 }
00103
00104 const Extensions* extensions = getExtensions(state.getContextID(),true);
00105
00106 for(SortData::SortItemList::const_iterator itr = sortData.spriteIdx->begin(),
00107 end = sortData.spriteIdx->end();
00108 itr != end;
00109 ++itr) {
00110 const CloudSprite& t = _cloudsprites[itr->idx];
00111 GLfloat ua1[3] = { (GLfloat) t.texture_index_x/varieties_x,
00112 (GLfloat) t.texture_index_y/varieties_y,
00113 (GLfloat) t.width };
00114 GLfloat ua2[3] = { (GLfloat) t.height,
00115 (GLfloat) t.shade,
00116 (GLfloat) t.cloud_height };
00117 extensions->glVertexAttrib3fv(USR_ATTR_1, ua1 );
00118 extensions->glVertexAttrib3fv(USR_ATTR_2, ua2 );
00119 glColor4f(t.position.x(), t.position.y(), t.position.z(), 1.0);
00120 _geometry->draw(renderInfo);
00121 }
00122 }
00123
00124 void CloudShaderGeometry::addSprite(const SGVec3f& p, int tx, int ty,
00125 float w, float h,
00126 float s, float cull, float cloud_height)
00127 {
00128
00129
00130 for (CloudShaderGeometry::CloudSpriteList::iterator iter = _cloudsprites.begin();
00131 iter != _cloudsprites.end();
00132 ++iter)
00133 {
00134 if ((iter != _cloudsprites.begin()) &&
00135 (distSqr(iter->position, p) < cull)) {
00136
00137 return;
00138 }
00139 }
00140
00141 _cloudsprites.push_back(CloudSprite(p, tx, ty, w, h, s, cloud_height));
00142 }
00143
00144 bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
00145 {
00146 bool iteratorAdvanced = false;
00147
00148 CloudShaderGeometry& geom = static_cast<CloudShaderGeometry&>(obj);
00149
00150 if ((fr[0].matchWord("geometry"))) {
00151 ++fr;
00152 iteratorAdvanced = true;
00153 osg::Drawable* drawable = fr.readDrawable();
00154 if (drawable) {
00155 geom._geometry = drawable;
00156 }
00157 }
00158 if ((fr.matchSequence("instances %i"))) {
00159 int entry = fr[0].getNoNestedBrackets();
00160 int capacity;
00161 fr[1].getInt(capacity);
00162 geom._cloudsprites.reserve(capacity);
00163 fr += 3;
00164 iteratorAdvanced = true;
00165
00166 while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
00167 SGVec3f v;
00168 int tx, ty;
00169 float w, h, s, ch;
00170 if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
00171 && fr[2].getFloat(v.z()) && fr[3].getInt(tx) && fr[4].getInt(ty) &&
00172 fr[5].getFloat(w) && fr[6].getFloat(h)&& fr[7].getFloat(s) && fr[8].getFloat(ch)) {
00173 fr += 5;
00174
00175 geom._cloudsprites.push_back(CloudShaderGeometry::CloudSprite(v, tx, ty, w, h,s,ch));
00176 } else {
00177 ++fr;
00178 }
00179 }
00180 }
00181 return iteratorAdvanced;
00182 }
00183
00184 bool CloudShaderGeometry_writeLocalData(const Object& obj, Output& fw)
00185 {
00186 const CloudShaderGeometry& geom = static_cast<const CloudShaderGeometry&>(obj);
00187
00188 fw.indent() << "geometry" << std::endl;
00189 fw.writeObject(*geom._geometry);
00190 fw.indent() << "instances " << geom._cloudsprites.size() << std::endl;
00191 fw.indent() << "{" << std::endl;
00192 fw.moveIn();
00193 for (CloudShaderGeometry::CloudSpriteList::const_iterator itr
00194 = geom._cloudsprites.begin();
00195 itr != geom._cloudsprites.end();
00196 ++itr) {
00197 fw.indent() << itr->position.x() << " " << itr->position.y() << " "
00198 << itr->position.z() << " " << itr->texture_index_x << " "
00199 << itr->texture_index_y << " " << itr->width << " "
00200 << itr->height << " " << itr->shade
00201 << itr->cloud_height << " "<< std::endl;
00202 }
00203 fw.moveOut();
00204 fw.indent() << "}" << std::endl;
00205 return true;
00206 }
00207
00208
00209 osgDB::RegisterDotOsgWrapperProxy cloudShaderGeometryProxy
00210 (
00211 new CloudShaderGeometry,
00212 "CloudShaderGeometry",
00213 "Object Drawable CloudShaderGeometry",
00214 &CloudShaderGeometry_readLocalData,
00215 &CloudShaderGeometry_writeLocalData
00216 );
00217 }