1
+ #include < osg/Texture2D>
2
+ #include < osg/Texture2DArray>
1
3
#include < osgDB/FileUtils>
2
4
#include < osgDB/Registry>
3
5
#include < osgDB/Input>
@@ -19,9 +21,11 @@ void applyUserTerrains( TerrainDataProxyMap& tdMap, const std::string& dbPath )
19
21
for ( short x=0 ; x<proxy->heightMapSize [0 ]; ++x )
20
22
{
21
23
int index = int (x) + int (y) * int (proxy->heightMapSize [0 ]);
22
- va->push_back ( osg::Vec3 (float (y) * proxy->size [2 ] / float (proxy->heightMapSize [1 ] - 1 ),
23
- proxy->heightMap [index ] * proxy->size [1 ],
24
- float (x) * proxy->size [0 ] / float (proxy->heightMapSize [0 ] - 1 )) );
24
+ float tx = float (y) / float (proxy->heightMapSize [1 ] - 1 );
25
+ float ty = float (x) / float (proxy->heightMapSize [0 ] - 1 );
26
+ va->push_back ( osg::Vec3 (
27
+ tx * proxy->size [2 ], proxy->heightMap [index ] * proxy->size [1 ], ty * proxy->size [0 ]) );
28
+ ta->push_back ( osg::Vec2 (ty, tx) );
25
29
}
26
30
}
27
31
@@ -37,11 +41,63 @@ void applyUserTerrains( TerrainDataProxyMap& tdMap, const std::string& dbPath )
37
41
}
38
42
}
39
43
44
+ // Create splat texture array
45
+ osg::ref_ptr<osg::Texture2DArray> splatTexture = new osg::Texture2DArray;
46
+ splatTexture->setTextureDepth ( proxy->layers );
47
+ splatTexture->setWrap ( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT );
48
+ splatTexture->setWrap ( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT );
49
+ splatTexture->setFilter ( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR );
50
+ splatTexture->setFilter ( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );
51
+
52
+ int splatW = 0 , splatH = 0 ;
53
+ for ( int i=0 ; i<proxy->layers ; ++i )
54
+ {
55
+ osg::Image* image = osgDB::readImageFile (proxy->splatTextures [i]);
56
+ splatTexture->setImage ( i, image );
57
+
58
+ if ( !image ) { OSG_NOTICE << " Bad splat file " << proxy->splatTextures [i] << std::endl; }
59
+ else if ( !splatW || !splatH ) { splatW = image->s (); splatH = image->t (); }
60
+ else if ( splatW!=image->s () || splatH!=image->t () ) image->scaleImage (splatW, splatH, 1 );
61
+ }
62
+
63
+ // Create alpha texture
64
+ unsigned int dataSize = proxy->alphaMaps .size () * sizeof (osg::Vec4ub);
65
+ unsigned char * data = new unsigned char [dataSize];
66
+ memcpy ( data, (unsigned char *)&(proxy->alphaMaps [0 ]), dataSize );
67
+
68
+ osg::ref_ptr<osg::Image> alphaImage = new osg::Image;
69
+ alphaImage->setImage ( proxy->alphaMapSize [0 ], proxy->alphaMapSize [1 ], 1 , GL_RGBA, GL_RGBA,
70
+ GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE );
71
+
72
+ osg::ref_ptr<osg::Texture2D> alphaTexture = new osg::Texture2D ( alphaImage.get () );
73
+ alphaTexture->setWrap ( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT );
74
+ alphaTexture->setWrap ( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT );
75
+ alphaTexture->setFilter ( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR );
76
+ alphaTexture->setFilter ( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );
77
+
78
+ // Create the terrain geometry
40
79
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
41
80
geom->setVertexArray ( va.get () );
42
- // geom->setTexCoordArray( 0, ta.get() );
81
+ geom->setTexCoordArray ( 0 , ta.get () );
43
82
geom->addPrimitiveSet ( de.get () );
44
83
84
+ osg::StateSet* ss = geom->getOrCreateStateSet ();
85
+ ss->setTextureAttribute ( 0 , splatTexture.get () ); // TODO: lightmap at unit 1?
86
+ ss->setTextureAttributeAndModes ( 2 , alphaTexture.get () );
87
+
88
+ osg::ref_ptr<osg::Program> program = new osg::Program;
89
+ program->addShader ( osgDB::readShaderFile (osg::Shader::VERTEX, dbPath + " /shaders/Terrain.vert" ) );
90
+ program->addShader ( osgDB::readShaderFile (osg::Shader::FRAGMENT, dbPath + " /shaders/Terrain.frag" ) );
91
+ ss->setAttributeAndModes ( program.get () );
92
+ ss->addUniform ( new osg::Uniform (" splatTexture" , (int )0 ) );
93
+ ss->addUniform ( new osg::Uniform (" lightTexture" , (int )1 ) );
94
+ ss->addUniform ( new osg::Uniform (" alphaTexture" , (int )2 ) );
95
+
96
+ osg::Uniform* splatTilingOffsetsUniform = ss->getOrCreateUniform (
97
+ " splatTilingOffsets" , osg::Uniform::FLOAT_VEC4, 4 );
98
+ for ( int i=0 ; i<proxy->layers ; ++i )
99
+ splatTilingOffsetsUniform->setElement ( i, proxy->splatTilingOffsets [i] );
100
+
45
101
// Add normal and tangent array for the geometry
46
102
osgUtil::SmoothingVisitor smv;
47
103
smv.smooth ( *geom );
@@ -85,7 +141,67 @@ bool TerrainData_readLocalData( osg::Object& obj, osgDB::Input& fr )
85
141
iteratorAdvanced = true ; ++fr;
86
142
}
87
143
88
- // TODO
144
+ proxy.layers = 0 ;
145
+ if ( fr.matchSequence (" AlphaMap %i %i %i {" ) )
146
+ {
147
+ int w = 0 , h = 0 ;
148
+ fr[1 ].getInt (w); fr[2 ].getInt (h); fr[3 ].getInt (proxy.layers );
149
+ proxy.alphaMapSize .set ( w, h );
150
+ proxy.alphaMaps .resize ( w * h );
151
+ proxy.splatTextures .resize ( proxy.layers );
152
+ proxy.splatTilingOffsets .resize ( proxy.layers );
153
+
154
+ int entry0 = fr[0 ].getNoNestedBrackets ();
155
+ fr += 5 ;
156
+ while ( !fr.eof () && fr[0 ].getNoNestedBrackets ()>entry0 )
157
+ {
158
+ if ( fr.matchSequence (" Layer %i {" ) )
159
+ {
160
+ int id = 0 , index = 0 ;
161
+ fr[1 ].getInt ( id );
162
+
163
+ int entry = fr[0 ].getNoNestedBrackets ();
164
+ fr += 3 ;
165
+ if ( id<4 )
166
+ {
167
+ while ( !fr.eof () && fr[0 ].getNoNestedBrackets ()>entry )
168
+ {
169
+ float v = 0 .0f ; fr[0 ].getFloat (v);
170
+ proxy.alphaMaps [index ][3 - id] = unsigned char (v * 255 .0f ); // start from v.w
171
+ ++fr; ++index ;
172
+ }
173
+ }
174
+ else
175
+ {
176
+ OSG_WARN << " We only handle terrain with equal or less than 4 layers" << std::endl;
177
+ while ( !fr.eof () && fr[0 ].getNoNestedBrackets ()>entry ) ++fr;
178
+ }
179
+ ++fr;
180
+ }
181
+ }
182
+ iteratorAdvanced = true ; ++fr;
183
+ }
184
+
185
+ for ( int i=0 ; i<proxy.layers ; ++i )
186
+ {
187
+ std::stringstream ss; ss << " Splat" << i << " %s %s" ;
188
+ if ( fr.matchSequence (ss.str ().c_str ()) )
189
+ {
190
+ std::string texName = fr[1 ].getStr (), texPath = fr[2 ].getStr ();
191
+ proxy.splatTextures [i] = texPath;
192
+ iteratorAdvanced = true ; fr += 3 ;
193
+ }
194
+
195
+ ss.str (" " ); ss << " SplatTilingOffset" << i << " %f %f %f %f" ;
196
+ if ( fr.matchSequence (ss.str ().c_str ()) )
197
+ {
198
+ osg::Vec4 tilingOffset;
199
+ for ( int n=0 ; n<4 ; ++n ) fr[1 + n].getFloat ( tilingOffset[n] );
200
+ proxy.splatTilingOffsets [i].set ( tilingOffset[0 ], tilingOffset[1 ],
201
+ tilingOffset[2 ], tilingOffset[3 ] );
202
+ iteratorAdvanced = true ; fr += 5 ;
203
+ }
204
+ }
89
205
return iteratorAdvanced;
90
206
}
91
207
0 commit comments