Skyscraper 2.0
texture.cpp
Go to the documentation of this file.
1/*
2 Scalable Building Simulator - Texture Manager
3 The Skyscraper Project - Version 2.0
4 Copyright (C)2004-2024 Ryan Thoryk
5 https://www.skyscrapersim.net
6 https://sourceforge.net/projects/skyscraper/
7 Contact - ryan@skyscrapersim.net
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22*/
23
24#include <OgreRoot.h>
25#include <OgreImage.h>
26#include <OgreTextureManager.h>
27#include <OgreTechnique.h>
28#include <OgreMaterialManager.h>
29#include <OgreFont.h>
30#include <OgreFontManager.h>
31#include <OgreHardwarePixelBuffer.h>
32#include <OgreResourceGroupManager.h>
33#include <OgreRTShaderSystem.h>
34#include "globals.h"
35#include "sbs.h"
36#include "utility.h"
37#include "texture.h"
38
39namespace SBS {
40
42{
43 SetName("Texture Manager");
44
45 AutoX = true;
46 AutoY = true;
47 MapIndex.resize(3);
48 MapUV.resize(3);
49 OldMapIndex.resize(3);
50 OldMapUV.resize(3);
51 MapVerts1.resize(3);
52 MapVerts2.resize(3);
53 MapVerts3.resize(3);
54 OldMapVerts1.resize(3);
55 OldMapVerts2.resize(3);
56 OldMapVerts3.resize(3);
57 MapMethod = 0;
58 OldMapMethod = 0;
59 RevX = false;
60 RevY = false;
61 RevZ = false;
62 OldRevX = false;
63 OldRevY = false;
64 OldRevZ = false;
65 PlanarFlat = false;
66 OldPlanarFlat = false;
67 PlanarRotate = false;
68 OldPlanarRotate = false;
69 for (int i = 0; i <= 2; i++)
70 {
71 MapIndex[i] = 0;
72 OldMapIndex[i] = 0;
73 OldMapUV[i] = Vector2::ZERO;
74 MapUV[i] = Vector2::ZERO;
75 }
76 DefaultMapper = sbs->GetConfigInt("Skyscraper.SBS.TextureMapper", 0);
77 texturecount = 0;
78 materialcount = 0;
79 TextureOverride = false;
80 FlipTexture = false;
81 mainnegflip = 0;
82 mainposflip = 0;
83 sidenegflip = 0;
84 sideposflip = 0;
85 topflip = 0;
86 bottomflip = 0;
87 widthscale.resize(6);
88 heightscale.resize(6);
89
90 //set default texture map values
92
93 //load default textures
94 Report("Loading default textures...");
96 LoadTexture("data/default.png", "Default", 1, 1);
97 LoadTexture("data/gray2-sm.jpg", "ConnectionWall", 1, 1);
98 LoadTexture("data/metal1-sm.jpg", "Connection", 1, 1);
100 Report("Done");
101}
102
104{
105 //delete materials
107 textureinfo.clear();
108
109 if (textureboxes.empty() == false)
111
112 //remove manually-created textures
113 for (size_t i = 0; i < manual_textures.size(); i++)
114 {
115 if (manual_textures[i])
116 {
117 Ogre::TextureManager::getSingleton().remove(manual_textures[i]->getHandle());
118 }
119 }
120 manual_textures.clear();
121}
122
123bool TextureManager::LoadTexture(const std::string &filename, const std::string &name, Real widthmult, Real heightmult, bool enable_force, bool force_mode, int mipmaps, bool use_alpha_color, Ogre::ColourValue alpha_color)
124{
125 //first verify the filename
126 std::string filename2 = sbs->VerifyFile(filename);
127
128 //load texture
129 bool has_alpha = false;
130 Ogre::TexturePtr mTex = LoadTexture(filename2, mipmaps, has_alpha, use_alpha_color, alpha_color);
131
132 if (!mTex)
133 return false;
134 std::string texturename = mTex->getName();
135
136 //create a new material
137 std::string matname = TrimStringCopy(name);
138 Ogre::MaterialPtr mMat = CreateMaterial(matname, "General");
139
140 if (mMat == 0)
141 return false;
142
143 //bind texture to material
144 BindTextureToMaterial(mMat, texturename, has_alpha);
145
146 //add texture multipliers
147 RegisterTextureInfo(name, "", filename, widthmult, heightmult, enable_force, force_mode, mTex->getSize(), mMat->getSize());
148
149 if (sbs->Verbose)
150 Report("Loaded texture '" + filename2 + "' as '" + matname + "', size " + ToString((int)mTex->getSize()));
151 else
152 Report("Loaded texture '" + filename2 + "' as '" + matname + "'");
153
154 return true;
155}
156
157bool TextureManager::LoadAnimatedTexture(std::vector<std::string> filenames, const std::string &name, Real duration, Real widthmult, Real heightmult, bool enable_force, bool force_mode, int mipmaps, bool use_alpha_color, Ogre::ColourValue alpha_color)
158{
159 std::vector<std::string> filenames2;
160
161 size_t num_frames = filenames.size();
162
163 //first verify the filenames
164 for (size_t i = 0; i < filenames.size(); i++)
165 {
166 TrimString(filenames[i]);
167 filenames2.emplace_back(sbs->VerifyFile(filenames[i]));
168 }
169
170 bool has_alpha = false;
171
172 size_t size = 0;
173 for (size_t i = 0; i < filenames2.size(); i++)
174 {
175 bool has_alpha2 = false;
176
177 //load texture
178 Ogre::TexturePtr mTex = LoadTexture(filenames2[i], mipmaps, has_alpha2, use_alpha_color, alpha_color);
179
180 if (!mTex)
181 return false;
182 std::string texturename = mTex->getName();
183
184 if (has_alpha2 == true)
185 has_alpha = true;
186
187 size += mTex->getSize();
188
189 if (sbs->Verbose)
190 Report("Loaded texture " + filenames2[i] + ", size " + ToString((int)mTex->getSize()));
191 }
192
193 //create a new material
194 std::string matname = TrimStringCopy(name);
195 Ogre::MaterialPtr mMat = CreateMaterial(matname, "General");
196
197 //bind first texture to material
198 Ogre::TextureUnitState* state = BindTextureToMaterial(mMat, filenames2[0], has_alpha);
199
200 //apply animation texture list
201 if (state)
202 {
203 std::string *namelist = new std::string[num_frames];
204 for (size_t i = 0; i < num_frames; i++)
205 namelist[i] = filenames2[i];
206 state->setAnimatedTextureName(namelist, num_frames, duration);
207 delete [] namelist;
208 }
209 else
210 return false;
211
212 //add texture multipliers
213 RegisterTextureInfo(name, "", "", widthmult, heightmult, enable_force, force_mode, size, mMat->getSize());
214
215 if (sbs->Verbose)
216 Report("Loaded animated texture " + matname);
217
218 return true;
219}
220
221bool TextureManager::LoadAlphaBlendTexture(const std::string &filename, const std::string &specular_filename, const std::string &blend_filename, const std::string &name, bool spherical, Real widthmult, Real heightmult, bool enable_force, bool force_mode, int mipmaps, bool use_alpha_color, Ogre::ColourValue alpha_color)
222{
223 //first verify the filenames
224 std::string filename2 = sbs->VerifyFile(filename);
225 std::string specular_filename2 = sbs->VerifyFile(specular_filename);
226 std::string blend_filename2 = sbs->VerifyFile(blend_filename);
227
228 //load texture
229 bool has_alpha = false, has_alpha2 = false;
230 Ogre::TexturePtr mTex = LoadTexture(filename2, mipmaps, has_alpha, use_alpha_color, alpha_color);
231
232 if (!mTex)
233 return false;
234 std::string texturename = mTex->getName();
235
236 //load specular texture
237 mTex = LoadTexture(specular_filename2, mipmaps, has_alpha2, use_alpha_color, alpha_color);
238
239 if (!mTex)
240 return ReportError("Error loading texture" + specular_filename2);
241 std::string specular_texturename = mTex->getName();
242
243 //load blend texture
244 mTex = LoadTexture(blend_filename2, mipmaps, has_alpha2, use_alpha_color, alpha_color);
245
246 if (!mTex)
247 return ReportError("Error loading texture" + blend_filename2);
248 std::string blend_texturename = mTex->getName();
249
250 //create a new material
251 std::string matname = TrimStringCopy(name);
252 Ogre::MaterialPtr mMat = CreateMaterial(matname, "General");
253
254 //bind texture to material
255 BindTextureToMaterial(mMat, texturename, has_alpha);
256 Ogre::TextureUnitState* spec_state = BindTextureToMaterial(mMat, specular_texturename, false);
257 Ogre::TextureUnitState* blend_state = BindTextureToMaterial(mMat, blend_texturename, false);
258
259 if (spec_state)
260 spec_state->setColourOperation(Ogre::LBO_ALPHA_BLEND);
261
262 if (blend_state)
263 {
264 blend_state->setColourOperationEx(Ogre::LBX_BLEND_CURRENT_ALPHA);
265 if (spherical == true)
266 blend_state->setEnvironmentMap(true, Ogre::TextureUnitState::ENV_CURVED);
267 else
268 blend_state->setEnvironmentMap(true, Ogre::TextureUnitState::ENV_PLANAR);
269 }
270
271 //add texture multipliers
272 RegisterTextureInfo(name, "", filename, widthmult, heightmult, enable_force, force_mode, mTex->getSize(), mMat->getSize());
273
274 if (sbs->Verbose)
275 Report("Loaded alpha blended texture '" + filename2 + "' as '" + matname + "'");
276
277 return true;
278}
279
280bool TextureManager::LoadMaterial(const std::string &materialname, const std::string &name, Real widthmult, Real heightmult, bool enable_force, bool force_mode)
281{
282 //set verbosity level
283 Ogre::MaterialPtr mMat;
284 std::string matname = materialname;
285
286 mMat = GetMaterialByName(matname, "Materials");
287
288 if (!mMat)
289 return false;
290
291 //show only clockwise side of material
292 mMat->setCullingMode(Ogre::CULL_ANTICLOCKWISE);
293
294 //add texture multipliers
295 RegisterTextureInfo(name, materialname, "", widthmult, heightmult, enable_force, force_mode, 0, mMat->getSize());
296
297 if (sbs->Verbose)
298 Report("Loaded material " + matname);
299
300 return true;
301}
302
303void TextureManager::RegisterTextureInfo(const std::string &name, const std::string &material_name, const std::string &filename, Real widthmult, Real heightmult, bool enable_force, bool force_mode, size_t tex_size, size_t mat_size)
304{
305 //register texture for multipliers information
306 //see TextureInfo structure for more information
307
308 if (widthmult == 0.0)
309 widthmult = 1.0;
310 if (heightmult == 0.0)
311 heightmult = 1.0;
312
313 TextureInfo info;
314 info.name = TrimStringCopy(name);
315 info.material_name = TrimStringCopy(material_name);
316 info.filename = TrimStringCopy(filename);
317 info.widthmult = widthmult;
318 info.heightmult = heightmult;
319 info.enable_force = enable_force;
320 info.force_mode = force_mode;
321 info.dependencies = 0;
322 info.tex_size = tex_size;
323 info.mat_size = mat_size;
324
325 textureinfo.emplace_back(info);
326}
327
328bool TextureManager::UnregisterTextureInfo(std::string name, std::string material_name)
329{
330 TrimString(name);
331 TrimString(material_name);
332
333 for (size_t i = 0; i < textureinfo.size(); i++)
334 {
335 if (textureinfo[i].name == name || (textureinfo[i].material_name == material_name && textureinfo[i].material_name != ""))
336 {
337 textureinfo.erase(textureinfo.begin() + i);
338 return true;
339 }
340 }
341 return false;
342}
343
344bool TextureManager::UnloadTexture(const std::string &name, const std::string &group)
345{
346 //unloads a texture
347
348 Ogre::ResourcePtr wrapper = GetTextureByName(name, group);
349 if (!wrapper)
350 return false;
351 Ogre::TextureManager::getSingleton().remove(wrapper);
353
354 Report("Unloaded texture " + name);
355
356 return true;
357}
358
359bool TextureManager::UnloadMaterial(const std::string &name, const std::string &group)
360{
361 //unloads a material
362
363 Ogre::ResourcePtr wrapper = GetMaterialByName(name, group);
364 if (!wrapper)
365 return false;
366 Ogre::MaterialManager::getSingleton().remove(wrapper);
368
369 Report("Unloaded material " + name);
370
371 return true;
372}
373
374bool TextureManager::LoadTextureCropped(const std::string &filename, const std::string &name, int x, int y, int width, int height, Real widthmult, Real heightmult, bool enable_force, bool force_mode)
375{
376 //loads only a portion of the specified texture
377
378 Ogre::ColourValue alpha_color = Ogre::ColourValue::Black;
379 int mipmaps = -1;
380 bool use_alpha_color = false;
381
382 //first verify the filename
383 std::string filename2 = sbs->VerifyFile(filename);
384
385 //load texture
386 bool has_alpha = false;
387 Ogre::TexturePtr mTex = LoadTexture(filename2, mipmaps, has_alpha, use_alpha_color, alpha_color);
388
389 if (!mTex)
390 return false;
391
392 //set default values if specified
393 if (x == -1)
394 x = 0;
395 if (y == -1)
396 y = 0;
397 if (width < 1)
398 width = (int)mTex->getWidth();
399 if (height < 1)
400 height = (int)mTex->getHeight();
401
402 if (x > (int)mTex->getWidth() || y > (int)mTex->getHeight())
403 return ReportError("LoadTextureCropped: invalid coordinates for '" + name + "'");
404 if (x + width > (int)mTex->getWidth() || y + height > (int)mTex->getHeight())
405 return ReportError("LoadTextureCropped: invalid size for '" + name + "'");
406
407 //determine pixel format
408 Ogre::PixelFormat format = Ogre::PF_X8R8G8B8;
409 if (has_alpha == true)
410 format = Ogre::PF_A8R8G8B8;
411
412 //create new empty texture
413 std::string texturename = ToString(sbs->InstanceNumber) + ":" + name;
414 Ogre::TexturePtr new_texture;
415 try
416 {
417 new_texture = Ogre::TextureManager::getSingleton().createManual(texturename, "General", Ogre::TEX_TYPE_2D, width, height, Ogre::MIP_UNLIMITED, format, Ogre::TU_DEFAULT);
418 manual_textures.emplace_back(new_texture);
420 }
421 catch (Ogre::Exception &e)
422 {
423 ReportError("Error creating new texture " + texturename + "\n" + e.getDescription());
424 return false;
425 }
426
427 //copy source and overlay images onto new image
428 Ogre::Box source (x, y, x + width, y + height);
429 Ogre::Box dest (0, 0, width, height);
430 CopyTexture(mTex, new_texture, source, dest);
431
432 //create a new material
433 Ogre::MaterialPtr mMat = CreateMaterial(name, "General");
434
435 //bind texture to material
436 BindTextureToMaterial(mMat, texturename, has_alpha);
437
438 if (sbs->Verbose)
439 Report("Loaded cropped texture '" + filename2 + "' as '" + name + "', size " + ToString((int)new_texture->getSize()));
440
441 //add texture multipliers
442 RegisterTextureInfo(name, "", filename, widthmult, heightmult, enable_force, force_mode, mTex->getSize(), mMat->getSize());
443
444 return true;
445}
446
447bool TextureManager::RotateTexture(const std::string &name, Real angle)
448{
449 //set a fixed rotation value for a texture
450
451 bool result;
452 std::string texname = TrimStringCopy(name);
453 std::string material = GetTextureMaterial(name, result, false);
454
455 if (!result)
456 return ReportError("RotateTexture: invalid texture " + texname + "\n");
457
458 //get material name
459 Ogre::MaterialPtr mMat = GetMaterialByName(material);
460
461 if (!mMat)
462 return false;
463
464 //get texture unit state
465 Ogre::TextureUnitState* state = GetTextureUnitState(mMat);
466
467 //set rotation
468 if (state)
469 state->setTextureRotate(Degree(-angle));
470 else
471 return false;
472
473 return true;
474}
475
476bool TextureManager::RotateAnimTexture(const std::string &name, Real speed)
477{
478 //set a rotation animation for a texture - speed is in revolutions per second
479
480 bool result;
481 std::string texname = TrimStringCopy(name);
482 std::string material = GetTextureMaterial(name, result, false);
483
484 if (!result)
485 return ReportError("RotateAnimTexture: invalid texture " + texname + "\n");
486
487 //get material name
488 Ogre::MaterialPtr mMat = GetMaterialByName(material);
489
490 if (!mMat)
491 return false;
492
493 //get texture unit state
494 Ogre::TextureUnitState* state = GetTextureUnitState(mMat);
495
496 //set rotation animation
497 if (state)
498 state->setRotateAnimation(speed);
499 else
500 return false;
501
502 return true;
503}
504
505bool TextureManager::ScrollTexture(const std::string &name, Real x_offset, Real y_offset)
506{
507 //set a fixed scroll amount for a texture
508
509 bool result;
510 std::string texname = TrimStringCopy(name);
511 std::string material = GetTextureMaterial(name, result, false);
512
513 if (!result)
514 return ReportError("ScrollTexture: invalid texture " + texname + "\n");
515
516 //get material name
517 Ogre::MaterialPtr mMat = GetMaterialByName(material);
518
519 if (!mMat)
520 return false;
521
522 //get texture unit state
523 Ogre::TextureUnitState* state = GetTextureUnitState(mMat);
524
525 //set scrolling value
526 if (state)
527 state->setTextureScroll(-x_offset, y_offset); //invert x value
528 else
529 return false;
530
531 return true;
532}
533
534bool TextureManager::ScrollAnimTexture(const std::string &name, Real x_speed, Real y_speed)
535{
536 //set a scroll animation for a texture - speed is in revolutions per second
537
538 bool result;
539 std::string texname = TrimStringCopy(name);
540 std::string material = GetTextureMaterial(name, result, false);
541
542 if (!result)
543 return ReportError("ScrollAnimTexture: invalid texture " + texname + "\n");
544
545 //get material name
546 Ogre::MaterialPtr mMat = GetMaterialByName(material);
547
548 if (!mMat)
549 return false;
550
551 //get texture unit state
552 Ogre::TextureUnitState* state = GetTextureUnitState(mMat);
553
554 //set scrolling animation
555 if (state)
556 state->setScrollAnimation(x_speed, -y_speed);
557 else
558 return false;
559
560 return true;
561}
562
563bool TextureManager::ScaleTexture(const std::string &name, Real x_scale, Real y_scale)
564{
565 //set a fixed scale amount for a texture
566
567 bool result;
568 std::string texname = TrimStringCopy(name);
569 std::string material = GetTextureMaterial(name, result, false);
570
571 if (!result)
572 return ReportError("ScaleTexture: invalid texture " + texname + "\n");
573
574 //get material name
575 Ogre::MaterialPtr mMat = GetMaterialByName(material);
576
577 if (!mMat)
578 return false;
579
580 //get texture unit state
581 Ogre::TextureUnitState* state = GetTextureUnitState(mMat);
582
583 //set scale
584 if (state)
585 state->setTextureScale(x_scale, y_scale);
586 else
587 return false;
588
589 return true;
590}
591
592bool TextureManager::TransformTexture(const std::string &name, const std::string &type, const std::string &wave_type, Real base, Real frequency, Real phase, Real amplitude)
593{
594 //set a transformation type for a texture
595
596 bool result;
597 std::string texname = TrimStringCopy(name);
598 std::string material = GetTextureMaterial(name, result, false);
599
600 std::string xform_type = TrimStringCopy(type);
601 SetCase(xform_type, false);
602 std::string wave = TrimStringCopy(wave_type);
603 SetCase(wave, false);
604
605 if (!result)
606 return ReportError("TransformTexture: invalid texture " + texname + "\n");
607
608 //get material name
609 Ogre::MaterialPtr mMat = GetMaterialByName(material);
610
611 if (!mMat)
612 return false;
613
614 //get texture unit state
615 Ogre::TextureUnitState* state = GetTextureUnitState(mMat);
616
617 //set transform
618 if (state)
619 {
620 Ogre::TextureUnitState::TextureTransformType type;
621 if (xform_type == "scroll_x")
622 type = Ogre::TextureUnitState::TT_TRANSLATE_U;
623 else if (xform_type == "scroll_y")
624 type = Ogre::TextureUnitState::TT_TRANSLATE_V;
625 else if (xform_type == "rotate")
626 type = Ogre::TextureUnitState::TT_ROTATE;
627 else if (xform_type == "scale_x")
628 type = Ogre::TextureUnitState::TT_SCALE_U;
629 else if (xform_type == "scale_y")
630 type = Ogre::TextureUnitState::TT_SCALE_V;
631 else
632 return false;
633
634 Ogre::WaveformType wavetype;
635 if (wave == "sine")
636 wavetype = Ogre::WFT_SINE;
637 else if (wave == "triangle")
638 wavetype = Ogre::WFT_TRIANGLE;
639 else if (wave == "square")
640 wavetype = Ogre::WFT_SQUARE;
641 else if (wave == "sawtooth")
642 wavetype = Ogre::WFT_SAWTOOTH;
643 else if (wave == "inverse_sawtooth")
644 wavetype = Ogre::WFT_INVERSE_SAWTOOTH;
645 else if (wave == "pwm")
646 wavetype = Ogre::WFT_PWM;
647 else
648 return false;
649
650 state->setTransformAnimation(type, wavetype, base, frequency, phase, amplitude);
651 }
652 else
653 return false;
654
655 return true;
656}
657
658bool TextureManager::AddTextToTexture(const std::string &origname, const std::string &name, const std::string &font_filename, Real font_size, const std::string &text, int x1, int y1, int x2, int y2, const std::string &h_align, const std::string &v_align, int ColorR, int ColorG, int ColorB, bool enable_force, bool force_mode)
659{
660 //adds text to the named texture, in the given box coordinates and alignment
661
662 //h_align is either "left", "right" or "center" - default is center
663 //v_align is either "top", "bottom", or "center" - default is center
664
665 //if either x1 or y1 are -1, the value of 0 is used.
666 //If either x2 or y2 are -1, the width or height of the texture is used.
667
668 std::string hAlign = h_align;
669 std::string vAlign = v_align;
670 std::string Name = TrimStringCopy(name);
671 std::string Origname = TrimStringCopy(origname);
672 std::string Text = TrimStringCopy(text);
673
674 std::string font_filename2 = sbs->VerifyFile(font_filename);
675
676 //load font
677 Ogre::FontPtr font;
678 std::string fontname = font_filename2 + ToString(font_size);
679 font = Ogre::FontManager::getSingleton().getByName(fontname, "General");
680
681 //load if font is not already loaded
682 if (!font)
683 {
684 try
685 {
686 font = Ogre::FontManager::getSingleton().create(fontname, "General");
687 //font->setType(Ogre::FontType::FT_TRUETYPE);
688 font->setSource(font_filename2);
689 font->setTrueTypeSize(font_size);
690 font->setTrueTypeResolution(96);
691 //font->setAntialiasColour(true);
692 font->addCodePointRange(Ogre::Font::CodePointRange(32, 126));
693 font->load();
694
695 //report font loaded and texture size
696 std::string texname = GetTextureName(font->getMaterial());
697 Ogre::TexturePtr fontTexture = GetTextureByName(texname);
698 if (fontTexture)
699 Report("Font " + font_filename2 + " loaded as size " + ToString(font_size) + ", with texture size " + ToString((int)fontTexture->getSize()));
700 }
701 catch (Ogre::Exception &e)
702 {
703 if (font)
704 {
705 //unload texture and font, if an error occurred
706 if (Ogre::TextureManager::getSingleton().getByName(fontname + "Texture"))
707 return ReportError("Error loading font " + fontname + "\n" + e.getDescription());
708
709 if (Ogre::FontManager::getSingleton().getByHandle(font->getHandle()))
710 return ReportError("Error loading font " + fontname + "\n" + e.getDescription());
711
712 Ogre::TextureManager::getSingleton().remove(fontname + "Texture");
713 Ogre::FontManager::getSingleton().remove(font->getHandle());
714 }
715 return ReportError("Error loading font " + fontname + "\n" + e.getDescription());
716 }
717 }
718
719 //get original texture
720 Ogre::MaterialPtr ptr = GetMaterialByName(Origname);
721 if (!ptr)
722 return ReportError("AddTextToTexture: Invalid original material '" + Origname + "'");
723
724 std::string texname = GetTextureName(ptr);
725 Ogre::TexturePtr background = GetTextureByName(texname);
726 if (!background)
727 return ReportError("AddTextToTexture: Invalid original texture '" + texname + "'");
728
729 bool has_alpha = background->hasAlpha();
730
731 //get texture tiling info
732 Real widthmult, heightmult;
733 GetTextureTiling(origname, widthmult, heightmult);
734
735 //get height and width of texture
736 int width = (int)background->getWidth();
737 int height = (int)background->getHeight();
738
739 //determine pixel format
740 Ogre::PixelFormat format = Ogre::PF_X8R8G8B8;
741 if (has_alpha == true)
742 format = Ogre::PF_A8R8G8B8;
743
744 //create new empty texture
745 std::string texturename = ToString(sbs->InstanceNumber) + ":" + Name;
746 Ogre::TexturePtr texture;
747 try
748 {
749 texture = Ogre::TextureManager::getSingleton().createManual(texturename, "General", Ogre::TEX_TYPE_2D, width, height, Ogre::MIP_UNLIMITED, format, Ogre::TU_STATIC|Ogre::TU_AUTOMIPMAP);
750 manual_textures.emplace_back(texture);
752 }
753 catch (Ogre::Exception &e)
754 {
755 ReportError("Error creating new texture " + texturename + "\n" + e.getDescription());
756 return false;
757 }
758
759 //get new texture dimensions, if it was resized
760 width = (int)texture->getWidth();
761 height = (int)texture->getHeight();
762
763 //set default values if specified
764 if (x1 == -1)
765 x1 = 0;
766 if (y1 == -1)
767 y1 = 0;
768 if (x2 == -1)
769 x2 = width - 1;
770 if (y2 == -1)
771 y2 = height - 1;
772
773 //draw original image onto new texture
774 CopyTexture(background, texture);
775
776 TrimString(hAlign);
777 TrimString(vAlign);
778 char align = 'c';
779 if (hAlign == "left")
780 align = 'l';
781 if (hAlign == "right")
782 align = 'r';
783 char valign = 'c';
784 if (vAlign == "top")
785 valign = 't';
786 if (vAlign == "bottom")
787 valign = 'b';
788
789 //write text
790 Real red = (Real)ColorR / 255;
791 Real green = (Real)ColorG / 255;
792 Real blue = (Real)ColorB / 255;
793
794 bool result = WriteToTexture(Text, texture, x1, y1, x2, y2, font, Ogre::ColourValue((float)red, (float)green, (float)blue, 1.0), align, valign);
795 if (result == false)
796 return false;
797
798 //create a new material
799 Ogre::MaterialPtr mMat = CreateMaterial(Name, "General");
800
801 //bind texture to material
802 BindTextureToMaterial(mMat, texturename, has_alpha);
803
804 //add texture multipliers
805 RegisterTextureInfo(name, "", "", widthmult, heightmult, enable_force, force_mode, texture->getSize(), mMat->getSize());
806
807 if (sbs->Verbose)
808 Report("AddTextToTexture: created texture '" + Name + "'");
809
811 return true;
812}
813
814bool TextureManager::AddTextureOverlay(const std::string &orig_texture, const std::string &overlay_texture, const std::string &name, int x, int y, int width, int height, Real widthmult, Real heightmult, bool enable_force, bool force_mode)
815{
816 //draws the specified texture on top of another texture
817 //orig_texture is the original texture to use; overlay_texture is the texture to draw on top of it
818
819 std::string Name = name;
820 std::string Origname = orig_texture;
821 std::string Overlay = overlay_texture;
822
823 //get original texture
824 Ogre::MaterialPtr ptr = GetMaterialByName(Origname);
825
826 if (!ptr)
827 return ReportError("AddTextureOverlay: Invalid original material '" + Origname + "'");
828
829 std::string texname = GetTextureName(ptr);
830 Ogre::TexturePtr image1 = GetTextureByName(texname);
831
832 if (!image1)
833 return ReportError("AddTextureOverlay: Invalid original texture '" + texname + "'");
834
835 bool has_alpha = image1->hasAlpha();
836
837 //get overlay texture
838 ptr = GetMaterialByName(Overlay);
839
840 if (!ptr)
841 return ReportError("AddTextureOverlay: Invalid overlay material '" + Overlay + "'");
842
843 texname = GetTextureName(ptr);
844 Ogre::TexturePtr image2 = GetTextureByName(texname);
845
846 if (!image2)
847 return ReportError("AddTextureOverlay: Invalid overlay texture '" + texname + "'");
848
849 //set default values if specified
850 if (x == -1)
851 x = 0;
852 if (y == -1)
853 y = 0;
854 if (width < 1)
855 width = (int)image2->getWidth();
856 if (height < 1)
857 height = (int)image2->getHeight();
858
859 if (x > (int)image1->getWidth() || y > (int)image1->getHeight())
860 return ReportError("AddTextureOverlay: invalid coordinates for '" + Name + "'");
861 if (x + width > (int)image1->getWidth() || y + height > (int)image1->getHeight())
862 return ReportError("AddTextureOverlay: invalid size for '" + Name + "'");
863
864 //determine pixel format
865 Ogre::PixelFormat format = Ogre::PF_X8R8G8B8;
866 if (has_alpha == true)
867 format = Ogre::PF_A8R8G8B8;
868
869 //create new empty texture
870 std::string texturename = ToString(sbs->InstanceNumber) + ":" + Name;
871 Ogre::TexturePtr new_texture;
872 try
873 {
874 new_texture = Ogre::TextureManager::getSingleton().createManual(texturename, "General", Ogre::TEX_TYPE_2D, (Ogre::uint)image1->getWidth(), (Ogre::uint)image1->getHeight(), Ogre::MIP_UNLIMITED, format, Ogre::TU_DEFAULT);
875 manual_textures.emplace_back(new_texture);
877 }
878 catch (Ogre::Exception &e)
879 {
880 ReportError("Error creating new texture " + texturename + "\n" + e.getDescription());
881 return false;
882 }
883
884 //copy source and overlay images onto new image
885 Ogre::Box source (x, y, x + width, y + height);
886 Ogre::Box source_full (0, 0, image1->getWidth(), image1->getHeight());
887 Ogre::Box overlay (0, 0, image2->getWidth(), image2->getHeight());
888 CopyTexture(image1, new_texture, source_full, source_full);
889 CopyTexture(image2, new_texture, overlay, source);
890
891 //create a new material
892 Ogre::MaterialPtr mMat = CreateMaterial(Name, "General");
893
894 //bind texture to material
895 BindTextureToMaterial(mMat, texturename, has_alpha);
896
897 if (sbs->Verbose)
898 Report("AddTextureOverlay: created texture '" + Name + "'");
899
900 //add texture multipliers
901 RegisterTextureInfo(name, "", "", widthmult, heightmult, enable_force, force_mode, new_texture->getSize(), mMat->getSize());
902
903 return true;
904}
905
906std::string TextureManager::GetTextureMaterial(const std::string &name, bool &result, bool report, const std::string &polygon_name)
907{
908 //perform a lookup on a texture, and return material name if it exists, or "Default" if not
909 //returns false in &result if texture load failed, and if default material was used instead
910
911 //use material_name value instead of name, if loaded as a material script instead of a direct texture
912 //if report is true and texture is not found, issue warning
913
914 std::string matname = name;
915
916 if (matname == prev_material)
917 {
918 result = true;
919 return matname;
920 }
921
922 for (size_t i = 0; i < textureinfo.size(); i++)
923 {
924 if (textureinfo[i].name == matname)
925 {
926 if (textureinfo[i].material_name != "")
927 {
928 matname = textureinfo[i].material_name;
929 break;
930 }
931 }
932 }
933 Ogre::MaterialPtr material = GetMaterialByName(matname);
934
935 if (!material.get())
936 {
937 //if material's not found, display a warning and use a default material
938 if (report == true)
939 {
940 std::string message;
941 if (polygon_name != "")
942 message = "Texture '" + matname + "' not found for polygon '" + polygon_name + "'; using default material";
943 else
944 message = "Texture '" + matname + "' not found; using default material";
945 ReportError(message);
946 }
947
948 //set to default material
949 matname = "Default";
950 result = false;
951 }
952 else
953 result = true;
954
955 prev_material = matname;
956 return matname;
957}
958
960{
961 //process texture flip info
962
963 if (tw == 0)
964 tw = 1;
965 if (th == 0)
966 th = 1;
967
968 for (int i = 0; i <= 5; i++)
969 {
970 widthscale[i] = tw;
971 heightscale[i] = th;
972 }
973
974 //texture flipping
975 if (FlipTexture == true)
976 {
977 int info;
978 for (int i = 0; i <= 5; i++)
979 {
980 info = 0;
981 if (i == 0)
982 info = mainnegflip;
983 if (i == 1)
984 info = mainposflip;
985 if (i == 2)
986 info = sidenegflip;
987 if (i == 3)
988 info = sideposflip;
989 if (i == 4)
990 info = topflip;
991 if (i == 5)
992 info = bottomflip;
993
994 if (info == 1 || info == 3)
995 widthscale[i] = -tw;
996 if (info == 2 || info == 3)
997 heightscale[i] = -th;
998 }
999 }
1000}
1001
1002bool TextureManager::GetTextureTiling(const std::string &texture, Real &tw, Real &th)
1003{
1004 //get per-texture tiling values from the textureinfo array
1005 for (size_t i = 0; i < textureinfo.size(); i++)
1006 {
1007 if (textureinfo[i].name == texture)
1008 {
1009 tw = textureinfo[i].widthmult;
1010 th = textureinfo[i].heightmult;
1011 return true;
1012 }
1013 }
1014 return false;
1015}
1016
1017bool TextureManager::GetTextureForce(const std::string &texture, bool &enable_force, bool &force_mode)
1018{
1019 //get per-texture tiling values from the textureinfo array
1020 for (size_t i = 0; i < textureinfo.size(); i++)
1021 {
1022 if (textureinfo[i].name == texture)
1023 {
1024 enable_force = textureinfo[i].enable_force;
1025 force_mode = textureinfo[i].force_mode;
1026 return true;
1027 }
1028 }
1029 return false;
1030}
1031
1033{
1034 //return total number of textures
1035 return texturecount;
1036}
1037
1039{
1040 //return total number of materials
1041 return materialcount;
1042}
1043
1045{
1046 //unload images in all texture wrappers
1047
1048 //for (int i = 0; i < engine->GetTextureList()->GetCount(); i++)
1049 //engine->GetTextureList()->Get(i)->SetImageFile(0);
1050}
1051
1052Real TextureManager::AutoSize(Real n1, Real n2, bool iswidth, Real offset, bool enable_force, bool force_mode)
1053{
1054 //Texture autosizing formulas
1055
1056 if (offset == 0)
1057 offset = 1;
1058
1059 if (iswidth == true)
1060 {
1061 if ((AutoX == true && enable_force == false) || (enable_force == true && force_mode == true))
1062 return std::abs(n1 - n2) * offset;
1063 else
1064 return offset;
1065 }
1066 else
1067 {
1068 if ((AutoY == true && enable_force == false) || (enable_force == true && force_mode == true))
1069 return std::abs(n1 - n2) * offset;
1070 else
1071 return offset;
1072 }
1073}
1074
1076{
1077 //enable or disable texture autosizing
1078 AutoX = x;
1079 AutoY = y;
1080}
1081
1082void TextureManager::GetAutoSize(bool &x, bool &y)
1083{
1084 //return texture autosizing values
1085 x = AutoX;
1086 y = AutoY;
1087}
1088
1089Vector2 TextureManager::CalculateSizing(const std::string &texture, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, int direction, Real tw, Real th)
1090{
1091 //calculate texture autosizing based on polygon extents
1092
1093 //Call texture autosizing formulas
1094 Real tw2 = tw, th2 = th;
1095
1096 bool force_enable = false, force_mode = false;
1097 GetTextureForce(texture, force_enable, force_mode);
1098
1099 Real width = v1.distance(v2);
1100 Real height = v2.distance(v3);
1101
1102 tw2 = AutoSize(0, width, true, tw, force_enable, force_mode);
1103 th2 = AutoSize(0, height, false, th, force_enable, force_mode);
1104
1105 //return results
1106 return Vector2(tw2, th2);
1107}
1108
1109bool TextureManager::GetTextureMapping(PolyArray &vertices, Vector3 &v1, Vector3 &v2, Vector3 &v3, int &direction)
1110{
1111 //returns texture mapping coordinates for the specified vertices, in the v1, v2, and v3 vectors
1112 //this performs one of 3 methods - planar mapping, index mapping and manual vertex mapping
1113
1114 if (MapMethod == 0)
1115 {
1116 //planar method
1117
1118 Vector2 x, y, z;
1119 PolyArray varray;
1120 bool rev_x = false, rev_y = false, rev_z = false;
1121
1122 //determine the largest projection dimension (the dimension that the polygon is generally on;
1123 //with a floor Y would be biggest)
1124 Plane plane = sbs->GetUtility()->ComputePlane(vertices);
1125 Vector3 normal = plane.normal;
1126
1127 direction = 0; //x; faces left/right
1128
1129 if (std::abs (normal.y) > std::abs (normal.x) && std::abs (normal.y) > std::abs (normal.z))
1130 direction = 1; //y biggest; faces up/down
1131 else if (std::abs (normal.z) > std::abs (normal.x))
1132 direction = 2; //z biggest; faces front/back
1133 else if (normal.x == 0)
1134 return false; //fail if normal vector is 0
1135
1136 size_t selX = (1 << direction) & 0x3;
1137 size_t selY = (1 << selX) & 0x3;
1138
1139 varray.reserve(vertices.size());
1140 for (size_t i = 0; i < vertices.size(); i++)
1141 {
1142 varray.emplace_back(Vector3(vertices[i][selX], vertices[i][selY], 0));
1143 }
1144
1145 //automatically flip texture based on largest normal (corrects some situations where the texture is incorrectly reversed)
1146 if (PlanarRotate == false)
1147 {
1148 if (direction == 0 && normal.x > 0)
1149 rev_z = true;
1150
1151 if (direction == 1 && normal.y > 0)
1152 rev_x = true;
1153
1154 if (direction == 2 && normal.z < 0)
1155 rev_x = true;
1156 }
1157 else
1158 {
1159 if (direction == 0 && normal.x < 0)
1160 rev_z = true;
1161
1162 if (direction == 0)
1163 rev_y = true;
1164
1165 if (direction == 1 && normal.y > 0)
1166 rev_z = true;
1167
1168 if (direction == 1)
1169 rev_x = true;
1170
1171 if (direction == 2)
1172 rev_y = true;
1173
1174 if (direction == 2 && normal.z > 0)
1175 rev_x = true;
1176 }
1177
1178 //force a texture flip based on parameters
1179 if (RevX == true)
1180 rev_x = !rev_x;
1181
1182 if (RevY == true)
1183 rev_y = !rev_y;
1184
1185 if (RevZ == true)
1186 rev_z = !rev_z;
1187
1188 //get extents of both dimensions, since the polygon is projected in 2D as X and Y coordinates
1189 Vector2 a, b;
1190 a = sbs->GetUtility()->GetExtents(varray, 1);
1191 b = sbs->GetUtility()->GetExtents(varray, 2);
1192
1193 //set the result 2D coordinates
1194 if (direction == 0)
1195 {
1196 Vector2 pos, pos2;
1197
1198 if (rev_z == false)
1199 pos = Vector2(b.y, b.x);
1200 else
1201 pos = Vector2(b.x, b.y);
1202
1203 if (rev_y == false)
1204 pos2 = Vector2(a.y, a.x);
1205 else
1206 pos2 = Vector2(a.x, a.y);
1207
1208 if (PlanarRotate == false)
1209 {
1210 v1.z = pos.x; //right
1211 v2.z = pos.y; //left
1212 v3.z = pos.y; //left
1213 v1.y = pos2.x; //top
1214 v2.y = pos2.x; //top
1215 v3.y = pos2.y; //bottom
1216 }
1217 else
1218 {
1219 v1.z = pos.y; //left
1220 v2.z = pos.y; //left
1221 v3.z = pos.x; //right
1222 v1.y = pos2.x; //top
1223 v2.y = pos2.y; //bottom
1224 v3.y = pos2.y; //bottom
1225 }
1226 }
1227 if (direction == 1)
1228 {
1229 Vector2 pos, pos2;
1230
1231 if (rev_x == false)
1232 pos = Vector2(b.x, b.y);
1233 else
1234 pos = Vector2(b.y, b.x);
1235
1236 if (rev_z == false)
1237 pos2 = Vector2(a.x, a.y);
1238 else
1239 pos2 = Vector2(a.y, a.x);
1240
1241 if (PlanarRotate == false)
1242 {
1243 v1.x = pos.x; //left
1244 v2.x = pos.y; //right
1245 v3.x = pos.y; //right
1246 v1.z = pos2.x; //bottom
1247 v2.z = pos2.x; //bottom
1248 v3.z = pos2.y; //top
1249 }
1250 else
1251 {
1252 v1.x = pos.y; //left
1253 v2.x = pos.y; //left
1254 v3.x = pos.x; //right
1255 v1.z = pos2.y; //bottom
1256 v2.z = pos2.x; //top
1257 v3.z = pos2.x; //top
1258 }
1259 }
1260 if (direction == 2)
1261 {
1262 Vector2 pos, pos2;
1263
1264 if (rev_x == false)
1265 pos = Vector2(a.y, a.x);
1266 else
1267 pos = Vector2(a.x, a.y);
1268
1269 if (rev_y == false)
1270 pos2 = Vector2(b.y, b.x);
1271 else
1272 pos2 = Vector2(b.x, b.y);
1273
1274 if (PlanarRotate == false)
1275 {
1276 v1.x = pos.x; //right
1277 v2.x = pos.y; //left
1278 v3.x = pos.y; //left
1279 v1.y = pos2.x; //top
1280 v2.y = pos2.x; //top
1281 v3.y = pos2.y; //bottom
1282 }
1283 else
1284 {
1285 v1.x = pos.y; //left
1286 v2.x = pos.y; //left
1287 v3.x = pos.x; //right
1288 v1.y = pos2.x; //top
1289 v2.y = pos2.y; //bottom
1290 v3.y = pos2.y; //bottom
1291 }
1292 }
1293
1294 //use the plane equation to get the coordinate values of the dropped dimension
1295 if (direction == 0)
1296 {
1297 v1.x = -((normal.y * v1.y) + (normal.z * v1.z) + plane.d) / normal.x; //get X
1298 v2.x = -((normal.y * v2.y) + (normal.z * v2.z) + plane.d) / normal.x; //get X
1299 v3.x = -((normal.y * v3.y) + (normal.z * v3.z) + plane.d) / normal.x; //get X
1300
1301 if (PlanarFlat == true)
1302 v3.x = v2.x;
1303 }
1304 if (direction == 1)
1305 {
1306 v1.y = -((normal.x * v1.x) + (normal.z * v1.z) + plane.d) / normal.y; //get Y
1307 v2.y = -((normal.x * v2.x) + (normal.z * v2.z) + plane.d) / normal.y; //get Y
1308 v3.y = -((normal.x * v3.x) + (normal.z * v3.z) + plane.d) / normal.y; //get Y
1309
1310 if (PlanarFlat == true)
1311 v3.y = v2.y;
1312 }
1313 if (direction == 2)
1314 {
1315 v1.z = -((normal.x * v1.x) + (normal.y * v1.y) + plane.d) / normal.z; //get Z
1316 v2.z = -((normal.x * v2.x) + (normal.y * v2.y) + plane.d) / normal.z; //get Z
1317 v3.z = -((normal.x * v3.x) + (normal.y * v3.y) + plane.d) / normal.z; //get Z
1318
1319 if (PlanarFlat == true)
1320 v3.z = v2.z;
1321 }
1322 }
1323 if (MapMethod == 1)
1324 {
1325 //index method
1326 v1 = vertices[MapIndex[0]];
1327 v2 = vertices[MapIndex[1]];
1328 v3 = vertices[MapIndex[2]];
1329
1330 //determine the largest projection dimension (the dimension that the polygon is generally on;
1331 //with a floor Y would be biggest)
1332 Plane plane = Plane(v1, v2, v3);
1333 Vector3 normal = plane.normal;
1334
1335 direction = 0; //x; faces left/right
1336
1337 if (std::abs (normal.y) > std::abs (normal.x) && std::abs (normal.y) > std::abs (normal.z))
1338 direction = 1; //y biggest; faces up/down
1339 else if (std::abs (normal.z) > std::abs (normal.x))
1340 direction = 2; //z biggest; faces front/back
1341 else if (normal.x == 0)
1342 return false; //fail if normal vector is 0
1343 }
1344 if (MapMethod == 2)
1345 {
1346 //advanced manual vertex method
1347
1348 for (int i = 0; i < 3; i++)
1349 {
1350 for (int j = 0; j < 3; j++)
1351 {
1352 std::string string;
1353 if (j == 0)
1354 string = MapVerts1[i];
1355 if (j == 1)
1356 string = MapVerts2[i];
1357 if (j == 2)
1358 string = MapVerts3[i];
1359
1360 SetCase(string, false);
1361
1362 //find X component
1363 size_t location = string.find("x");
1364 if (location != std::string::npos)
1365 {
1366 std::string number = string.substr(location + 1);
1367 if (ToInt(number) < (int)vertices.size())
1368 ReplaceAll(string, "x" + number, ToString(vertices[ToInt(number)].x));
1369 else
1370 ReplaceAll(string, "x" + number, "0"); //number value out of bounds
1371 }
1372
1373 //find Y component
1374 location = string.find("y");
1375 if (location != std::string::npos)
1376 {
1377 std::string number = string.substr(location + 1);
1378 if (ToInt(number) < (int)vertices.size())
1379 ReplaceAll(string, "y" + number, ToString(vertices[ToInt(number)].y));
1380 else
1381 ReplaceAll(string, "y" + number, "0"); //number value out of bounds
1382 }
1383
1384 //find Z component
1385 location = string.find("z");
1386 if (location != std::string::npos)
1387 {
1388 std::string number = string.substr(location + 1);
1389 if (ToInt(number) < (int)vertices.size())
1390 ReplaceAll(string, "z" + number, ToString(vertices[ToInt(number)].z));
1391 else
1392 ReplaceAll(string, "z" + number, "0"); //number value out of bounds
1393 }
1394
1395 //store values
1396 if (i == 0)
1397 {
1398 if (j == 0)
1399 v1.x = ToFloat(string);
1400 if (j == 1)
1401 v2.x = ToFloat(string);
1402 if (j == 2)
1403 v3.x = ToFloat(string);
1404 }
1405 if (i == 1)
1406 {
1407 if (j == 0)
1408 v1.y = ToFloat(string);
1409 if (j == 1)
1410 v2.y = ToFloat(string);
1411 if (j == 2)
1412 v3.y = ToFloat(string);
1413 }
1414 if (i == 2)
1415 {
1416 if (j == 0)
1417 v1.z = ToFloat(string);
1418 if (j == 1)
1419 v2.z = ToFloat(string);
1420 if (j == 2)
1421 v3.z = ToFloat(string);
1422 }
1423 }
1424 }
1425
1426 //determine the largest projection dimension (the dimension that the polygon is generally on;
1427 //with a floor Y would be biggest)
1428 Plane plane = Plane(v1, v2, v3);
1429 Vector3 normal = plane.normal;
1430
1431 direction = 0; //x; faces left/right
1432
1433 if (std::abs (normal.y) > std::abs (normal.x) && std::abs (normal.y) > std::abs (normal.z))
1434 direction = 1; //y biggest; faces up/down
1435 else if (std::abs (normal.z) > std::abs (normal.x))
1436 direction = 2; //z biggest; faces front/back
1437 else if (normal.x == 0)
1438 return false; //fail if normal vector is 0
1439 }
1440
1441 return true;
1442}
1443
1445{
1446 //Resets UV texture mapping to defaults or previous values
1447 if (todefaults == true)
1448 {
1449 if (DefaultMapper == 0)
1450 SetPlanarMapping(false, false, false, false, false);
1451 if (DefaultMapper == 1)
1452 SetTextureMapping(0, Vector2(0, 0), 1, Vector2(1, 0), 2, Vector2(1, 1));
1453 if (DefaultMapper == 2)
1454 SetTextureMapping2("x0", "y0", "z0", Vector2(0, 0), "x1", "y1", "z1", Vector2(1, 0), "x2", "y2", "z2", Vector2(1, 1));
1455 }
1456 else
1457 {
1458 if (OldMapMethod == 0)
1460 if (OldMapMethod == 1)
1462 if (OldMapMethod == 2)
1464 }
1465}
1466
1467void TextureManager::SetPlanarMapping(bool flat, bool FlipX, bool FlipY, bool FlipZ, bool rotate)
1468{
1469 //sets planar texture mapping parameters
1470 //X, Y and Z reverse planar texture mapping per axis
1471 //Flat determines if depth should be ignored when mapping
1472
1473 //first backup old parameters
1474 BackupMapping();
1475
1476 //now set new parameters
1477 RevX = FlipX;
1478 RevY = FlipY;
1479 RevZ = FlipZ;
1480 MapUV[0] = Vector2(0, 0);
1481 MapUV[1] = Vector2(1, 0);
1482 MapUV[2] = Vector2(1, 1);
1483 PlanarFlat = flat;
1484 MapMethod = 0;
1485 PlanarRotate = rotate;
1486}
1487
1488void TextureManager::GetPlanarMapping(bool &flat, bool &FlipX, bool &FlipY, bool &FlipZ, bool &rotate)
1489{
1490 //gets planar texture mapping parameters
1491 //X, Y and Z reverse planar texture mapping per axis
1492 //Flat determines if depth should be ignored when mapping
1493
1494 FlipX = RevX;
1495 FlipY = RevY;
1496 FlipZ = RevZ;
1497 flat = PlanarFlat;
1498 rotate = PlanarRotate;
1499}
1500
1501void TextureManager::SetTextureMapping(int vertindex1, Vector2 uv1, int vertindex2, Vector2 uv2, int vertindex3, Vector2 uv3)
1502{
1503 //Manually sets UV texture mapping. Use ResetTextureMapping to return to default values
1504
1505 BackupMapping();
1506
1507 //set new values
1508 MapIndex[0] = vertindex1;
1509 MapIndex[1] = vertindex2;
1510 MapIndex[2] = vertindex3;
1511 MapUV[0] = uv1;
1512 MapUV[1] = uv2;
1513 MapUV[2] = uv3;
1514 MapMethod = 1;
1515}
1516
1517void TextureManager::SetTextureMapping2(const std::string & x1, const std::string & y1, const std::string & z1, Vector2 uv1, const std::string & x2, const std::string & y2, const std::string & z2, Vector2 uv2, const std::string & x3, const std::string & y3, const std::string & z3, Vector2 uv3)
1518{
1519 //Manually sets UV texture mapping (advanced version)
1520 //Use ResetTextureMapping to return to default values
1521
1522 BackupMapping();
1523
1524 MapVerts1[0] = x1;
1525 MapVerts1[1] = y1;
1526 MapVerts1[2] = z1;
1527 MapVerts2[0] = x2;
1528 MapVerts2[1] = y2;
1529 MapVerts2[2] = z2;
1530 MapVerts3[0] = x3;
1531 MapVerts3[1] = y3;
1532 MapVerts3[2] = z3;
1533 MapUV[0] = uv1;
1534 MapUV[1] = uv2;
1535 MapUV[2] = uv3;
1536 MapMethod = 2;
1537}
1538
1540{
1541 //backup texture mapping parameters
1542 if (MapMethod == 0)
1543 {
1544 OldRevX = RevX;
1545 OldRevY = RevY;
1546 OldRevZ = RevZ;
1549 }
1550 else
1551 {
1552 for (int i = 0; i <= 2; i++)
1553 {
1554 if (MapMethod == 1)
1555 OldMapIndex[i] = MapIndex[i];
1556 if (MapMethod == 2)
1557 {
1558 OldMapVerts1[i] = MapVerts1[i];
1559 OldMapVerts1[i] = MapVerts1[i];
1560 OldMapVerts1[i] = MapVerts1[i];
1561 }
1562 }
1563 }
1564 for (int i = 0; i <= 2; i++)
1565 OldMapUV[i] = MapUV[i];
1567}
1568
1569void TextureManager::SetTextureFlip(int mainneg, int mainpos, int sideneg, int sidepos, int top, int bottom)
1570{
1571 //flip a texture on a specified side either horizontally or vertically (or both)
1572 //parameters are:
1573 //0 = no flipping
1574 //1 = flip horizontally
1575 //2 = flip vertically
1576 //3 = flip both
1577
1578 mainnegflip = mainneg;
1579 mainposflip = mainpos;
1580 sidenegflip = sideneg;
1581 sideposflip = sidepos;
1582 topflip = top;
1583 bottomflip = bottom;
1584 FlipTexture = true;
1585}
1586
1587void TextureManager::SetTextureOverride(const std::string &mainneg, const std::string &mainpos, const std::string &sideneg, const std::string &sidepos, const std::string &top, const std::string &bottom)
1588{
1589 //set override textures and enable override
1590
1591 mainnegtex = TrimStringCopy(mainneg);
1592 mainpostex = TrimStringCopy(mainpos);
1593 sidenegtex = TrimStringCopy(sideneg);
1594 sidepostex = TrimStringCopy(sidepos);
1595 toptex = TrimStringCopy(top);
1596 bottomtex = TrimStringCopy(bottom);
1597 TextureOverride = true;
1598}
1599
1600std::string TextureManager::ListTextures(bool show_filename)
1601{
1602 //list loaded textures
1603
1604 std::string list;
1605 if (show_filename == true)
1606 list.append("Name --- Filename\n\n");
1607
1608 for (size_t i = 0; i < textureinfo.size(); i++)
1609 {
1610 list.append(textureinfo[i].name);
1611 if (show_filename == true)
1612 {
1613 list.append(", ");
1614 list.append(textureinfo[i].filename);
1615 }
1616 list.append("\n");
1617 }
1618 return list;
1619}
1620
1622{
1623 return (int)textureinfo.size();
1624}
1625
1627{
1628 if (index >= 0 && index < textureinfo.size())
1629 {
1630 info = textureinfo[index];
1631 return true;
1632 }
1633
1634 return false;
1635}
1636
1638{
1639 if (index >= 0 && index < textureinfo.size())
1640 {
1641 textureinfo[index] = info;
1642 return true;
1643 }
1644
1645 return false;
1646}
1647
1648void TextureManager::IncrementTextureUsage(const std::string &name)
1649{
1650 for (size_t i = 0; i < textureinfo.size(); i++)
1651 {
1652 if (textureinfo[i].name == name)
1653 {
1655 return;
1656 }
1657 }
1658}
1659
1660void TextureManager::DecrementTextureUsage(const std::string &name)
1661{
1662 for (size_t i = 0; i < textureinfo.size(); i++)
1663 {
1664 if (textureinfo[i].name == name)
1665 {
1666 textureinfo[i].dependencies--;
1667 return;
1668 }
1669 }
1670}
1671
1672// from http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Creating+transparency+based+on+a+key+colour+in+code
1693Ogre::TexturePtr TextureManager::loadChromaKeyedTexture(const std::string& filename, const std::string& resGroup, const std::string& name, const Ogre::ColourValue& keyCol, int numMipmaps, Real threshold)
1694{
1695 using namespace Ogre;
1696 using std::fabs;
1697 Image srcImg;
1698 Ogre::ColourValue keyCol2 = keyCol;
1699
1700 String strExt;
1701
1702 size_t pos = filename.find_last_of(".");
1703 if (pos != String::npos && pos < (filename.length() - 1))
1704 strExt = filename.substr(pos+1);
1705
1706 //srcImg.load(filename, resGroup);
1707 DataStreamPtr encoded = ResourceGroupManager::getSingleton().openResource(filename, resGroup);
1708 SetCase(strExt, false);
1709 if (strExt == "gif")
1710 {
1711 //get chroma transparency color from GIF file data
1712 uchar enabled = 0, trans_color = 0, check = 0;
1713 size_t found = 0;
1714
1715 //first, find graphics control extension (starts with 21:F9:04 hex)
1716 for (size_t i = 0; i < encoded->size(); i++)
1717 {
1718 //extension found
1719 if (found == 3 && i < encoded->size() - 4)
1720 {
1721 //gif transparency info
1722
1723 //bit flag layout of packed field
1724 struct ext {
1725 unsigned char transparent : 1; //transparency flag is first bit
1726 unsigned char userinput : 1;
1727 unsigned char disposal : 3;
1728 unsigned char reserved : 3;
1729 };
1730 ext flags;
1731
1732 encoded->seek(i); //transparency enabled if value is 0x1
1733 encoded->read(&flags, 1);
1734 enabled = flags.transparent;
1735 encoded->seek(i + 3); //transparency color
1736 encoded->read(&trans_color, 1);
1737 break;
1738 }
1739
1740 encoded->seek(i);
1741 encoded->read(&check, 1);
1742
1743 //check for first value, 21h
1744 if (check == 33 && i < encoded->size() - 4)
1745 {
1746 found = 1;
1747
1748 //find second value, F9h
1749 i++;
1750 encoded->seek(i);
1751 encoded->read(&check, 1);
1752 if (check == 249)
1753 found++;
1754
1755 //find third value, 04h
1756 i++;
1757 encoded->seek(i);
1758 encoded->read(&check, 1);
1759 if (check == 4)
1760 found++;
1761 }
1762 }
1763
1764 if (enabled == 1)
1765 {
1766 //get color value from image palette
1767 uchar r, g, b;
1768 Ogre::uint pos = (Ogre::uint(trans_color) * 3) + 13; //palette starts at offset 0x13
1769 encoded->seek(pos);
1770 encoded->read(&r, 1);
1771 encoded->seek(pos + 1);
1772 encoded->read(&g, 1);
1773 encoded->seek(pos + 2);
1774 encoded->read(&b, 1);
1775 keyCol2.r = float(r / 255);
1776 keyCol2.g = float(g / 255);
1777 keyCol2.b = float(b / 255);
1778 }
1779 encoded->seek(0);
1780 }
1781 srcImg.load(encoded, strExt);
1782
1783 unsigned int width = (unsigned int)srcImg.getWidth(), height = (unsigned int)srcImg.getHeight();
1784 // Since Ogre 1.6 Shoggoth, the OGRE_ALLOC_T memory macro must be used:
1785 uchar* pixelData = OGRE_ALLOC_T(uchar, PixelUtil::getMemorySize(width, height, 1, PF_A8R8G8B8), MEMCATEGORY_GENERAL);
1786 unsigned long pxDataIndex = 0, pxDataIndexStep = (unsigned long)PixelUtil::getNumElemBytes(PF_A8R8G8B8);
1787
1788 for(unsigned int y = 0; y < height; y++)
1789 {
1790 for(unsigned int x = 0; x < width; x++)
1791 {
1792 ColourValue pixCol = srcImg.getColourAt(x, y, 0);
1793 ColourValue diffCol = pixCol - keyCol2;
1794 pixCol.a = ((std::abs(diffCol.r) < threshold) && (std::abs(diffCol.g) < threshold) && (std::abs(diffCol.b) < threshold)) ? 0.0f : 1.0f;
1795 Ogre::PixelUtil::packColour(pixCol, PF_A8R8G8B8, static_cast<void*>(pixelData + pxDataIndex));
1796 pxDataIndex += pxDataIndexStep;
1797 }
1798 }
1799
1800 Image chromaKeyedImg;
1801 chromaKeyedImg.loadDynamicImage(pixelData, width, height, 1, PF_A8R8G8B8, true);
1802 // You could save the chroma keyed image at this point for caching:
1803 // chromaKeyedImg.save(resName);
1804 Ogre::TexturePtr mTex = Ogre::TextureManager::getSingleton().loadImage(name, resGroup, chromaKeyedImg, TEX_TYPE_2D, numMipmaps);
1806 return mTex;
1807}
1808
1809bool TextureManager::WriteToTexture(const std::string &str, Ogre::TexturePtr destTexture, int destLeft, int destTop, int destRight, int destBottom, Ogre::FontPtr font, const Ogre::ColourValue &color, char justify, char vert_justify, bool wordwrap)
1810{
1811 //justify is left 'l' by default - set to 'r' or 'c' for right or center
1812 //vert_justify is top 't' by default - set to 'c' or 'b' for center or bottom
1813
1814 using namespace Ogre;
1815
1816 if ((int)destTexture->getHeight() < destBottom - 1)
1817 destBottom = destTexture->getHeight() - 1;
1818 if ((int)destTexture->getWidth() < destRight - 1)
1819 destRight = destTexture->getWidth() - 1;
1820
1821 try
1822 {
1823 if (!font->isLoaded())
1824 font->load();
1825 }
1826 catch (Ogre::Exception &e)
1827 {
1828 return ReportError("Error loading font " + font->getName() + "\n" + e.getDescription());
1829 }
1830
1831 std::string texname = GetTextureName(font->getMaterial());
1832 TexturePtr fontTexture = GetTextureByName(texname);
1833
1834 if (!fontTexture)
1835 return false;
1836
1837 //output glyph map to file
1838 //SaveTexture(fontTexture, "test.png");
1839
1840 HardwarePixelBufferSharedPtr fontBuffer = fontTexture->getBuffer();
1841 HardwarePixelBufferSharedPtr destBuffer = destTexture->getBuffer();
1842
1843 PixelBox destPb = destBuffer->lock(Box(0, 0, destTexture->getWidth() - 1, destTexture->getHeight() - 1), HardwareBuffer::HBL_NORMAL);
1844
1845 // The font texture buffer was created write only...so we cannot read it back :o). One solution is to copy the buffer instead of locking it. (Maybe there is a way to create a font texture which is not write_only ?)
1846
1847 int index = -1;
1848 for (size_t i = 0; i < textureboxes.size(); i++)
1849 {
1850 if (textureboxes[i].font == font)
1851 {
1852 index = (int)i;
1853 break;
1854 }
1855 }
1856 if (index == -1)
1857 {
1858 // create a buffer
1859 index = (int)textureboxes.size();
1860 textureboxes.resize(textureboxes.size() + 1);
1861 textureboxes[index].font = font;
1862 size_t nBuffSize = fontBuffer->getSizeInBytes();
1863 textureboxes[index].buffer = (unsigned char*)calloc(nBuffSize, sizeof(unsigned char));
1864
1865 // create pixel box using the copy of the buffer
1866 textureboxes[index].box = new Ogre::PixelBox(fontBuffer->getWidth(), fontBuffer->getHeight(), fontBuffer->getDepth(), fontBuffer->getFormat(), textureboxes[index].buffer);
1867 fontBuffer->blitToMemory(*textureboxes[index].box); //this is very slow
1868 }
1869
1870 unsigned char* fontData = static_cast<unsigned char*>(textureboxes[index].box->data);
1871 unsigned char* destData = static_cast<unsigned char*>(destPb.data);
1872
1873 const int fontPixelSize = (int)PixelUtil::getNumElemBytes(textureboxes[index].box->format);
1874 const int destPixelSize = (int)PixelUtil::getNumElemBytes(destPb.format);
1875
1876 const int fontRowPitchBytes = (int)textureboxes[index].box->rowPitch * fontPixelSize;
1877 const int destRowPitchBytes = (int)destPb.rowPitch * destPixelSize;
1878
1879 Box *GlyphTexCoords;
1880 GlyphTexCoords = new Box[str.size()];
1881
1882 Font::UVRect glypheTexRect;
1883 int charheight = 0; //max character height
1884 int charwidth = 0; //max character width
1885
1886 for(size_t i = 0; i < str.size(); i++)
1887 {
1888 if ((str[i] != '\t') && (str[i] != '\n') && (str[i] != ' '))
1889 {
1890 glypheTexRect = font->getGlyphTexCoords(str[i]);
1891 GlyphTexCoords[i].left = uint32_t(glypheTexRect.left * fontTexture->getSrcWidth());
1892 GlyphTexCoords[i].top = uint32_t(glypheTexRect.top * fontTexture->getSrcHeight());
1893 GlyphTexCoords[i].right = uint32_t(glypheTexRect.right * fontTexture->getSrcWidth());
1894 GlyphTexCoords[i].bottom = uint32_t(glypheTexRect.bottom * fontTexture->getSrcHeight());
1895
1896 if (glypheTexRect.right < glypheTexRect.left || glypheTexRect.bottom < glypheTexRect.top)
1897 return ReportError("Error processing font - invalid texture coordinates for font " + font->getName());
1898
1899 //get true bottom of character, since the previous routine doesn't seem to get an accurate result
1900 size_t lastline = 0;
1901 for (size_t j = 0; j < GlyphTexCoords[i].getHeight(); j++)
1902 {
1903 for (size_t k = 0; k < GlyphTexCoords[i].getWidth(); k++)
1904 {
1905 float alpha = color.a * (fontData[(j + GlyphTexCoords[i].top) * fontRowPitchBytes + (k + GlyphTexCoords[i].left) * fontPixelSize + 1] / 255.0f);
1906 if (alpha > 0.0)
1907 lastline = j;
1908 }
1909 }
1910 GlyphTexCoords[i].bottom = GlyphTexCoords[i].top + lastline + 1;
1911
1912 if ((int)GlyphTexCoords[i].getHeight() > charheight)
1913 charheight = (int)GlyphTexCoords[i].getHeight();
1914 if ((int)GlyphTexCoords[i].getWidth() > charwidth)
1915 charwidth = (int)GlyphTexCoords[i].getWidth();
1916 }
1917 }
1918
1919 int cursorX = 0;
1920 int cursorY = 0;
1921 //int lineend = destRight - destLeft;
1922 bool carriagereturn = true;
1923 for (size_t strindex = 0; strindex < str.size(); strindex++)
1924 {
1925 switch(str[strindex])
1926 {
1927 case ' ':
1928 cursorX += charwidth;
1929 break;
1930 case '\t':
1931 cursorX += charwidth * 3;
1932 break;
1933 case '\n':
1934 cursorY += charheight; carriagereturn = true;
1935 break;
1936 default:
1937 {
1938 //wrapping
1939 /*if ((cursorX + GlyphTexCoords[strindex].getWidth() > lineend) && !carriagereturn)
1940 {
1941 cursorY += charheight;
1942 carriagereturn = true;
1943 }*/
1944
1945 //justify
1946 if (carriagereturn)
1947 {
1948 int l = (int)strindex;
1949 int textwidth = 0;
1950 int wordwidth = 0;
1951
1952 while((l < (int)str.size()) && (str[l] != '\n'))
1953 {
1954 wordwidth = 0;
1955
1956 switch (str[l])
1957 {
1958 case ' ':
1959 wordwidth = charwidth; ++l;
1960 break;
1961 case '\t':
1962 wordwidth = charwidth *3; ++l;
1963 break;
1964 case '\n':
1965 l = (int)str.size();
1966 }
1967
1968 if (wordwrap)
1969 {
1970 while((l < (int)str.size()) && (str[l] != ' ') && (str[l] != '\t') && (str[l] != '\n'))
1971 {
1972 wordwidth += (int)GlyphTexCoords[l].getWidth();
1973 ++l;
1974 }
1975 }
1976 else
1977 {
1978 wordwidth += (int)GlyphTexCoords[l].getWidth();
1979 l++;
1980 }
1981
1982 textwidth += wordwidth;
1983 }
1984
1985 if (textwidth == 0)
1986 textwidth = destRight - destLeft;
1987
1988 switch (justify)
1989 {
1990 case 'c':
1991 cursorX = destLeft + ((destRight - destLeft) / 2) - (textwidth / 2);
1992 //lineend = (destRight - destLeft) - cursorX;
1993 break;
1994
1995 case 'r':
1996 cursorX = destRight - textwidth;
1997 //lineend = destRight - destLeft;
1998 break;
1999
2000 default:
2001 cursorX = destRight;
2002 //lineend = textwidth;
2003 break;
2004 }
2005
2006 switch (vert_justify)
2007 {
2008 case 'c':
2009 cursorY = destTop + ((destBottom - destTop) / 2) - (charheight / 2);
2010 break;
2011
2012 case 'b':
2013 cursorY = destBottom - charheight + cursorY;
2014 break;
2015 default:
2016 cursorY = destTop;
2017 }
2018 carriagereturn = false;
2019 }
2020
2021 //abort - not enough space to draw
2022 if ((cursorY + charheight) >= (int)destTexture->getHeight())
2023 {
2024 Report("Text '" + str + "' out of bounds\n");
2025 goto stop;
2026 }
2027 //printf("%d, %d\n", cursorX, cursorY);
2028
2029 //draw pixel by pixel
2030 for (size_t i = 0; i < GlyphTexCoords[strindex].getHeight(); i++)
2031 {
2032 for (size_t j = 0; j < GlyphTexCoords[strindex].getWidth(); j++)
2033 {
2034 float alpha = color.a * (fontData[(i + GlyphTexCoords[strindex].top) * fontRowPitchBytes + (j + GlyphTexCoords[strindex].left) * fontPixelSize + 1] / 255.0f);
2035 float invalpha = 1.0f - alpha;
2036 int offset = (i + cursorY) * destRowPitchBytes + (j + cursorX) * destPixelSize;
2037 if (offset >= 0)
2038 {
2039 ColourValue pix;
2040 PixelUtil::unpackColour(&pix, destPb.format, &destData[offset]);
2041 pix = (pix * invalpha) + (color * alpha);
2042 PixelUtil::packColour(pix, destPb.format, &destData[offset]);
2043 }
2044 }
2045 }
2046
2047 cursorX += (int)GlyphTexCoords[strindex].getWidth();
2048 break;
2049 }//default
2050 }//switch
2051 }//for
2052
2053 stop:
2054 delete[] GlyphTexCoords;
2055
2056 destBuffer->unlock();
2057 return true;
2058}
2059
2060void TextureManager::SaveTexture(Ogre::TexturePtr texture, const std::string & filename)
2061{
2062 //save a raw texture to a file
2063
2064 Ogre::Image image;
2065 texture->convertToImage(image, true);
2066 image.save(filename);
2067}
2068
2069bool TextureManager::GetTextureImage(Ogre::TexturePtr texture)
2070{
2071 if (!texture)
2072 return false;
2073
2074 SaveTexture(texture, "temp.jpg");
2075 return true;
2076}
2077
2082
2087
2092
2097
2098Ogre::TexturePtr TextureManager::LoadTexture(const std::string &filename, int mipmaps, bool &has_alpha, bool use_alpha_color, Ogre::ColourValue alpha_color)
2099{
2100 //set verbosity level
2101 Ogre::TextureManager::getSingleton().setVerbose(sbs->Verbose);
2102
2103 //exit if no texture specified
2104 if (filename == "")
2105 return 0;
2106
2107 std::string filename2 = filename;
2108
2109 //determine if the file is a GIF image, to force keycolor alpha
2110 std::string extension = filename2.substr(filename.size() - 3);
2111 SetCase(extension, false);
2112 if (extension == "gif")
2113 use_alpha_color = true;
2114
2115 //load the texture
2116 std::string path = sbs->GetMountPath(filename2, filename2);
2117 Ogre::TexturePtr mTex;
2118 std::string texturename;
2119 has_alpha = false;
2120
2121 try
2122 {
2123 if (use_alpha_color == false)
2124 {
2125 //get any existing texture
2126 mTex = GetTextureByName(filename2, path);
2127
2128 //if not found, load new texture
2129 if (!mTex)
2130 {
2131 mTex = Ogre::TextureManager::getSingleton().load(filename2, path, Ogre::TEX_TYPE_2D, mipmaps);
2133 }
2134
2135 if (!mTex)
2136 {
2137 ReportError("Error loading texture" + filename2);
2138 return mTex;
2139 }
2140 texturename = mTex->getName();
2141 has_alpha = mTex->hasAlpha();
2142 }
2143 else
2144 {
2145 //load based on chroma key for alpha
2146
2147 texturename = "kc_" + filename2;
2148
2149 //get any existing texture
2150 mTex = GetTextureByName(texturename, path);
2151
2152 //if not found, load new texture
2153 if (!mTex)
2154 mTex = loadChromaKeyedTexture(filename2, path, texturename, Ogre::ColourValue::White);
2155
2156 if (!mTex)
2157 {
2158 ReportError("Error loading texture" + filename2);
2159 return mTex;
2160 }
2161 has_alpha = true;
2162 }
2163 }
2164 catch (Ogre::Exception &e)
2165 {
2166 //texture needs to be removed if a load failed
2167 Ogre::ResourcePtr wrapper = GetTextureByName(filename2, path);
2168 if (wrapper.get())
2169 Ogre::TextureManager::getSingleton().remove(wrapper);
2170
2171 ReportError("Error loading texture " + filename2 + "\n" + e.getDescription());
2172 return mTex;
2173 }
2174
2175 return mTex;
2176}
2177
2178Ogre::MaterialPtr TextureManager::CreateMaterial(const std::string &name, const std::string &path)
2179{
2180 //unload material if already loaded
2181 if (UnloadMaterial(name, path) == true)
2183
2184 //create new material
2185 Ogre::MaterialPtr mMat;
2186 try
2187 {
2188 mMat = Ogre::MaterialManager::getSingleton().create(ToString(sbs->InstanceNumber) + ":" + name, path);
2189 }
2190 catch (Ogre::Exception& e)
2191 {
2192 ReportError("Error creating material for texture " + name + "\n" + e.getDescription());
2193 return 0;
2194 }
2195
2197
2198 EnableLighting(name, true);
2199 EnableShadows(name, true);
2200
2201 //show only clockwise side of material
2202 mMat->setCullingMode(Ogre::CULL_ANTICLOCKWISE);
2203
2204 return mMat;
2205}
2206
2207void TextureManager::EnableLighting(const std::string &material_name, bool value)
2208{
2209 //enable or disable lighting on a material
2210
2211 Ogre::MaterialPtr mat = GetMaterialByName(material_name);
2212
2213 if (mat)
2214 {
2215 mat->setLightingEnabled(false);
2216 if (sbs->GetConfigBool("Skyscraper.SBS.Lighting", false) == true)
2217 {
2218 mat->setLightingEnabled(value);
2219 mat->setAmbient(sbs->AmbientR, sbs->AmbientG, sbs->AmbientB);
2220 }
2221 }
2222}
2223
2224Ogre::MaterialPtr TextureManager::GetMaterialByName(const std::string &name, const std::string &group)
2225{
2226 Ogre::MaterialPtr ptr = 0;
2227
2228 if (Ogre::ResourceGroupManager::getSingleton().resourceGroupExists(group) == false)
2229 return ptr;
2230
2231 ptr = Ogre::MaterialManager::getSingleton().getByName(ToString(sbs->InstanceNumber) + ":" + name, group);
2232 return ptr;
2233}
2234
2235Ogre::TextureUnitState* TextureManager::BindTextureToMaterial(Ogre::MaterialPtr mMat, std::string texture_name, bool has_alpha)
2236{
2237 Ogre::TextureUnitState *state = mMat->getTechnique(0)->getPass(0)->createTextureUnitState(texture_name);
2238
2239 //enable alpha blending for related textures
2240 if (has_alpha == true)
2241 {
2242 //mMat->setDepthWriteEnabled(false);
2243 //mMat->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
2244
2245 //enable hard alpha for alpha mask values 128 and above
2246 mMat->getTechnique(0)->getPass(0)->setAlphaRejectSettings(Ogre::CMPF_GREATER_EQUAL, 128);
2247 }
2248 return state;
2249}
2250
2251Ogre::TextureUnitState* TextureManager::GetTextureUnitState(Ogre::MaterialPtr mMat)
2252{
2253 //get first texture unit state
2254 return mMat->getTechnique(0)->getPass(0)->getTextureUnitState(0);
2255}
2256
2257std::string TextureManager::GetTextureName(Ogre::MaterialPtr mMat)
2258{
2259 std::string texname = "";
2260
2261 Ogre::TextureUnitState *state = GetTextureUnitState(mMat);
2262 if (state)
2263 texname = state->getTextureName();
2264
2265 return texname;
2266}
2267
2268Ogre::TexturePtr TextureManager::GetTextureByName(const std::string &name, const std::string &group)
2269{
2270 Ogre::TexturePtr ptr = 0;
2271
2272 if (Ogre::ResourceGroupManager::getSingleton().resourceGroupExists(group) == false)
2273 return ptr;
2274
2275 ptr = Ogre::TextureManager::getSingleton().getByName(name, group);
2276 return ptr;
2277}
2278
2280{
2281 //delete all registered materials
2282
2283 for (size_t i = 0; i < textureinfo.size(); i++)
2284 {
2285 Ogre::MaterialManager::getSingleton().remove(ToString(sbs->InstanceNumber) + ":" + textureinfo[i].name);
2286 }
2287}
2288
2289void TextureManager::CopyTexture(Ogre::TexturePtr source, Ogre::TexturePtr destination)
2290{
2291 //copy a source texture onto a destination texture using the full sizes
2292
2293 Ogre::Box srcbox (0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
2294 Ogre::Box dstbox (0, 0, 0, destination->getWidth(), destination->getHeight(), destination->getDepth());
2295
2296 CopyTexture(source, destination, srcbox, dstbox);
2297}
2298
2299void TextureManager::CopyTexture(Ogre::TexturePtr source, Ogre::TexturePtr destination, const Ogre::Box &srcBox, const Ogre::Box &dstBox)
2300{
2301 //copy a source texture onto a destination texture using specified sizes
2302
2303 try
2304 {
2305 //if dimensions are the same, use standard copy method to prevent
2306 //some crashes on systems with small npot textures
2307 //note - this currently doesn't work properly on DirectX, needs fixing
2308 if (srcBox.getWidth() == source->getWidth() &&
2309 srcBox.getHeight() == source->getHeight() &&
2310 dstBox.getWidth() == destination->getWidth() &&
2311 dstBox.getHeight() == destination->getHeight() &&
2312 sbs->mRoot->getRenderSystem()->getName() != "Direct3D9 Rendering Subsystem" &&
2313 sbs->mRoot->getRenderSystem()->getName() != "Direct3D11 Rendering Subsystem")
2314 {
2315 source->copyToTexture(destination);
2316 return;
2317 }
2318
2319 Ogre::HardwarePixelBufferSharedPtr buffer = source->getBuffer();
2320
2321 if (sbs->mRoot->getRenderSystem()->getName() == "Direct3D11 Rendering Subsystem")
2322 {
2323 //old method:
2324 buffer->lock(srcBox, Ogre::HardwareBuffer::HBL_READ_ONLY);
2325 const Ogre::PixelBox& pb = buffer->getCurrentLock();
2326 destination->getBuffer()->blitFromMemory(pb, dstBox);
2327 buffer->unlock();
2328 }
2329 else
2330 {
2331 //new method:
2332 destination->getBuffer()->blit(buffer, srcBox, dstBox);
2333 }
2334 }
2335 catch (Ogre::Exception& e)
2336 {
2337 ReportError("Error copying texture\n" + e.getDescription());
2338 return;
2339 }
2340}
2341
2343{
2344 for (size_t i = 0; i < textureboxes.size(); i++)
2345 {
2346 free(textureboxes[i].buffer);
2347
2348 if (textureboxes[i].box)
2349 delete textureboxes[i].box;
2350 }
2351 textureboxes.clear();
2352}
2353
2355{
2356 PlanarRotate = value;
2357}
2358
2360{
2361 return PlanarRotate;
2362}
2363
2364void TextureManager::EnableShadows(const std::string &material_name, bool value)
2365{
2366 //enable shadows
2367
2368 Ogre::MaterialPtr mMat = GetMaterialByName(material_name);
2369 if (mMat)
2370 mMat->setReceiveShadows(value);
2371}
2372
2373void TextureManager::SetCulling(const std::string &material_name, int mode)
2374{
2375 //sets culling mode on a material
2376 //if mode is 0, do not cull (both sides visible)
2377 //if mode is 1, cull anticlockwise (SBS default)
2378 //if mode is 2, cull clockwise (Ogre default)
2379
2380 //get original material
2381 Ogre::MaterialPtr mat = GetMaterialByName(material_name);
2382
2383 if (mat)
2384 {
2385 if (mode == 0)
2386 mat->setCullingMode(Ogre::CullingMode::CULL_NONE);
2387 if (mode == 1)
2388 mat->setCullingMode(Ogre::CullingMode::CULL_ANTICLOCKWISE);
2389 if (mode == 2)
2390 mat->setCullingMode(Ogre::CullingMode::CULL_CLOCKWISE);
2391 }
2392 else
2393 ReportError("SetCulling: Material " + material_name + " not found");
2394}
2395
2397{
2398 size_t result = 0;
2399
2400 for (size_t i = 0; i < textureinfo.size(); i++)
2401 {
2402 result += textureinfo[i].tex_size + textureinfo[i].mat_size;
2403 }
2404
2405 return result;
2406}
2407
2408}
std::string Name
Definition object.h:52
virtual bool ReportError(const std::string &message)
Definition object.cpp:84
virtual void Report(const std::string &message)
Definition object.cpp:78
void SetName(const std::string &name)
Definition object.cpp:72
Ogre::Root * mRoot
Definition sbs.h:137
Real AmbientG
Definition sbs.h:426
Real AmbientR
Definition sbs.h:426
std::string GetMountPath(std::string filename, std::string &newfilename)
Definition sbs.cpp:3335
void CacheFilename(const std::string &filename, const std::string &result)
Definition sbs.cpp:3369
Utility * GetUtility()
Definition sbs.cpp:4611
void ResetLighting()
Definition sbs.cpp:3388
int InstanceNumber
Definition sbs.h:197
bool GetConfigBool(const std::string &key, bool default_value)
Definition sbs.cpp:3243
int GetConfigInt(const std::string &key, int default_value)
Definition sbs.cpp:3232
void SetLighting(Real red=1.0, Real green=1.0, Real blue=1.0)
Definition sbs.cpp:3378
Real AmbientB
Definition sbs.h:426
std::string VerifyFile(const std::string &filename)
Definition sbs.cpp:2916
bool Verbose
Definition sbs.h:186
bool LoadTextureCropped(const std::string &filename, const std::string &name, int x, int y, int width, int height, Real widthmult, Real heightmult, bool enable_force=false, bool force_mode=false)
Definition texture.cpp:374
bool LoadTexture(const std::string &filename, const std::string &name, Real widthmult, Real heightmult, bool enable_force=false, bool force_mode=false, int mipmaps=-1, bool use_alpha_color=false, Ogre::ColourValue alpha_color=Ogre::ColourValue::Black)
Definition texture.cpp:123
void CopyTexture(Ogre::TexturePtr source, Ogre::TexturePtr destination)
Definition texture.cpp:2289
bool ScrollTexture(const std::string &name, Real x_offset, Real y_offset)
Definition texture.cpp:505
std::vector< Real > widthscale
Definition texture.h:116
void EnableShadows(const std::string &material_name, bool value)
Definition texture.cpp:2364
bool UnloadMaterial(const std::string &name, const std::string &group)
Definition texture.cpp:359
std::string mainnegtex
Definition texture.h:112
bool GetTextureForce(const std::string &texture, bool &enable_force, bool &force_mode)
Definition texture.cpp:1017
Ogre::MaterialPtr CreateMaterial(const std::string &name, const std::string &path)
Definition texture.cpp:2178
std::vector< std::string > OldMapVerts3
Definition texture.h:146
bool GetTextureImage(Ogre::TexturePtr texture)
Definition texture.cpp:2069
void DecrementMaterialCount()
Definition texture.cpp:2093
bool RotateTexture(const std::string &name, Real angle)
Definition texture.cpp:447
bool AddTextToTexture(const std::string &origname, const std::string &name, const std::string &font_filename, Real font_size, const std::string &text, int x1, int y1, int x2, int y2, const std::string &h_align, const std::string &v_align, int ColorR, int ColorG, int ColorB, bool enable_force=false, bool force_mode=false)
Definition texture.cpp:658
void SetAutoSize(bool x, bool y)
Definition texture.cpp:1075
void ProcessTextureFlip(Real tw, Real th)
Definition texture.cpp:959
void SetTextureMapping(int vertindex1, Vector2 uv1, int vertindex2, Vector2 uv2, int vertindex3, Vector2 uv3)
Definition texture.cpp:1501
bool ScrollAnimTexture(const std::string &name, Real x_speed, Real y_speed)
Definition texture.cpp:534
std::string ListTextures(bool show_filename=false)
Definition texture.cpp:1600
std::vector< TexturePixelBox > textureboxes
Definition texture.h:175
TextureManager(Object *parent)
Definition texture.cpp:41
std::string sidenegtex
Definition texture.h:112
std::string prev_material
Definition texture.h:178
void GetAutoSize(bool &x, bool &y)
Definition texture.cpp:1082
void SaveTexture(Ogre::TexturePtr texture, const std::string &filename)
Definition texture.cpp:2060
Ogre::TextureUnitState * GetTextureUnitState(Ogre::MaterialPtr mMat)
Definition texture.cpp:2251
std::vector< std::string > MapVerts1
Definition texture.h:141
bool TransformTexture(const std::string &name, const std::string &type, const std::string &wave_type, Real base, Real frequency, Real phase, Real amplitude)
Definition texture.cpp:592
std::vector< int > MapIndex
Definition texture.h:137
bool LoadAnimatedTexture(std::vector< std::string > filenames, const std::string &name, Real duration, Real widthmult, Real heightmult, bool enable_force=false, bool force_mode=false, int mipmaps=-1, bool use_alpha_color=false, Ogre::ColourValue alpha_color=Ogre::ColourValue::Black)
Definition texture.cpp:157
void SetPlanarRotate(bool value)
Definition texture.cpp:2354
Real AutoSize(Real n1, Real n2, bool iswidth, Real offset, bool enable_force, bool force_mode)
Definition texture.cpp:1052
std::vector< Ogre::TexturePtr > manual_textures
Definition texture.h:163
std::vector< std::string > OldMapVerts2
Definition texture.h:145
void SetTextureMapping2(const std::string &x1, const std::string &y1, const std::string &z1, Vector2 uv1, const std::string &x2, const std::string &y2, const std::string &z2, Vector2 uv2, const std::string &x3, const std::string &y3, const std::string &z3, Vector2 uv3)
Definition texture.cpp:1517
bool GetTextureMapping(PolyArray &vertices, Vector3 &v1, Vector3 &v2, Vector3 &v3, int &direction)
Definition texture.cpp:1109
void GetPlanarMapping(bool &flat, bool &FlipX, bool &FlipY, bool &FlipZ, bool &rotate)
Definition texture.cpp:1488
bool LoadMaterial(const std::string &filename, const std::string &name, Real widthmult, Real heightmult, bool enable_force=false, bool force_mode=false)
Definition texture.cpp:280
std::string bottomtex
Definition texture.h:112
void IncrementMaterialCount()
Definition texture.cpp:2088
Ogre::TexturePtr GetTextureByName(const std::string &name, const std::string &group="General")
Definition texture.cpp:2268
std::vector< Vector2 > OldMapUV
Definition texture.h:140
void SetCulling(const std::string &material_name, int mode=1)
Definition texture.cpp:2373
size_t GetMemoryUsage()
Definition texture.cpp:2396
bool UnloadTexture(const std::string &name, const std::string &group)
Definition texture.cpp:344
bool SetTextureInfo(int index, TextureInfo &info)
Definition texture.cpp:1637
bool GetTextureInfo(int index, TextureInfo &info)
Definition texture.cpp:1626
void DecrementTextureCount()
Definition texture.cpp:2083
bool RotateAnimTexture(const std::string &name, Real speed)
Definition texture.cpp:476
std::vector< std::string > OldMapVerts1
Definition texture.h:144
Vector2 CalculateSizing(const std::string &texture, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, int direction, Real tw, Real th)
Definition texture.cpp:1089
void SetTextureFlip(int mainneg, int mainpos, int sideneg, int sidepos, int top, int bottom)
Definition texture.cpp:1569
std::vector< Vector2 > MapUV
Definition texture.h:139
void ResetTextureMapping(bool todefaults=false)
Definition texture.cpp:1444
bool AddTextureOverlay(const std::string &orig_texture, const std::string &overlay_texture, const std::string &name, int x, int y, int width, int height, Real widthmult, Real heightmult, bool enable_force=false, bool force_mode=false)
Definition texture.cpp:814
bool WriteToTexture(const std::string &str, Ogre::TexturePtr destTexture, int destLeft, int destTop, int destRight, int destBottom, Ogre::FontPtr font, const Ogre::ColourValue &color, char justify='l', char vert_justify='t', bool wordwrap=true)
Definition texture.cpp:1809
std::vector< std::string > MapVerts2
Definition texture.h:142
void SetPlanarMapping(bool flat, bool FlipX, bool FlipY, bool FlipZ, bool rotate)
Definition texture.cpp:1467
void SetTextureOverride(const std::string &mainneg, const std::string &mainpos, const std::string &sideneg, const std::string &sidepos, const std::string &top, const std::string &bottom)
Definition texture.cpp:1587
std::string GetTextureMaterial(const std::string &name, bool &result, bool report=true, const std::string &polygon_name="")
Definition texture.cpp:906
bool LoadAlphaBlendTexture(const std::string &filename, const std::string &specular_filename, const std::string &blend_filename, const std::string &name, bool spherical, Real widthmult, Real heightmult, bool enable_force=false, bool force_mode=false, int mipmaps=-1, bool use_alpha_color=false, Ogre::ColourValue alpha_color=Ogre::ColourValue::Black)
Definition texture.cpp:221
void RegisterTextureInfo(const std::string &name, const std::string &material_name, const std::string &filename, Real widthmult, Real heightmult, bool enable_force, bool force_mode, size_t tex_size, size_t mat_size)
Definition texture.cpp:303
void DecrementTextureUsage(const std::string &name)
Definition texture.cpp:1660
std::vector< int > OldMapIndex
Definition texture.h:138
bool ScaleTexture(const std::string &name, Real x_scale, Real y_scale)
Definition texture.cpp:563
std::vector< TextureInfo > textureinfo
Definition texture.h:162
Ogre::TexturePtr loadChromaKeyedTexture(const std::string &filename, const std::string &resGroup, const std::string &name, const Ogre::ColourValue &keyCol=Ogre::ColourValue::Black, int numMipmaps=-1, Real threshold=0.003)
Definition texture.cpp:1693
std::vector< std::string > MapVerts3
Definition texture.h:143
std::vector< Real > heightscale
Definition texture.h:117
bool UnregisterTextureInfo(std::string name, std::string material_name="")
Definition texture.cpp:328
std::string toptex
Definition texture.h:112
void IncrementTextureUsage(const std::string &name)
Definition texture.cpp:1648
void IncrementTextureCount()
Definition texture.cpp:2078
Ogre::TextureUnitState * BindTextureToMaterial(Ogre::MaterialPtr mMat, std::string texture_name, bool has_alpha)
Definition texture.cpp:2235
std::string mainpostex
Definition texture.h:112
Ogre::MaterialPtr GetMaterialByName(const std::string &name, const std::string &group="General")
Definition texture.cpp:2224
void EnableLighting(const std::string &material_name, bool value)
Definition texture.cpp:2207
bool GetTextureTiling(const std::string &texture, Real &tw, Real &th)
Definition texture.cpp:1002
std::string GetTextureName(Ogre::MaterialPtr mMat)
Definition texture.cpp:2257
std::string sidepostex
Definition texture.h:112
Vector2 GetExtents(PolyArray &varray, int coord, bool flip_z=false)
Definition utility.cpp:49
Plane ComputePlane(PolyArray &vertices, bool flip_normal=true)
Definition utility.cpp:504
Ogre::Vector3 Vector3
Definition globals.h:58
Ogre::Real Real
Definition globals.h:57
Ogre::Plane Plane
Definition globals.h:65
Ogre::Vector2 Vector2
Definition globals.h:59
Ogre::Degree Degree
Definition globals.h:61
std::vector< Vector3 > PolyArray
Definition sbs.h:118
void ReplaceAll(std::string &string, const std::string &original, const std::string &replacement)
Definition globals.cpp:201
int ToInt(const std::string &string)
Definition globals.cpp:402
void SetCase(std::string &string, bool uppercase)
Definition globals.cpp:172
std::string ToString(int number)
Definition globals.cpp:279
Real ToFloat(const std::string &string)
Definition globals.cpp:397
void TrimString(std::string &string)
Definition globals.cpp:188
std::string TrimStringCopy(std::string string)
Definition globals.cpp:194