@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
18
18
*/
19
19
20
20
#include " tile.h"
21
+ #include " irrlichttypes_extrabloated.h"
21
22
#include " debug.h"
22
23
#include " main.h" // for g_settings
23
24
#include " filesys.h"
@@ -238,15 +239,15 @@ class SourceImageCache
238
239
return NULL ;
239
240
}
240
241
// Primarily fetches from cache, secondarily tries to read from filesystem
241
- video::IImage* getOrLoad (const std::string &name, IrrlichtDevice *device )
242
+ video::IImage* getOrLoad (const std::string &name, IrrlichtDevice *m_device )
242
243
{
243
244
std::map<std::string, video::IImage*>::iterator n;
244
245
n = m_images.find (name);
245
246
if (n != m_images.end ()){
246
247
n->second ->grab (); // Grab for caller
247
248
return n->second ;
248
249
}
249
- video::IVideoDriver* driver = device ->getVideoDriver ();
250
+ video::IVideoDriver* driver = m_device ->getVideoDriver ();
250
251
std::string path = getTexturePath (name.c_str ());
251
252
if (path == " " ){
252
253
infostream<<" SourceImageCache::getOrLoad(): No path found for \" "
@@ -378,6 +379,22 @@ class TextureSource : public IWritableTextureSource
378
379
// Shall be called from the main thread.
379
380
void rebuildImagesAndTextures ();
380
381
382
+ // Render a mesh to a texture.
383
+ // Returns NULL if render-to-texture failed.
384
+ // Shall be called from the main thread.
385
+ video::ITexture* generateTextureFromMesh (
386
+ const TextureFromMeshParams ¶ms);
387
+
388
+ // Generates an image from a full string like
389
+ // "stone.png^mineral_coal.png^[crack0".
390
+ // Shall be called from the main thread.
391
+ video::IImage* generateImageFromScratch (std::string name);
392
+
393
+ // Generate image based on a string like "stone.png" or "[crack0".
394
+ // if baseimg is NULL, it is created. Otherwise stuff is made on it.
395
+ // Shall be called from the main thread.
396
+ bool generateImage (std::string part_of_name, video::IImage *& baseimg);
397
+
381
398
private:
382
399
383
400
// The id of the thread that is allowed to use irrlicht directly
@@ -406,6 +423,11 @@ class TextureSource : public IWritableTextureSource
406
423
// Textures that have been overwritten with other ones
407
424
// but can't be deleted because the ITexture* might still be used
408
425
std::list<video::ITexture*> m_texture_trash;
426
+
427
+ // Cached settings needed for making textures from meshes
428
+ bool m_setting_trilinear_filter;
429
+ bool m_setting_bilinear_filter;
430
+ bool m_setting_anisotropic_filter;
409
431
};
410
432
411
433
IWritableTextureSource* createTextureSource (IrrlichtDevice *device)
@@ -425,6 +447,13 @@ TextureSource::TextureSource(IrrlichtDevice *device):
425
447
// Add a NULL TextureInfo as the first index, named ""
426
448
m_textureinfo_cache.push_back (TextureInfo (" " ));
427
449
m_name_to_id[" " ] = 0 ;
450
+
451
+ // Cache some settings
452
+ // Note: Since this is only done once, the game must be restarted
453
+ // for these settings to take effect
454
+ m_setting_trilinear_filter = g_settings->getBool (" trilinear_filter" );
455
+ m_setting_bilinear_filter = g_settings->getBool (" bilinear_filter" );
456
+ m_setting_anisotropic_filter = g_settings->getBool (" anisotropic_filter" );
428
457
}
429
458
430
459
TextureSource::~TextureSource ()
@@ -538,20 +567,6 @@ core::dimension2d<u32> imageTransformDimension(u32 transform, core::dimension2d<
538
567
// Apply transform to image data
539
568
void imageTransform (u32 transform, video::IImage *src, video::IImage *dst);
540
569
541
- /*
542
- Generate image based on a string like "stone.png" or "[crack0".
543
- if baseimg is NULL, it is created. Otherwise stuff is made on it.
544
- */
545
- bool generate_image (std::string part_of_name, video::IImage *& baseimg,
546
- IrrlichtDevice *device, SourceImageCache *sourcecache);
547
-
548
- /*
549
- Generates an image from a full string like
550
- "stone.png^mineral_coal.png^[crack0".
551
- */
552
- video::IImage* generate_image_from_scratch (std::string name,
553
- IrrlichtDevice *device, SourceImageCache *sourcecache);
554
-
555
570
/*
556
571
This method generates all the textures
557
572
*/
@@ -685,7 +700,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
685
700
// infostream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
686
701
687
702
// Generate image according to part of name
688
- if (!generate_image (last_part_of_name, baseimg, m_device, &m_sourcecache ))
703
+ if (!generateImage (last_part_of_name, baseimg))
689
704
{
690
705
errorstream<<" getTextureIdDirect(): "
691
706
" failed to generate \" " <<last_part_of_name<<" \" "
@@ -790,7 +805,7 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im
790
805
m_sourcecache.insert (name, img, true , m_device->getVideoDriver ());
791
806
m_source_image_existence.set (name, true );
792
807
}
793
-
808
+
794
809
void TextureSource::rebuildImagesAndTextures ()
795
810
{
796
811
JMutexAutoLock lock (m_textureinfo_cache_mutex);
@@ -800,8 +815,7 @@ void TextureSource::rebuildImagesAndTextures()
800
815
// Recreate textures
801
816
for (u32 i=0 ; i<m_textureinfo_cache.size (); i++){
802
817
TextureInfo *ti = &m_textureinfo_cache[i];
803
- video::IImage *img =
804
- generate_image_from_scratch (ti->name , m_device, &m_sourcecache);
818
+ video::IImage *img = generateImageFromScratch (ti->name );
805
819
// Create texture from resulting image
806
820
video::ITexture *t = NULL ;
807
821
if (img)
@@ -816,13 +830,90 @@ void TextureSource::rebuildImagesAndTextures()
816
830
}
817
831
}
818
832
819
- video::IImage* generate_image_from_scratch (std::string name,
820
- IrrlichtDevice *device, SourceImageCache *sourcecache )
833
+ video::ITexture* TextureSource::generateTextureFromMesh (
834
+ const TextureFromMeshParams ¶ms )
821
835
{
822
- /* infostream<<"generate_image_from_scratch(): "
836
+ video::IVideoDriver *driver = m_device->getVideoDriver ();
837
+ assert (driver);
838
+
839
+ if (driver->queryFeature (video::EVDF_RENDER_TO_TARGET) == false )
840
+ {
841
+ static bool warned = false ;
842
+ if (!warned)
843
+ {
844
+ errorstream<<" TextureSource::generateTextureFromMesh(): "
845
+ <<" EVDF_RENDER_TO_TARGET not supported." <<std::endl;
846
+ warned = true ;
847
+ }
848
+ return NULL ;
849
+ }
850
+
851
+ // Create render target texture
852
+ video::ITexture *rtt = driver->addRenderTargetTexture (
853
+ params.dim , params.rtt_texture_name .c_str (),
854
+ video::ECF_A8R8G8B8);
855
+ if (rtt == NULL )
856
+ {
857
+ errorstream<<" TextureSource::generateTextureFromMesh(): "
858
+ <<" addRenderTargetTexture returned NULL." <<std::endl;
859
+ return NULL ;
860
+ }
861
+
862
+ // Set render target
863
+ driver->setRenderTarget (rtt, false , true , video::SColor (0 ,0 ,0 ,0 ));
864
+
865
+ // Get a scene manager
866
+ scene::ISceneManager *smgr_main = m_device->getSceneManager ();
867
+ assert (smgr_main);
868
+ scene::ISceneManager *smgr = smgr_main->createNewSceneManager ();
869
+ assert (smgr);
870
+
871
+ scene::IMeshSceneNode* meshnode = smgr->addMeshSceneNode (params.mesh , NULL , -1 , v3f (0 ,0 ,0 ), v3f (0 ,0 ,0 ), v3f (1 ,1 ,1 ), true );
872
+ meshnode->setMaterialFlag (video::EMF_LIGHTING, true );
873
+ meshnode->setMaterialFlag (video::EMF_ANTI_ALIASING, true );
874
+ meshnode->setMaterialFlag (video::EMF_TRILINEAR_FILTER, m_setting_trilinear_filter);
875
+ meshnode->setMaterialFlag (video::EMF_BILINEAR_FILTER, m_setting_bilinear_filter);
876
+ meshnode->setMaterialFlag (video::EMF_ANISOTROPIC_FILTER, m_setting_anisotropic_filter);
877
+
878
+ scene::ICameraSceneNode* camera = smgr->addCameraSceneNode (0 ,
879
+ params.camera_position , params.camera_lookat );
880
+ // second parameter of setProjectionMatrix (isOrthogonal) is ignored
881
+ camera->setProjectionMatrix (params.camera_projection_matrix , false );
882
+
883
+ smgr->setAmbientLight (params.ambient_light );
884
+ smgr->addLightSceneNode (0 ,
885
+ params.light_position ,
886
+ params.light_color ,
887
+ params.light_radius );
888
+
889
+ // Render scene
890
+ driver->beginScene (true , true , video::SColor (0 ,0 ,0 ,0 ));
891
+ smgr->drawAll ();
892
+ driver->endScene ();
893
+
894
+ // NOTE: The scene nodes should not be dropped, otherwise
895
+ // smgr->drop() segfaults
896
+ /* cube->drop();
897
+ camera->drop();
898
+ light->drop();*/
899
+ // Drop scene manager
900
+ smgr->drop ();
901
+
902
+ // Unset render target
903
+ driver->setRenderTarget (0 , false , true , 0 );
904
+
905
+ if (params.delete_texture_on_shutdown )
906
+ m_texture_trash.push_back (rtt);
907
+
908
+ return rtt;
909
+ }
910
+
911
+ video::IImage* TextureSource::generateImageFromScratch (std::string name)
912
+ {
913
+ /* infostream<<"generateImageFromScratch(): "
823
914
"\""<<name<<"\""<<std::endl;*/
824
-
825
- video::IVideoDriver* driver = device ->getVideoDriver ();
915
+
916
+ video::IVideoDriver * driver = m_device ->getVideoDriver ();
826
917
assert (driver);
827
918
828
919
/*
@@ -835,12 +926,6 @@ video::IImage* generate_image_from_scratch(std::string name,
835
926
836
927
// Find last meta separator in name
837
928
s32 last_separator_position = name.find_last_of (separator);
838
- // if(last_separator_position == std::npos)
839
- // last_separator_position = -1;
840
-
841
- /* infostream<<"generate_image_from_scratch(): "
842
- <<"last_separator_position="<<last_separator_position
843
- <<std::endl;*/
844
929
845
930
/*
846
931
If separator was found, construct the base name and make the
@@ -851,11 +936,7 @@ video::IImage* generate_image_from_scratch(std::string name,
851
936
{
852
937
// Construct base name
853
938
base_image_name = name.substr (0 , last_separator_position);
854
- /* infostream<<"generate_image_from_scratch(): Calling itself recursively"
855
- " to get base image of \""<<name<<"\" = \""
856
- <<base_image_name<<"\""<<std::endl;*/
857
- baseimg = generate_image_from_scratch (base_image_name, device,
858
- sourcecache);
939
+ baseimg = generateImageFromScratch (base_image_name);
859
940
}
860
941
861
942
/*
@@ -864,12 +945,11 @@ video::IImage* generate_image_from_scratch(std::string name,
864
945
*/
865
946
866
947
std::string last_part_of_name = name.substr (last_separator_position+1 );
867
- // infostream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
868
948
869
949
// Generate image according to part of name
870
- if (!generate_image (last_part_of_name, baseimg, device, sourcecache ))
950
+ if (!generateImage (last_part_of_name, baseimg))
871
951
{
872
- errorstream<<" generate_image_from_scratch (): "
952
+ errorstream<<" generateImageFromScratch (): "
873
953
" failed to generate \" " <<last_part_of_name<<" \" "
874
954
<<std::endl;
875
955
return NULL ;
@@ -878,23 +958,22 @@ video::IImage* generate_image_from_scratch(std::string name,
878
958
return baseimg;
879
959
}
880
960
881
- bool generate_image (std::string part_of_name, video::IImage *& baseimg,
882
- IrrlichtDevice *device, SourceImageCache *sourcecache)
961
+ bool TextureSource::generateImage (std::string part_of_name, video::IImage *& baseimg)
883
962
{
884
- video::IVideoDriver* driver = device ->getVideoDriver ();
963
+ video::IVideoDriver* driver = m_device ->getVideoDriver ();
885
964
assert (driver);
886
965
887
966
// Stuff starting with [ are special commands
888
967
if (part_of_name.size () == 0 || part_of_name[0 ] != ' [' )
889
968
{
890
- video::IImage *image = sourcecache-> getOrLoad (part_of_name, device );
969
+ video::IImage *image = m_sourcecache. getOrLoad (part_of_name, m_device );
891
970
892
971
if (image == NULL )
893
972
{
894
973
if (part_of_name != " " ){
895
- errorstream<<" generate_image (): Could not load image \" "
974
+ errorstream<<" generateImage (): Could not load image \" "
896
975
<<part_of_name<<" \" " <<" while building texture" <<std::endl;
897
- errorstream<<" generate_image (): Creating a dummy"
976
+ errorstream<<" generateImage (): Creating a dummy"
898
977
<<" image for \" " <<part_of_name<<" \" " <<std::endl;
899
978
}
900
979
@@ -955,7 +1034,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
955
1034
{
956
1035
// A special texture modification
957
1036
958
- /* infostream<<"generate_image (): generating special "
1037
+ /* infostream<<"generateImage (): generating special "
959
1038
<<"modification \""<<part_of_name<<"\""
960
1039
<<std::endl;*/
961
1040
@@ -967,7 +1046,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
967
1046
{
968
1047
if (baseimg == NULL )
969
1048
{
970
- errorstream<<" generate_image (): baseimg==NULL "
1049
+ errorstream<<" generateImage (): baseimg==NULL "
971
1050
<<" for part_of_name=\" " <<part_of_name
972
1051
<<" \" , cancelling." <<std::endl;
973
1052
return false ;
@@ -996,8 +1075,8 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
996
1075
It is an image with a number of cracking stages
997
1076
horizontally tiled.
998
1077
*/
999
- video::IImage *img_crack = sourcecache-> getOrLoad (
1000
- " crack_anylength.png" , device );
1078
+ video::IImage *img_crack = m_sourcecache. getOrLoad (
1079
+ " crack_anylength.png" , m_device );
1001
1080
1002
1081
if (img_crack && progression >= 0 )
1003
1082
{
@@ -1080,7 +1159,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1080
1159
infostream<<" Adding \" " <<filename
1081
1160
<<" \" to combined (" <<x<<" ," <<y<<" )"
1082
1161
<<std::endl;
1083
- video::IImage *img = sourcecache-> getOrLoad (filename, device );
1162
+ video::IImage *img = m_sourcecache. getOrLoad (filename, m_device );
1084
1163
if (img)
1085
1164
{
1086
1165
core::dimension2d<u32> dim = img->getDimension ();
@@ -1111,7 +1190,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1111
1190
{
1112
1191
if (baseimg == NULL )
1113
1192
{
1114
- errorstream<<" generate_image (): baseimg==NULL "
1193
+ errorstream<<" generateImage (): baseimg==NULL "
1115
1194
<<" for part_of_name=\" " <<part_of_name
1116
1195
<<" \" , cancelling." <<std::endl;
1117
1196
return false ;
@@ -1130,7 +1209,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1130
1209
{
1131
1210
if (baseimg == NULL )
1132
1211
{
1133
- errorstream<<" generate_image (): baseimg==NULL "
1212
+ errorstream<<" generateImage (): baseimg==NULL "
1134
1213
<<" for part_of_name=\" " <<part_of_name
1135
1214
<<" \" , cancelling." <<std::endl;
1136
1215
return false ;
@@ -1155,7 +1234,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1155
1234
{
1156
1235
if (baseimg == NULL )
1157
1236
{
1158
- errorstream<<" generate_image (): baseimg==NULL "
1237
+ errorstream<<" generateImage (): baseimg==NULL "
1159
1238
<<" for part_of_name=\" " <<part_of_name
1160
1239
<<" \" , cancelling." <<std::endl;
1161
1240
return false ;
@@ -1212,7 +1291,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1212
1291
{
1213
1292
if (baseimg == NULL )
1214
1293
{
1215
- errorstream<<" generate_image (): baseimg==NULL "
1294
+ errorstream<<" generateImage (): baseimg==NULL "
1216
1295
<<" for part_of_name=\" " <<part_of_name
1217
1296
<<" \" , cancelling." <<std::endl;
1218
1297
return false ;
@@ -1240,7 +1319,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1240
1319
{
1241
1320
if (baseimg != NULL )
1242
1321
{
1243
- errorstream<<" generate_image (): baseimg!=NULL "
1322
+ errorstream<<" generateImage (): baseimg!=NULL "
1244
1323
<<" for part_of_name=\" " <<part_of_name
1245
1324
<<" \" , cancelling." <<std::endl;
1246
1325
return false ;
@@ -1254,12 +1333,12 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1254
1333
std::string imagename_right = sf.next (" {" );
1255
1334
1256
1335
// Generate images for the faces of the cube
1257
- video::IImage *img_top = generate_image_from_scratch (
1258
- imagename_top, device, sourcecache );
1259
- video::IImage *img_left = generate_image_from_scratch (
1260
- imagename_left, device, sourcecache );
1261
- video::IImage *img_right = generate_image_from_scratch (
1262
- imagename_right, device, sourcecache );
1336
+ video::IImage *img_top =
1337
+ generateImageFromScratch ( imagename_top);
1338
+ video::IImage *img_left =
1339
+ generateImageFromScratch ( imagename_left);
1340
+ video::IImage *img_right =
1341
+ generateImageFromScratch ( imagename_right);
1263
1342
assert (img_top && img_left && img_right);
1264
1343
1265
1344
// Create textures from images
@@ -1288,31 +1367,25 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1288
1367
cube->getMeshBuffer (4 )->getMaterial ().setTexture (0 , texture_left);
1289
1368
cube->getMeshBuffer (5 )->getMaterial ().setTexture (0 , texture_left);
1290
1369
1291
- core::dimension2d<u32> dim (64 ,64 );
1292
- std::string rtt_texture_name = part_of_name + " _RTT" ;
1293
-
1294
- v3f camera_position (0 , 1.0 , -1.5 );
1295
- camera_position.rotateXZBy (45 );
1296
- v3f camera_lookat (0 , 0 , 0 );
1297
- core::CMatrix4<f32> camera_projection_matrix;
1370
+ TextureFromMeshParams params;
1371
+ params.mesh = cube;
1372
+ params.dim .set (64 , 64 );
1373
+ params.rtt_texture_name = part_of_name + " _RTT" ;
1374
+ // We will delete the rtt texture ourselves
1375
+ params.delete_texture_on_shutdown = false ;
1376
+ params.camera_position .set (0 , 1.0 , -1.5 );
1377
+ params.camera_position .rotateXZBy (45 );
1378
+ params.camera_lookat .set (0 , 0 , 0 );
1298
1379
// Set orthogonal projection
1299
- camera_projection_matrix.buildProjectionMatrixOrthoLH (
1380
+ params. camera_projection_matrix .buildProjectionMatrixOrthoLH (
1300
1381
1.65 , 1.65 , 0 , 100 );
1301
1382
1302
- video::SColorf ambient_light (0.2 ,0.2 ,0.2 );
1303
- v3f light_position (10 , 100 , -50 );
1304
- video::SColorf light_color (0.5 ,0.5 ,0.5 );
1305
- f32 light_radius = 1000 ;
1306
-
1307
- video::ITexture *rtt = generateTextureFromMesh (
1308
- cube, device, dim, rtt_texture_name,
1309
- camera_position,
1310
- camera_lookat,
1311
- camera_projection_matrix,
1312
- ambient_light,
1313
- light_position,
1314
- light_color,
1315
- light_radius);
1383
+ params.ambient_light .set (1.0 , 0.2 , 0.2 , 0.2 );
1384
+ params.light_position .set (10 , 100 , -50 );
1385
+ params.light_color .set (1.0 , 0.5 , 0.5 , 0.5 );
1386
+ params.light_radius = 1000 ;
1387
+
1388
+ video::ITexture *rtt = generateTextureFromMesh (params);
1316
1389
1317
1390
// Drop mesh
1318
1391
cube->drop ();
@@ -1324,19 +1397,18 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1324
1397
1325
1398
if (rtt == NULL )
1326
1399
{
1327
- baseimg = generate_image_from_scratch (
1328
- imagename_top, device, sourcecache);
1400
+ baseimg = generateImageFromScratch (imagename_top);
1329
1401
return true ;
1330
1402
}
1331
1403
1332
1404
// Create image of render target
1333
- video::IImage *image = driver->createImage (rtt, v2s32 (0 ,0 ), dim);
1405
+ video::IImage *image = driver->createImage (rtt, v2s32 (0 ,0 ), params. dim );
1334
1406
assert (image);
1335
1407
1336
- // cleanup texture
1408
+ // Cleanup texture
1337
1409
driver->removeTexture (rtt);
1338
1410
1339
- baseimg = driver->createImage (video::ECF_A8R8G8B8, dim);
1411
+ baseimg = driver->createImage (video::ECF_A8R8G8B8, params. dim );
1340
1412
1341
1413
if (image)
1342
1414
{
@@ -1358,7 +1430,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1358
1430
1359
1431
if (baseimg == NULL )
1360
1432
baseimg = driver->createImage (video::ECF_A8R8G8B8, v2u32 (16 ,16 ));
1361
- video::IImage *img = sourcecache-> getOrLoad (filename, device );
1433
+ video::IImage *img = m_sourcecache. getOrLoad (filename, m_device );
1362
1434
if (img)
1363
1435
{
1364
1436
core::dimension2d<u32> dim = img->getDimension ();
@@ -1392,7 +1464,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1392
1464
u32 frame_index = stoi (sf.next (" :" ));
1393
1465
1394
1466
if (baseimg == NULL ){
1395
- errorstream<<" generate_image (): baseimg!=NULL "
1467
+ errorstream<<" generateImage (): baseimg!=NULL "
1396
1468
<<" for part_of_name=\" " <<part_of_name
1397
1469
<<" \" , cancelling." <<std::endl;
1398
1470
return false ;
@@ -1404,7 +1476,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1404
1476
video::IImage *img = driver->createImage (video::ECF_A8R8G8B8,
1405
1477
frame_size);
1406
1478
if (!img){
1407
- errorstream<<" generate_image (): Could not create image "
1479
+ errorstream<<" generateImage (): Could not create image "
1408
1480
<<" for part_of_name=\" " <<part_of_name
1409
1481
<<" \" , cancelling." <<std::endl;
1410
1482
return false ;
@@ -1426,7 +1498,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
1426
1498
}
1427
1499
else
1428
1500
{
1429
- errorstream<<" generate_image (): Invalid "
1501
+ errorstream<<" generateImage (): Invalid "
1430
1502
" modification: \" " <<part_of_name<<" \" " <<std::endl;
1431
1503
}
1432
1504
}
0 commit comments