#define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
#endif
+inline static void applyShadeFactor(video::SColor& color, float factor)
+{
+ color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
+ color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
+ color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255));
+}
+
+void applyFacesShading(video::SColor &color, const v3f &normal)
+{
+ /*
+ Some drawtypes have normals set to (0, 0, 0), this must result in
+ maximum brightness: shade factor 1.0.
+ Shade factors for aligned cube faces are:
+ +Y 1.000000 sqrt(1.0)
+ -Y 0.447213 sqrt(0.2)
+ +-X 0.670820 sqrt(0.45)
+ +-Z 0.836660 sqrt(0.7)
+ */
+ float x2 = normal.X * normal.X;
+ float y2 = normal.Y * normal.Y;
+ float z2 = normal.Z * normal.Z;
+ if (normal.Y < 0)
+ applyShadeFactor(color, 0.670820f * x2 + 0.447213f * y2 + 0.836660f * z2);
+ else if ((x2 > 1e-3) || (z2 > 1e-3))
+ applyShadeFactor(color, 0.670820f * x2 + 1.000000f * y2 + 0.836660f * z2);
+}
+
scene::IAnimatedMesh* createCubeMesh(v3f scale)
{
video::SColor c(255,255,255,255);
if (mesh == NULL)
return;
- core::aabbox3d<f32> bbox;
+ aabb3f bbox;
bbox.reset(0, 0, 0);
u32 mc = mesh->getMeshBufferCount();
if (mesh == NULL)
return;
- core::aabbox3d<f32> bbox;
+ aabb3f bbox;
bbox.reset(0, 0, 0);
u32 mc = mesh->getMeshBufferCount();
mesh->setBoundingBox(bbox);
}
+void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color)
+{
+ const u32 stride = getVertexPitchFromType(buf->getVertexType());
+ u32 vertex_count = buf->getVertexCount();
+ u8 *vertices = (u8 *) buf->getVertices();
+ for (u32 i = 0; i < vertex_count; i++)
+ ((video::S3DVertex *) (vertices + i * stride))->Color = color;
+}
void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
{
return;
u32 mc = mesh->getMeshBufferCount();
- for (u32 j = 0; j < mc; j++) {
- scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
- const u32 stride = getVertexPitchFromType(buf->getVertexType());
- u32 vertex_count = buf->getVertexCount();
- u8 *vertices = (u8 *)buf->getVertices();
- for (u32 i = 0; i < vertex_count; i++)
- ((video::S3DVertex *)(vertices + i * stride))->Color = color;
+ for (u32 j = 0; j < mc; j++)
+ setMeshBufferColor(mesh->getMeshBuffer(j), color);
+}
+
+void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolor)
+{
+ const u32 stride = getVertexPitchFromType(buf->getVertexType());
+ u32 vertex_count = buf->getVertexCount();
+ u8 *vertices = (u8 *) buf->getVertices();
+ for (u32 i = 0; i < vertex_count; i++) {
+ video::S3DVertex *vertex = (video::S3DVertex *) (vertices + i * stride);
+ video::SColor *vc = &(vertex->Color);
+ // Reset color
+ *vc = *buffercolor;
+ // Apply shading
+ applyFacesShading(*vc, vertex->Normal);
}
}
const video::SColor &colorY,
const video::SColor &colorZ)
{
- if(mesh == NULL)
+ if (mesh == NULL)
return;
-
+
u16 mc = mesh->getMeshBufferCount();
- for(u16 j=0; j<mc; j++)
- {
+ for (u16 j = 0; j < mc; j++) {
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
- video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
- u16 vc = buf->getVertexCount();
- for(u16 i=0; i<vc; i++)
- {
- f32 x = fabs(vertices[i].Normal.X);
- f32 y = fabs(vertices[i].Normal.Y);
- f32 z = fabs(vertices[i].Normal.Z);
- if(x >= y && x >= z)
- vertices[i].Color = colorX;
- else if(y >= z)
- vertices[i].Color = colorY;
+ const u32 stride = getVertexPitchFromType(buf->getVertexType());
+ u32 vertex_count = buf->getVertexCount();
+ u8 *vertices = (u8 *)buf->getVertices();
+ for (u32 i = 0; i < vertex_count; i++) {
+ video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
+ f32 x = fabs(vertex->Normal.X);
+ f32 y = fabs(vertex->Normal.Y);
+ f32 z = fabs(vertex->Normal.Z);
+ if (x >= y && x >= z)
+ vertex->Color = colorX;
+ else if (y >= z)
+ vertex->Color = colorY;
else
- vertices[i].Color = colorZ;
-
+ vertex->Color = colorZ;
}
}
}
-void rotateMeshXYby (scene::IMesh *mesh, f64 degrees)
-{
+void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal,
+ const video::SColor &color)
+{
+ if (!mesh)
+ return;
+
u16 mc = mesh->getMeshBufferCount();
- for(u16 j = 0; j < mc; j++)
- {
+ for (u16 j = 0; j < mc; j++) {
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
- video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
- u16 vc = buf->getVertexCount();
- for(u16 i = 0; i < vc; i++)
- {
- vertices[i].Pos.rotateXYBy(degrees);
+ const u32 stride = getVertexPitchFromType(buf->getVertexType());
+ u32 vertex_count = buf->getVertexCount();
+ u8 *vertices = (u8 *)buf->getVertices();
+ for (u32 i = 0; i < vertex_count; i++) {
+ video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
+ if (normal == vertex->Normal) {
+ vertex->Color = color;
+ }
}
}
}
-void rotateMeshXZby (scene::IMesh *mesh, f64 degrees)
-{
+void rotateMeshXYby(scene::IMesh *mesh, f64 degrees)
+{
u16 mc = mesh->getMeshBufferCount();
- for(u16 j = 0; j < mc; j++)
- {
+ for (u16 j = 0; j < mc; j++) {
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
- video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
- u16 vc = buf->getVertexCount();
- for(u16 i = 0; i < vc; i++)
- {
- vertices[i].Pos.rotateXZBy(degrees);
- }
+ const u32 stride = getVertexPitchFromType(buf->getVertexType());
+ u32 vertex_count = buf->getVertexCount();
+ u8 *vertices = (u8 *)buf->getVertices();
+ for (u32 i = 0; i < vertex_count; i++)
+ ((video::S3DVertex *)(vertices + i * stride))->Pos.rotateXYBy(degrees);
}
}
-void rotateMeshYZby (scene::IMesh *mesh, f64 degrees)
-{
+void rotateMeshXZby(scene::IMesh *mesh, f64 degrees)
+{
u16 mc = mesh->getMeshBufferCount();
- for(u16 j = 0; j < mc; j++)
- {
+ for (u16 j = 0; j < mc; j++) {
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
- video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
- u16 vc = buf->getVertexCount();
- for(u16 i = 0; i < vc; i++)
- {
- vertices[i].Pos.rotateYZBy(degrees);
- }
+ const u32 stride = getVertexPitchFromType(buf->getVertexType());
+ u32 vertex_count = buf->getVertexCount();
+ u8 *vertices = (u8 *)buf->getVertices();
+ for (u32 i = 0; i < vertex_count; i++)
+ ((video::S3DVertex *)(vertices + i * stride))->Pos.rotateXZBy(degrees);
+ }
+}
+
+void rotateMeshYZby(scene::IMesh *mesh, f64 degrees)
+{
+ u16 mc = mesh->getMeshBufferCount();
+ for (u16 j = 0; j < mc; j++) {
+ scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
+ const u32 stride = getVertexPitchFromType(buf->getVertexType());
+ u32 vertex_count = buf->getVertexCount();
+ u8 *vertices = (u8 *)buf->getVertices();
+ for (u32 i = 0; i < vertex_count; i++)
+ ((video::S3DVertex *)(vertices + i * stride))->Pos.rotateYZBy(degrees);
}
}
void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
-{
- int axisdir = facedir>>2;
+{
+ int axisdir = facedir >> 2;
facedir &= 0x03;
u16 mc = mesh->getMeshBufferCount();
- for(u16 j = 0; j < mc; j++)
- {
+ for (u16 j = 0; j < mc; j++) {
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
- video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
- u16 vc = buf->getVertexCount();
- for(u16 i=0; i<vc; i++)
- {
- switch (axisdir)
- {
- case 0:
- if(facedir == 1)
- vertices[i].Pos.rotateXZBy(-90);
- else if(facedir == 2)
- vertices[i].Pos.rotateXZBy(180);
- else if(facedir == 3)
- vertices[i].Pos.rotateXZBy(90);
- break;
- case 1: // z+
- vertices[i].Pos.rotateYZBy(90);
- if(facedir == 1)
- vertices[i].Pos.rotateXYBy(90);
- else if(facedir == 2)
- vertices[i].Pos.rotateXYBy(180);
- else if(facedir == 3)
- vertices[i].Pos.rotateXYBy(-90);
- break;
- case 2: //z-
- vertices[i].Pos.rotateYZBy(-90);
- if(facedir == 1)
- vertices[i].Pos.rotateXYBy(-90);
- else if(facedir == 2)
- vertices[i].Pos.rotateXYBy(180);
- else if(facedir == 3)
- vertices[i].Pos.rotateXYBy(90);
- break;
- case 3: //x+
- vertices[i].Pos.rotateXYBy(-90);
- if(facedir == 1)
- vertices[i].Pos.rotateYZBy(90);
- else if(facedir == 2)
- vertices[i].Pos.rotateYZBy(180);
- else if(facedir == 3)
- vertices[i].Pos.rotateYZBy(-90);
- break;
- case 4: //x-
- vertices[i].Pos.rotateXYBy(90);
- if(facedir == 1)
- vertices[i].Pos.rotateYZBy(-90);
- else if(facedir == 2)
- vertices[i].Pos.rotateYZBy(180);
- else if(facedir == 3)
- vertices[i].Pos.rotateYZBy(90);
- break;
- case 5:
- vertices[i].Pos.rotateXYBy(-180);
- if(facedir == 1)
- vertices[i].Pos.rotateXZBy(90);
- else if(facedir == 2)
- vertices[i].Pos.rotateXZBy(180);
- else if(facedir == 3)
- vertices[i].Pos.rotateXZBy(-90);
- break;
- default:
- break;
+ const u32 stride = getVertexPitchFromType(buf->getVertexType());
+ u32 vertex_count = buf->getVertexCount();
+ u8 *vertices = (u8 *)buf->getVertices();
+ for (u32 i = 0; i < vertex_count; i++) {
+ video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
+ switch (axisdir) {
+ case 0:
+ if (facedir == 1)
+ vertex->Pos.rotateXZBy(-90);
+ else if (facedir == 2)
+ vertex->Pos.rotateXZBy(180);
+ else if (facedir == 3)
+ vertex->Pos.rotateXZBy(90);
+ break;
+ case 1: // z+
+ vertex->Pos.rotateYZBy(90);
+ if (facedir == 1)
+ vertex->Pos.rotateXYBy(90);
+ else if (facedir == 2)
+ vertex->Pos.rotateXYBy(180);
+ else if (facedir == 3)
+ vertex->Pos.rotateXYBy(-90);
+ break;
+ case 2: //z-
+ vertex->Pos.rotateYZBy(-90);
+ if (facedir == 1)
+ vertex->Pos.rotateXYBy(-90);
+ else if (facedir == 2)
+ vertex->Pos.rotateXYBy(180);
+ else if (facedir == 3)
+ vertex->Pos.rotateXYBy(90);
+ break;
+ case 3: //x+
+ vertex->Pos.rotateXYBy(-90);
+ if (facedir == 1)
+ vertex->Pos.rotateYZBy(90);
+ else if (facedir == 2)
+ vertex->Pos.rotateYZBy(180);
+ else if (facedir == 3)
+ vertex->Pos.rotateYZBy(-90);
+ break;
+ case 4: //x-
+ vertex->Pos.rotateXYBy(90);
+ if (facedir == 1)
+ vertex->Pos.rotateYZBy(-90);
+ else if (facedir == 2)
+ vertex->Pos.rotateYZBy(180);
+ else if (facedir == 3)
+ vertex->Pos.rotateYZBy(90);
+ break;
+ case 5:
+ vertex->Pos.rotateXYBy(-180);
+ if (facedir == 1)
+ vertex->Pos.rotateXZBy(90);
+ else if (facedir == 2)
+ vertex->Pos.rotateXZBy(180);
+ else if (facedir == 3)
+ vertex->Pos.rotateXZBy(-90);
+ break;
+ default:
+ break;
}
}
}
void recalculateBoundingBox(scene::IMesh *src_mesh)
{
- core::aabbox3d<f32> bbox;
+ aabb3f bbox;
bbox.reset(0,0,0);
- for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
- {
+ for (u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) {
scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
buf->recalculateBoundingBox();
- if(j == 0)
+ if (j == 0)
bbox = buf->getBoundingBox();
else
bbox.addInternalBox(buf->getBoundingBox());
src_mesh->setBoundingBox(bbox);
}
-scene::IMesh* cloneMesh(scene::IMesh *src_mesh)
+scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer)
+{
+ switch (mesh_buffer->getVertexType()) {
+ case video::EVT_STANDARD: {
+ video::S3DVertex *v = (video::S3DVertex *) mesh_buffer->getVertices();
+ u16 *indices = mesh_buffer->getIndices();
+ scene::SMeshBuffer *cloned_buffer = new scene::SMeshBuffer();
+ cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices,
+ mesh_buffer->getIndexCount());
+ return cloned_buffer;
+ }
+ case video::EVT_2TCOORDS: {
+ video::S3DVertex2TCoords *v =
+ (video::S3DVertex2TCoords *) mesh_buffer->getVertices();
+ u16 *indices = mesh_buffer->getIndices();
+ scene::SMeshBufferTangents *cloned_buffer =
+ new scene::SMeshBufferTangents();
+ cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices,
+ mesh_buffer->getIndexCount());
+ return cloned_buffer;
+ }
+ case video::EVT_TANGENTS: {
+ video::S3DVertexTangents *v =
+ (video::S3DVertexTangents *) mesh_buffer->getVertices();
+ u16 *indices = mesh_buffer->getIndices();
+ scene::SMeshBufferTangents *cloned_buffer =
+ new scene::SMeshBufferTangents();
+ cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices,
+ mesh_buffer->getIndexCount());
+ return cloned_buffer;
+ }
+ }
+ // This should not happen.
+ sanity_check(false);
+ return NULL;
+}
+
+scene::SMesh* cloneMesh(scene::IMesh *src_mesh)
{
scene::SMesh* dst_mesh = new scene::SMesh();
- for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
- {
- scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
- video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
- u16 *indices = (u16*)buf->getIndices();
- scene::SMeshBuffer *temp_buf = new scene::SMeshBuffer();
- temp_buf->append(vertices, buf->getVertexCount(),
- indices, buf->getIndexCount());
+ for (u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) {
+ scene::IMeshBuffer *temp_buf = cloneMeshBuffer(
+ src_mesh->getMeshBuffer(j));
dst_mesh->addMeshBuffer(temp_buf);
temp_buf->drop();
+
}
- return dst_mesh;
+ return dst_mesh;
}
-scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
+scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
+ const f32 *uv_coords, float expand)
{
scene::SMesh* dst_mesh = new scene::SMesh();
+
for (u16 j = 0; j < 6; j++)
{
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
dst_mesh->addMeshBuffer(buf);
buf->drop();
}
-
- video::SColor c(255,255,255,255);
- std::vector<aabb3f> boxes = f->node_box.fixed;
-
- for(std::vector<aabb3f>::iterator
+ video::SColor c(255,255,255,255);
+
+ for (std::vector<aabb3f>::const_iterator
i = boxes.begin();
- i != boxes.end(); i++)
+ i != boxes.end(); ++i)
{
aabb3f box = *i;
-
- f32 temp;
- if (box.MinEdge.X > box.MaxEdge.X)
- {
- temp=box.MinEdge.X;
- box.MinEdge.X=box.MaxEdge.X;
- box.MaxEdge.X=temp;
- }
- if (box.MinEdge.Y > box.MaxEdge.Y)
- {
- temp=box.MinEdge.Y;
- box.MinEdge.Y=box.MaxEdge.Y;
- box.MaxEdge.Y=temp;
- }
- if (box.MinEdge.Z > box.MaxEdge.Z)
- {
- temp=box.MinEdge.Z;
- box.MinEdge.Z=box.MaxEdge.Z;
- box.MaxEdge.Z=temp;
- }
- // Compute texture coords
- f32 tx1 = (box.MinEdge.X/BS)+0.5;
- f32 ty1 = (box.MinEdge.Y/BS)+0.5;
- f32 tz1 = (box.MinEdge.Z/BS)+0.5;
- f32 tx2 = (box.MaxEdge.X/BS)+0.5;
- f32 ty2 = (box.MaxEdge.Y/BS)+0.5;
- f32 tz2 = (box.MaxEdge.Z/BS)+0.5;
- f32 txc[24] = {
+ box.repair();
+
+ box.MinEdge.X -= expand;
+ box.MinEdge.Y -= expand;
+ box.MinEdge.Z -= expand;
+ box.MaxEdge.X += expand;
+ box.MaxEdge.Y += expand;
+ box.MaxEdge.Z += expand;
+
+ // Compute texture UV coords
+ f32 tx1 = (box.MinEdge.X / BS) + 0.5;
+ f32 ty1 = (box.MinEdge.Y / BS) + 0.5;
+ f32 tz1 = (box.MinEdge.Z / BS) + 0.5;
+ f32 tx2 = (box.MaxEdge.X / BS) + 0.5;
+ f32 ty2 = (box.MaxEdge.Y / BS) + 0.5;
+ f32 tz2 = (box.MaxEdge.Z / BS) + 0.5;
+
+ f32 txc_default[24] = {
// up
- tx1, 1-tz2, tx2, 1-tz1,
+ tx1, 1 - tz2, tx2, 1 - tz1,
// down
tx1, tz1, tx2, tz2,
// right
- tz1, 1-ty2, tz2, 1-ty1,
+ tz1, 1 - ty2, tz2, 1 - ty1,
// left
- 1-tz2, 1-ty2, 1-tz1, 1-ty1,
+ 1 - tz2, 1 - ty2, 1 - tz1, 1 - ty1,
// back
- 1-tx2, 1-ty2, 1-tx1, 1-ty1,
+ 1 - tx2, 1 - ty2, 1 - tx1, 1 - ty1,
// front
- tx1, 1-ty2, tx2, 1-ty1,
+ tx1, 1 - ty2, tx2, 1 - ty1,
};
+
+ // use default texture UV mapping if not provided
+ const f32 *txc = uv_coords ? uv_coords : txc_default;
+
v3f min = box.MinEdge;
v3f max = box.MaxEdge;
buf->append(vertices + j, 4, indices, 6);
}
}
- return dst_mesh;
+ return dst_mesh;
}
struct vcache