TDME2  1.9.200
GenerateImposterLOD.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 #include <string>
5 #include <vector>
6 
7 #include <tdme/tdme.h>
10 #include <tdme/engine/Texture.h>
12 #include <tdme/engine/Color4.h>
13 #include <tdme/engine/model/Face.h>
17 #include <tdme/engine/model/Node.h>
21 #include <tdme/engine/Engine.h>
22 #include <tdme/engine/LODObject.h>
23 #include <tdme/engine/Object.h>
25 #include <tdme/math/Math.h>
26 #include <tdme/math/Vector2.h>
27 #include <tdme/math/Vector3.h>
29 #include <tdme/utilities/Console.h>
33 
35 
36 using std::string;
37 using std::unique_ptr;
38 using std::vector;
39 
57 using tdme::math::Math;
65 
66 void GenerateImposterLOD::generate(
67  Model* model,
68  const string& pathName,
69  const string& fileName,
70  int billboardCount,
71  vector<string>& imposterModelFileNames,
72  vector<Model*>& imposterModels
73 ) {
74  auto osEngine = unique_ptr<Engine>(Engine::createOffScreenInstance(4096, 4096, true, true, false));
75  osEngine->setPartition(new SimplePartition());
76  osEngine->setSceneColor(Color4(0.0f, 0.0f, 0.0f, 0.0f));
77  //
78  auto light = osEngine->getLightAt(0);
79  light->setAmbient(Color4(1.0f, 1.0f, 1.0f, 1.0f));
80  light->setDiffuse(Color4(0.5f, 0.5f, 0.5f, 1.0f));
81  light->setSpecular(Color4(1.0f, 1.0f, 1.0f, 1.0f));
82  light->setPosition(Vector4(0.0f, 20000.0f, 0.0f, 0.0f));
83  light->setSpotDirection(Vector3(0.0f, 0.0f, 0.0f).sub(Vector3(light->getPosition().getX(), light->getPosition().getY(), light->getPosition().getZ())));
84  light->setConstantAttenuation(0.5f);
85  light->setLinearAttenuation(0.0f);
86  light->setQuadraticAttenuation(0.0f);
87  light->setSpotExponent(0.0f);
88  light->setSpotCutOff(180.0f);
89  light->setEnabled(true);
90  // do a feasible scale
91  auto boundingBox = model->getBoundingBox();
92  float maxAxisDimension = Tools::computeMaxAxisDimension(boundingBox);
93  if (maxAxisDimension < Math::EPSILON) maxAxisDimension = 1.0f;
94 
95  //
96  auto camera = osEngine->getCamera();
97  camera->setLookAt(boundingBox->getCenter());
98  camera->setLookFrom(boundingBox->getCenter().clone().add(Vector3(0.0f, 0.0f, boundingBox->getCenter().getZ() + maxAxisDimension * 1.25f)));
99 
100  //
101  auto entity = new Object("model", model);
102  entity->addRotation(Vector3(0.0f, 1.0f, 0.0f), 0.0f);
103  osEngine->addEntity(entity);
104 
105  //
106  imposterModels.resize(billboardCount);
107  imposterModelFileNames.resize(billboardCount);
108 
109  //
110  for (auto i = 0; i < billboardCount; i++) {
111  //
112  auto yRotation = static_cast<float>(i) * (360.0f / static_cast<float>(billboardCount));
113  entity->setRotationAngle(0, static_cast<float>(yRotation));
114  entity->update();
115 
116  //
117  osEngine->display();
118  //
119  auto modelId = Tools::removeFileExtension(fileName) + "-y" + to_string(static_cast<int>(yRotation)) + "deg";
120  auto modelFileName = modelId + ".tm";
121  auto textureFileName = Tools::removeFileExtension(fileName) + "-y" + to_string(static_cast<int>(yRotation)) + "deg.png";
122  osEngine->makeScreenshot(pathName, textureFileName, false);
123 
124  //
125  auto minX = 10000;
126  auto maxX = -1;
127  auto minY = 10000;
128  auto maxY = -1;
129  auto texture = unique_ptr<Texture, decltype([](Texture* texture){ texture->releaseReference(); })>(TextureReader::read(pathName, textureFileName, false, false));
130  auto textureTextureData = texture->getRGBTextureData();
131  for (auto y = 0; y < texture->getTextureHeight(); y++) {
132  for (auto x = 0; x < texture->getTextureWidth(); x++) {
133  auto alpha = textureTextureData.get(y * texture->getTextureWidth() * 4 + x * 4 + 3);
134  if (alpha < 5) continue;
135  minX = Math::min(minX, x);
136  maxX = Math::max(maxX, x);
137  minY = Math::min(minY, y);
138  maxY = Math::max(maxY, y);
139  }
140  }
141 
142  // crop texture
143  auto croppedTextureWidth = maxX - minX;
144  auto croppedTextureHeight = maxY - minY;
145  auto croppedTextureByteBuffer = ByteBuffer(croppedTextureWidth * croppedTextureHeight * 4);
146  for (auto y = minY; y < maxY; y++) {
147  for (auto x = minX; x < maxX; x++) {
148  auto pixelOffset = y * texture->getTextureWidth() * 4 + x * 4;
149  auto red = textureTextureData.get(pixelOffset + 0);
150  auto green = textureTextureData.get(pixelOffset + 1);
151  auto blue = textureTextureData.get(pixelOffset + 2);
152  auto alpha = textureTextureData.get(pixelOffset + 3);
153  croppedTextureByteBuffer.put(red);
154  croppedTextureByteBuffer.put(green);
155  croppedTextureByteBuffer.put(blue);
156  croppedTextureByteBuffer.put(alpha);
157  }
158  }
159 
160  //
161  {
162  auto croppedTexture =
163  unique_ptr<
164  Texture,
165  decltype([](Texture* texture){ texture->releaseReference(); })
166  >(
167  new Texture(
168  "tdme.engine.croppedtexture",
169  Texture::TEXTUREDEPTH_RGBA,
170  Texture::TEXTUREFORMAT_RGBA,
171  croppedTextureWidth,
172  croppedTextureHeight,
173  croppedTextureWidth,
174  croppedTextureHeight,
175  Texture::TEXTUREFORMAT_RGBA,
176  croppedTextureByteBuffer
177  )
178  );
179  croppedTexture->acquireReference();
180  auto scaledTexture = unique_ptr<Texture, decltype([](Texture* texture){ texture->releaseReference(); })>(TextureReader::scale(croppedTexture.get(), 1024, 1024));
181  // save
182  PNGTextureWriter::write(scaledTexture.get(), pathName, textureFileName, false, false);
183  }
184 
185  // create model
186  auto left = boundingBox->getMin().getX();
187  auto right = boundingBox->getMax().getX();
188  auto top = boundingBox->getMin().getY();
189  auto bottom = boundingBox->getMax().getY();
190  auto depth = boundingBox->getCenter().getZ();
191  //
192  auto billboard = make_unique<Model>(modelId, modelId, UpVector::Y_UP, RotationOrder::ZYX, nullptr);
193  //
194  auto billboardMaterial = make_unique<Material>("billboard");
195  billboardMaterial->setSpecularMaterialProperties(make_unique<SpecularMaterialProperties>().release());
196  billboardMaterial->getSpecularMaterialProperties()->setSpecularColor(Color4(0.0f, 0.0f, 0.0f, 1.0f));
197  billboardMaterial->getSpecularMaterialProperties()->setDiffuseTexture(pathName, textureFileName);
198  billboardMaterial->getSpecularMaterialProperties()->setDiffuseTextureMaskedTransparency(true);
199  //
200  auto billboardNode = make_unique<Node>(billboard.get(), nullptr, "billboard", "billboard");
201  vector<Vector3> billboardVertices;
202  billboardVertices.emplace_back(left, top, depth);
203  billboardVertices.emplace_back(left, bottom, depth);
204  billboardVertices.emplace_back(right, bottom, depth);
205  billboardVertices.emplace_back(right, top, depth);
206  vector<Vector3> billboardNormals;
207  billboardNormals.emplace_back(0.0f, 1.0f, 0.0f);
208  vector<Vector2> billboardTextureCoordinates;
209  billboardTextureCoordinates.emplace_back(0.0f, 1.0f);
210  billboardTextureCoordinates.emplace_back(0.0f, 0.0f);
211  billboardTextureCoordinates.emplace_back(1.0f, 0.0f);
212  billboardTextureCoordinates.emplace_back(1.0f, 1.0f);
213  vector<Face> billboardFacesGround;
214  billboardFacesGround.emplace_back(billboardNode.get(), 0, 1, 2, 0, 0, 0, 0, 1, 2);
215  billboardFacesGround.emplace_back(billboardNode.get(), 2, 3, 0, 0, 0, 0, 2, 3, 0);
216  FacesEntity billboardNodeFacesEntity(billboardNode.get(), "billboard.facesentity");
217  billboardNodeFacesEntity.setMaterial(billboardMaterial.get());
218  vector<FacesEntity> billboardNodeFacesEntities;
219  billboardNodeFacesEntity.setFaces(billboardFacesGround);
220  billboardNodeFacesEntities.push_back(billboardNodeFacesEntity);
221  billboardNode->setVertices(billboardVertices);
222  billboardNode->setNormals(billboardNormals);
223  billboardNode->setTextureCoordinates(billboardTextureCoordinates);
224  billboardNode->setFacesEntities(billboardNodeFacesEntities);
225  billboard->getNodes()["billboard"] = billboardNode.get();
226  billboard->getSubNodes()["billboard"] = billboardNode.get();
227  billboardNode.release();
228  //
229  billboard->getMaterials()[billboardMaterial->getId()] = billboardMaterial.get();
230  billboardMaterial.release();
231  //
232  ModelTools::prepareForIndexedRendering(billboard.get());
233 
234  //
235  TMWriter::write(
236  billboard.get(),
237  pathName,
238  modelFileName
239  );
240 
241  //
242  imposterModels[i] = billboard.release();
243  imposterModelFileNames[i] = (pathName.empty() == false?pathName + "/":"") + modelFileName;
244  }
245 
246  //
247  osEngine->dispose();
248 }
Color 4 definition class.
Definition: Color4.h:18
Engine main class.
Definition: Engine.h:131
LOD object to be used with engine class.
Definition: LODObject.h:49
Object to be used with engine class.
Definition: Object.h:60
Bogus/Simple partition implementation.
Texture entity.
Definition: Texture.h:24
ByteBuffer getRGBTextureData()
Definition: Texture.h:253
uint16_t getTextureHeight() const
Definition: Texture.h:211
uint16_t getTextureWidth() const
Definition: Texture.h:218
Represents a model face, consisting of vertex, normal, tangent and bitangent vectors,...
Definition: Face.h:18
Node faces entity A node can have multiple entities containing faces and a applied material.
Definition: FacesEntity.h:23
void setMaterial(Material *material)
Set up the entity's material.
Definition: FacesEntity.h:67
void setFaces(const vector< Face > &faces)
Set up entity's faces.
Definition: FacesEntity.cpp:43
Represents a material.
Definition: Material.h:23
Representation of a 3D model.
Definition: Model.h:35
BoundingBox * getBoundingBox()
Definition: Model.cpp:150
Model node.
Definition: Node.h:32
Represents rotation orders of a model.
Definition: RotationOrder.h:23
Represents specular material properties.
Model up vector.
Definition: UpVector.h:20
Standard math functions.
Definition: Math.h:19
Vector2 class representing vector2 mathematical structure and operations with x, y components.
Definition: Vector2.h:20
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
Vector4 class representing vector4 mathematical structure and operations with x, y,...
Definition: Vector4.h:22
Generate imposter LOD utility class.
static const string removeFileExtension(const string &fileName)
Remove file extension, e.g.
Definition: Tools.cpp:554
static float computeMaxAxisDimension(BoundingBox *boundingBox)
Compute max axis dimension for given bounding box.
Definition: Tools.cpp:183
uint8_t get(int64_t position) const
Definition: Buffer.h:107
Byte buffer class.
Definition: ByteBuffer.h:27
Console class.
Definition: Console.h:29
Exception base class.
Definition: ExceptionBase.h:19
Model tools functions class.
Definition: ModelTools.h:42
virtual void releaseReference()
Releases a reference, thus decrementing the counter and delete it if reference counter is zero.
Definition: Reference.h:38
std::exception Exception
Exception base class.
Definition: Exception.h:18