- /*
- Generate sides
- */
-
- v3s16 side_dirs[4] = {
- v3s16(1,0,0),
- v3s16(-1,0,0),
- v3s16(0,0,1),
- v3s16(0,0,-1),
- };
- s16 side_corners[4][2] = {
- {1, 2},
- {3, 0},
- {2, 3},
- {0, 1},
- };
- for(u32 i=0; i<4; i++)
- {
- v3s16 dir = side_dirs[i];
-
- /*
- If our topside is liquid and neighbor's topside
- is liquid, don't draw side face
- */
- if(top_is_same_liquid &&
- neighbor_flags[dir] & neighborflag_top_is_same_liquid)
- continue;
-
- content_t neighbor_content = neighbor_contents[dir];
- const ContentFeatures &n_feat = nodedef->get(neighbor_content);
-
- // Don't draw face if neighbor is blocking the view
- if(n_feat.solidness == 2)
- continue;
-
- bool neighbor_is_same_liquid = (neighbor_content == c_source
- || neighbor_content == c_flowing);
-
- // Don't draw any faces if neighbor same is liquid and top is
- // same liquid
- if(neighbor_is_same_liquid == true
- && top_is_same_liquid == false)
- continue;
-
- // Use backface culled material if neighbor doesn't have a
- // solidness of 0
- const TileSpec *current_tile = &tile_liquid;
- if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
- current_tile = &tile_liquid_bfculled;
-
- video::S3DVertex vertices[4] =
- {
- video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
- video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
- video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
- video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
- };
-
- /*
- If our topside is liquid, set upper border of face
- at upper border of node
- */
- if(top_is_same_liquid)
- {
- vertices[2].Pos.Y = 0.5*BS;
- vertices[3].Pos.Y = 0.5*BS;
- }
- /*
- Otherwise upper position of face is corner levels
- */
- else
- {
- vertices[2].Pos.Y = corner_levels[side_corners[i][0]];
- vertices[3].Pos.Y = corner_levels[side_corners[i][1]];
- }
-
- /*
- If neighbor is liquid, lower border of face is corner
- liquid levels
- */
- if(neighbor_is_same_liquid)
- {
- vertices[0].Pos.Y = corner_levels[side_corners[i][1]];
- vertices[1].Pos.Y = corner_levels[side_corners[i][0]];
- }
- /*
- If neighbor is not liquid, lower border of face is
- lower border of node
- */
- else
- {
- vertices[0].Pos.Y = -0.5*BS;
- vertices[1].Pos.Y = -0.5*BS;
- }
-
- for(s32 j=0; j<4; j++)
- {
- if(dir == v3s16(0,0,1))
- vertices[j].Pos.rotateXZBy(0);
- if(dir == v3s16(0,0,-1))
- vertices[j].Pos.rotateXZBy(180);
- if(dir == v3s16(-1,0,0))
- vertices[j].Pos.rotateXZBy(90);
- if(dir == v3s16(1,0,-0))
- vertices[j].Pos.rotateXZBy(-90);
-
- // Do this to not cause glitches when two liquids are
- // side-by-side
- /*if(neighbor_is_same_liquid == false){
- vertices[j].Pos.X *= 0.98;
- vertices[j].Pos.Z *= 0.98;
- }*/
-
- vertices[j].Pos += intToFloat(p, BS);
- }
-
- u16 indices[] = {0,1,2,2,3,0};
- // Add to mesh collector
- collector.append(*current_tile, vertices, 4, indices, 6);
- }
-
- /*
- Generate top side, if appropriate
- */
-
- if(top_is_same_liquid == false)
- {
- video::S3DVertex vertices[4] =
- {
- video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
- video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
- video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,0),
- video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,0),
- };
-
- // To get backface culling right, the vertices need to go
- // clockwise around the front of the face. And we happened to
- // calculate corner levels in exact reverse order.
- s32 corner_resolve[4] = {3,2,1,0};
-
- for(s32 i=0; i<4; i++)
- {
- //vertices[i].Pos.Y += liquid_level;
- //vertices[i].Pos.Y += neighbor_levels[v3s16(0,0,0)];
- s32 j = corner_resolve[i];
- vertices[i].Pos.Y += corner_levels[j];
- vertices[i].Pos += intToFloat(p, BS);
- }
-
- // Default downwards-flowing texture animation goes from
- // -Z towards +Z, thus the direction is +Z.
- // Rotate texture to make animation go in flow direction
- // Positive if liquid moves towards +Z
- f32 dz = (corner_levels[side_corners[3][0]] +
- corner_levels[side_corners[3][1]]) -
- (corner_levels[side_corners[2][0]] +
- corner_levels[side_corners[2][1]]);
- // Positive if liquid moves towards +X
- f32 dx = (corner_levels[side_corners[1][0]] +
- corner_levels[side_corners[1][1]]) -
- (corner_levels[side_corners[0][0]] +
- corner_levels[side_corners[0][1]]);
- f32 tcoord_angle = atan2(dz, dx) * core::RADTODEG ;
- v2f tcoord_center(0.5, 0.5);
- v2f tcoord_translate(
- blockpos_nodes.Z + z,
- blockpos_nodes.X + x);
- tcoord_translate.rotateBy(tcoord_angle);
- tcoord_translate.X -= floor(tcoord_translate.X);
- tcoord_translate.Y -= floor(tcoord_translate.Y);
-
- for(s32 i=0; i<4; i++)
- {
- vertices[i].TCoords.rotateBy(
- tcoord_angle,
- tcoord_center);
- vertices[i].TCoords += tcoord_translate;
- }
-
- v2f t = vertices[0].TCoords;
- vertices[0].TCoords = vertices[2].TCoords;
- vertices[2].TCoords = t;
-
- u16 indices[] = {0,1,2,2,3,0};
- // Add to mesh collector
- collector.append(tile_liquid, vertices, 4, indices, 6);
- }
- break;}
- case NDT_GLASSLIKE:
- {
- TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
-
- u16 l = getInteriorLight(n, 1, nodedef);
- video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
-
- for(u32 j=0; j<6; j++)
- {
- // Check this neighbor
- v3s16 n2p = blockpos_nodes + p + g_6dirs[j];
- MapNode n2 = data->m_vmanip.getNodeNoEx(n2p);
- // Don't make face if neighbor is of same type
- if(n2.getContent() == n.getContent())
- continue;
-
- // The face at Z+
- video::S3DVertex vertices[4] = {
- video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
- video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
- video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 0,0),
- video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
- };
-
- // Rotations in the g_6dirs format
- if(j == 0) // Z+
- for(u16 i=0; i<4; i++)
- vertices[i].Pos.rotateXZBy(0);
- else if(j == 1) // Y+
- for(u16 i=0; i<4; i++)
- vertices[i].Pos.rotateYZBy(-90);
- else if(j == 2) // X+
- for(u16 i=0; i<4; i++)
- vertices[i].Pos.rotateXZBy(-90);
- else if(j == 3) // Z-
- for(u16 i=0; i<4; i++)
- vertices[i].Pos.rotateXZBy(180);
- else if(j == 4) // Y-
- for(u16 i=0; i<4; i++)
- vertices[i].Pos.rotateYZBy(90);
- else if(j == 5) // X-
- for(u16 i=0; i<4; i++)
- vertices[i].Pos.rotateXZBy(90);
-
- for(u16 i=0; i<4; i++){
- vertices[i].Pos += intToFloat(p, BS);
- }
-
- u16 indices[] = {0,1,2,2,3,0};
- // Add to mesh collector
- collector.append(tile, vertices, 4, indices, 6);
- }
- break;}
- case NDT_GLASSLIKE_FRAMED:
- {
- static const v3s16 dirs[6] = {
- v3s16( 0, 1, 0),
- v3s16( 0,-1, 0),
- v3s16( 1, 0, 0),
- v3s16(-1, 0, 0),
- v3s16( 0, 0, 1),
- v3s16( 0, 0,-1)
- };
-
- u8 i;
- TileSpec tiles[6];
- for (i = 0; i < 6; i++)
- tiles[i] = getNodeTile(n, p, dirs[i], data);
-
- TileSpec glass_tiles[6];
- if (tiles[1].texture && tiles[2].texture && tiles[3].texture) {
- glass_tiles[0] = tiles[2];
- glass_tiles[1] = tiles[3];
- glass_tiles[2] = tiles[1];
- glass_tiles[3] = tiles[1];
- glass_tiles[4] = tiles[1];
- glass_tiles[5] = tiles[1];
- } else {
- for (i = 0; i < 6; i++)
- glass_tiles[i] = tiles[1];
- }
-
- u8 param2 = n.getParam2();
- bool H_merge = ! bool(param2 & 128);
- bool V_merge = ! bool(param2 & 64);
- param2 = param2 & 63;
-
- u16 l = getInteriorLight(n, 1, nodedef);
- video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
- v3f pos = intToFloat(p, BS);
- static const float a = BS / 2;
- static const float g = a - 0.003;
- static const float b = .876 * ( BS / 2 );
-
- static const aabb3f frame_edges[12] = {
- aabb3f( b, b,-a, a, a, a), // y+
- aabb3f(-a, b,-a,-b, a, a), // y+
- aabb3f( b,-a,-a, a,-b, a), // y-
- aabb3f(-a,-a,-a,-b,-b, a), // y-
- aabb3f( b,-a, b, a, a, a), // x+
- aabb3f( b,-a,-a, a, a,-b), // x+
- aabb3f(-a,-a, b,-b, a, a), // x-
- aabb3f(-a,-a,-a,-b, a,-b), // x-
- aabb3f(-a, b, b, a, a, a), // z+
- aabb3f(-a,-a, b, a,-b, a), // z+
- aabb3f(-a,-a,-a, a,-b,-b), // z-
- aabb3f(-a, b,-a, a, a,-b) // z-
- };
- static const aabb3f glass_faces[6] = {
- aabb3f(-g, g,-g, g, g, g), // y+
- aabb3f(-g,-g,-g, g,-g, g), // y-
- aabb3f( g,-g,-g, g, g, g), // x+
- aabb3f(-g,-g,-g,-g, g, g), // x-
- aabb3f(-g,-g, g, g, g, g), // z+
- aabb3f(-g,-g,-g, g, g,-g) // z-
- };
-
- // table of node visible faces, 0 = invisible
- int visible_faces[6] = {0,0,0,0,0,0};
-
- // table of neighbours, 1 = same type, checked with g_26dirs
- int nb[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
- // g_26dirs to check when only horizontal merge is allowed
- int nb_H_dirs[8] = {0,2,3,5,10,11,12,13};
-
- content_t current = n.getContent();
- content_t n2c;
- MapNode n2;
- v3s16 n2p;
-
- // neighbours checks for frames visibility
-
- if (!H_merge && V_merge) {
- n2p = blockpos_nodes + p + g_26dirs[1];
- n2 = data->m_vmanip.getNodeNoEx(n2p);
- n2c = n2.getContent();
- if (n2c == current || n2c == CONTENT_IGNORE)
- nb[1] = 1;
- n2p = blockpos_nodes + p + g_26dirs[4];
- n2 = data->m_vmanip.getNodeNoEx(n2p);
- n2c = n2.getContent();
- if (n2c == current || n2c == CONTENT_IGNORE)
- nb[4] = 1;
- } else if (H_merge && !V_merge) {
- for(i = 0; i < 8; i++) {
- n2p = blockpos_nodes + p + g_26dirs[nb_H_dirs[i]];
- n2 = data->m_vmanip.getNodeNoEx(n2p);
- n2c = n2.getContent();
- if (n2c == current || n2c == CONTENT_IGNORE)
- nb[nb_H_dirs[i]] = 1;
- }
- } else if (H_merge && V_merge) {
- for(i = 0; i < 18; i++) {
- n2p = blockpos_nodes + p + g_26dirs[i];
- n2 = data->m_vmanip.getNodeNoEx(n2p);
- n2c = n2.getContent();
- if (n2c == current || n2c == CONTENT_IGNORE)
- nb[i] = 1;
- }
- }