+
+void MeshCollector::append(const TileLayer &layer,
+ const video::S3DVertex *vertices, u32 numVertices,
+ const u16 *indices, u32 numIndices,
+ v3f pos, video::SColor c, u8 light_source, u8 layernum,
+ bool use_scale)
+{
+ if (numIndices > 65535) {
+ dstream << "FIXME: MeshCollector::append() called with numIndices="
+ << numIndices << " (limit 65535)" << std::endl;
+ return;
+ }
+ std::vector<PreMeshBuffer> *buffers = &prebuffers[layernum];
+
+ PreMeshBuffer *p = NULL;
+ for (PreMeshBuffer &pp : *buffers) {
+ if (pp.layer == layer && pp.indices.size() + numIndices <= 65535) {
+ p = &pp;
+ break;
+ }
+ }
+
+ if (p == NULL) {
+ PreMeshBuffer pp;
+ pp.layer = layer;
+ buffers->push_back(pp);
+ p = &(*buffers)[buffers->size() - 1];
+ }
+
+ f32 scale = 1.0;
+ if (use_scale)
+ scale = 1.0 / layer.scale;
+
+ video::SColor original_c = c;
+ u32 vertex_count;
+ if (m_use_tangent_vertices) {
+ vertex_count = p->tangent_vertices.size();
+ for (u32 i = 0; i < numVertices; i++) {
+ if (!light_source) {
+ c = original_c;
+ applyFacesShading(c, vertices[i].Normal);
+ }
+ video::S3DVertexTangents vert(vertices[i].Pos + pos,
+ vertices[i].Normal, c, scale * vertices[i].TCoords);
+ p->tangent_vertices.push_back(vert);
+ }
+ } else {
+ vertex_count = p->vertices.size();
+ for (u32 i = 0; i < numVertices; i++) {
+ if (!light_source) {
+ c = original_c;
+ applyFacesShading(c, vertices[i].Normal);
+ }
+ video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal, c,
+ scale * vertices[i].TCoords);
+ p->vertices.push_back(vert);
+ }
+ }
+
+ for (u32 i = 0; i < numIndices; i++) {
+ u32 j = indices[i] + vertex_count;
+ p->indices.push_back(j);
+ }
+}
+
+void MeshCollector::applyTileColors()
+{
+ if (m_use_tangent_vertices)
+ for (auto &prebuffer : prebuffers) {
+ for (PreMeshBuffer &pmb : prebuffer) {
+ video::SColor tc = pmb.layer.color;
+ if (tc == video::SColor(0xFFFFFFFF))
+ continue;
+ for (video::S3DVertexTangents &tangent_vertex : pmb.tangent_vertices) {
+ video::SColor *c = &tangent_vertex.Color;
+ c->set(c->getAlpha(), c->getRed() * tc.getRed() / 255,
+ c->getGreen() * tc.getGreen() / 255,
+ c->getBlue() * tc.getBlue() / 255);
+ }
+ }
+ }
+ else
+ for (auto &prebuffer : prebuffers) {
+ for (PreMeshBuffer &pmb : prebuffer) {
+ video::SColor tc = pmb.layer.color;
+ if (tc == video::SColor(0xFFFFFFFF))
+ continue;
+ for (video::S3DVertex &vertex : pmb.vertices) {
+ video::SColor *c = &vertex.Color;
+ c->set(c->getAlpha(), c->getRed() * tc.getRed() / 255,
+ c->getGreen() * tc.getGreen() / 255,
+ c->getBlue() * tc.getBlue() / 255);
+ }
+ }
+ }
+}
+
+video::SColor encode_light(u16 light, u8 emissive_light)
+{
+ // Get components
+ u32 day = (light & 0xff);
+ u32 night = (light >> 8);
+ // Add emissive light
+ night += emissive_light * 2.5f;
+ if (night > 255)
+ night = 255;
+ // Since we don't know if the day light is sunlight or
+ // artificial light, assume it is artificial when the night
+ // light bank is also lit.
+ if (day < night)
+ day = 0;
+ else
+ day = day - night;
+ u32 sum = day + night;
+ // Ratio of sunlight:
+ u32 r;
+ if (sum > 0)
+ r = day * 255 / sum;
+ else
+ r = 0;
+ // Average light:
+ float b = (day + night) / 2;
+ return video::SColor(r, b, b, b);
+}