TDME2  1.9.200
GenerateBillboardLOD.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 #include <string>
5 
6 #include <tdme/tdme.h>
9 #include <tdme/engine/Texture.h>
11 #include <tdme/engine/Color4.h>
12 #include <tdme/engine/model/Face.h>
16 #include <tdme/engine/model/Node.h>
20 #include <tdme/engine/Engine.h>
21 #include <tdme/engine/LODObject.h>
22 #include <tdme/engine/Object.h>
24 #include <tdme/math/Math.h>
25 #include <tdme/math/Vector2.h>
26 #include <tdme/math/Vector3.h>
28 #include <tdme/utilities/Console.h>
32 
34 
35 using std::make_unique;
36 using std::string;
37 using std::unique_ptr;
38 
56 using tdme::math::Math;
64 
65 Model* GenerateBillboardLOD::generate(
66  Model* model,
67  const string& pathName,
68  const string& fileName
69 ) {
70  auto textureFileName = Tools::removeFileExtension(fileName) + ".png";
71  auto boundingBox = model->getBoundingBox();
72  //
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  float maxAxisDimension = Tools::computeMaxAxisDimension(boundingBox);
92  if (maxAxisDimension < Math::EPSILON) maxAxisDimension = 1.0f;
93  //
94  auto camera = osEngine->getCamera();
95  camera->setLookAt(boundingBox->getCenter());
96  camera->setLookFrom(boundingBox->getCenter().clone().add(Vector3(0.0f, 0.0f, boundingBox->getCenter().getZ() + maxAxisDimension * 1.25f)));
97  //
98  osEngine->addEntity(new Object("model", model));
99  //
100  osEngine->display();
101  //
102  osEngine->makeScreenshot(pathName, textureFileName, false);
103  //
104  osEngine->dispose();
105  }
106 
107  //
108  auto minX = 10000;
109  auto maxX = -1;
110  auto minY = 10000;
111  auto maxY = -1;
112  auto texture = TextureReader::read(pathName, textureFileName, false, false);
113  auto textureTextureData = texture->getRGBTextureData();
114  for (auto y = 0; y < texture->getTextureHeight(); y++) {
115  for (auto x = 0; x < texture->getTextureWidth(); x++) {
116  auto alpha = textureTextureData.get(y * texture->getTextureWidth() * 4 + x * 4 + 3);
117  if (alpha < 5) continue;
118  minX = Math::min(minX, x);
119  maxX = Math::max(maxX, x);
120  minY = Math::min(minY, y);
121  maxY = Math::max(maxY, y);
122  }
123  }
124 
125  // crop texture
126  auto croppedTextureWidth = maxX - minX;
127  auto croppedTextureHeight = maxY - minY;
128  auto croppedTextureByteBuffer = ByteBuffer(croppedTextureWidth * croppedTextureHeight * 4);
129  for (auto y = minY; y < maxY; y++) {
130  for (auto x = minX; x < maxX; x++) {
131  auto pixelOffset = y * texture->getTextureWidth() * 4 + x * 4;
132  auto red = textureTextureData.get(pixelOffset + 0);
133  auto green = textureTextureData.get(pixelOffset + 1);
134  auto blue = textureTextureData.get(pixelOffset + 2);
135  auto alpha = textureTextureData.get(pixelOffset + 3);
136  croppedTextureByteBuffer.put(red);
137  croppedTextureByteBuffer.put(green);
138  croppedTextureByteBuffer.put(blue);
139  croppedTextureByteBuffer.put(alpha);
140  }
141  }
142  //
143  texture->releaseReference();
144 
145  //
146  {
147  auto croppedTexture =
148  unique_ptr<
149  Texture,
150  decltype([](Texture* texture){ texture->releaseReference(); })
151  >(
152  new Texture(
153  "tdme.engine.croppedtexture",
154  Texture::TEXTUREDEPTH_RGBA,
155  Texture::TEXTUREFORMAT_RGBA,
156  croppedTextureWidth,
157  croppedTextureHeight,
158  croppedTextureWidth,
159  croppedTextureHeight,
160  Texture::TEXTUREFORMAT_RGBA,
161  croppedTextureByteBuffer
162  )
163  );
164  croppedTexture->acquireReference();
165  auto scaledTexture = unique_ptr<Texture, decltype([](Texture* texture){ texture->releaseReference(); })>(TextureReader::scale(croppedTexture.get(), 1024, 1024));
166  // save
167  PNGTextureWriter::write(scaledTexture.get(), pathName, textureFileName, false, false);
168  }
169 
170  // create model
171  auto left = boundingBox->getMin().getX();
172  auto right = boundingBox->getMax().getX();
173  auto top = boundingBox->getMin().getY();
174  auto bottom = boundingBox->getMax().getY();
175  auto depth = boundingBox->getCenter().getZ();
176  auto modelId = Tools::removeFileExtension(textureFileName) + ".tm";
177  auto billboard = make_unique<Model>(modelId, modelId, UpVector::Y_UP, RotationOrder::ZYX, nullptr);
178  //
179  auto billboardMaterial = make_unique<Material>("billboard");
180  billboardMaterial->setSpecularMaterialProperties(make_unique<SpecularMaterialProperties>().release());
181  billboardMaterial->getSpecularMaterialProperties()->setSpecularColor(Color4(0.0f, 0.0f, 0.0f, 1.0f));
182  billboardMaterial->getSpecularMaterialProperties()->setDiffuseTexture(pathName, textureFileName);
183  billboardMaterial->getSpecularMaterialProperties()->setDiffuseTextureMaskedTransparency(true);
184  //
185  auto billboardNode = make_unique<Node>(billboard.get(), nullptr, "billboard", "billboard");
186  vector<Vector3> billboardVertices;
187  billboardVertices.emplace_back(left, top, depth);
188  billboardVertices.emplace_back(left, bottom, depth);
189  billboardVertices.emplace_back(right, bottom, depth);
190  billboardVertices.emplace_back(right, top, depth);
191  vector<Vector3> billboardNormals;
192  billboardNormals.emplace_back(0.0f, 1.0f, 0.0f);
193  vector<Vector2> billboardTextureCoordinates;
194  billboardTextureCoordinates.emplace_back(0.0f, 1.0f);
195  billboardTextureCoordinates.emplace_back(0.0f, 0.0f);
196  billboardTextureCoordinates.emplace_back(1.0f, 0.0f);
197  billboardTextureCoordinates.emplace_back(1.0f, 1.0f);
198  vector<Face> billboardFacesGround;
199  billboardFacesGround.emplace_back(billboardNode.get(), 0, 1, 2, 0, 0, 0, 0, 1, 2);
200  billboardFacesGround.emplace_back(billboardNode.get(), 2, 3, 0, 0, 0, 0, 2, 3, 0);
201  FacesEntity billboardNodeFacesEntity(billboardNode.get(), "billboard.facesentity");
202  billboardNodeFacesEntity.setMaterial(billboardMaterial.get());
203  vector<FacesEntity> billboardNodeFacesEntities;
204  billboardNodeFacesEntity.setFaces(billboardFacesGround);
205  billboardNodeFacesEntities.push_back(billboardNodeFacesEntity);
206  billboardNode->setVertices(billboardVertices);
207  billboardNode->setNormals(billboardNormals);
208  billboardNode->setTextureCoordinates(billboardTextureCoordinates);
209  billboardNode->setFacesEntities(billboardNodeFacesEntities);
210  //
211  billboard->getNodes()["billboard"] = billboardNode.get();
212  billboard->getSubNodes()["billboard"] = billboardNode.get();
213  billboardNode.release();
214  //
215  billboard->getMaterials()[billboardMaterial->getId()] = billboardMaterial.get();
216  billboardMaterial.release();
217  //
218  ModelTools::prepareForIndexedRendering(billboard.get());
219 
220  //
221  TMWriter::write(
222  billboard.get(),
223  pathName,
224  fileName
225  );
226 
227  //
228  return billboard.release();
229 }
230 
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
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 billboard 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
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