From 3359eaf406bae1fb2a13efcf939ec7ced612e58c Mon Sep 17 00:00:00 2001 From: darkrose Date: Sat, 27 Jul 2013 02:06:22 +1000 Subject: [PATCH] redo collision, implement content draw type, rewrite mesh generator, implement nodeboxes, implement stairs and slabs --- src/collision.cpp | 578 +++++++++++++++++++++++++------------- src/collision.h | 63 +++-- src/common_irrlicht.h | 2 + src/content_craft.cpp | 23 +- src/content_mapblock.cpp | 591 ++++++++++++++++++--------------------- src/content_mapnode.cpp | 530 +++++++++++++++++++++++++++++++++++ src/content_mapnode.h | 45 ++- src/content_sao.cpp | 14 +- src/mapnode.cpp | 74 +++++ src/mapnode.h | 63 +++++ src/player.cpp | 304 ++++---------------- src/player.h | 4 + src/tile.cpp | 227 +++++++++++++++ 13 files changed, 1730 insertions(+), 788 deletions(-) diff --git a/src/collision.cpp b/src/collision.cpp index 437e930..797d9d4 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -1,18 +1,18 @@ /* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or +the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -20,28 +20,257 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "collision.h" #include "mapblock.h" #include "map.h" +#include "log.h" +#include "main.h" // g_profiler +#include "profiler.h" -collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, - const core::aabbox3d &box_0, - f32 dtime, v3f &pos_f, v3f &speed_f) +// Helper function: +// Checks for collision of a moving aabbox with a static aabbox +// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision +// The time after which the collision occurs is stored in dtime. +int axisAlignedCollision( + const aabb3f &staticbox, const aabb3f &movingbox, + const v3f &speed, f32 d, f32 &dtime) { + //TimeTaker tt("axisAlignedCollision"); + + f32 xsize = (staticbox.MaxEdge.X - staticbox.MinEdge.X); + f32 ysize = (staticbox.MaxEdge.Y - staticbox.MinEdge.Y); + f32 zsize = (staticbox.MaxEdge.Z - staticbox.MinEdge.Z); + + aabb3f relbox( + movingbox.MinEdge.X - staticbox.MinEdge.X, + movingbox.MinEdge.Y - staticbox.MinEdge.Y, + movingbox.MinEdge.Z - staticbox.MinEdge.Z, + movingbox.MaxEdge.X - staticbox.MinEdge.X, + movingbox.MaxEdge.Y - staticbox.MinEdge.Y, + movingbox.MaxEdge.Z - staticbox.MinEdge.Z + ); + + if(speed.X > 0) // Check for collision with X- plane + { + if(relbox.MaxEdge.X <= d) + { + dtime = - relbox.MaxEdge.X / speed.X; + if((relbox.MinEdge.Y + speed.Y * dtime < ysize) && + (relbox.MaxEdge.Y + speed.Y * dtime > 0) && + (relbox.MinEdge.Z + speed.Z * dtime < zsize) && + (relbox.MaxEdge.Z + speed.Z * dtime > 0)) + return 0; + } + else if(relbox.MinEdge.X > xsize) + { + return -1; + } + } + else if(speed.X < 0) // Check for collision with X+ plane + { + if(relbox.MinEdge.X >= xsize - d) + { + dtime = (xsize - relbox.MinEdge.X) / speed.X; + if((relbox.MinEdge.Y + speed.Y * dtime < ysize) && + (relbox.MaxEdge.Y + speed.Y * dtime > 0) && + (relbox.MinEdge.Z + speed.Z * dtime < zsize) && + (relbox.MaxEdge.Z + speed.Z * dtime > 0)) + return 0; + } + else if(relbox.MaxEdge.X < 0) + { + return -1; + } + } + + // NO else if here + + if(speed.Y > 0) // Check for collision with Y- plane + { + if(relbox.MaxEdge.Y <= d) + { + dtime = - relbox.MaxEdge.Y / speed.Y; + if((relbox.MinEdge.X + speed.X * dtime < xsize) && + (relbox.MaxEdge.X + speed.X * dtime > 0) && + (relbox.MinEdge.Z + speed.Z * dtime < zsize) && + (relbox.MaxEdge.Z + speed.Z * dtime > 0)) + return 1; + } + else if(relbox.MinEdge.Y > ysize) + { + return -1; + } + } + else if(speed.Y < 0) // Check for collision with Y+ plane + { + if(relbox.MinEdge.Y >= ysize - d) + { + dtime = (ysize - relbox.MinEdge.Y) / speed.Y; + if((relbox.MinEdge.X + speed.X * dtime < xsize) && + (relbox.MaxEdge.X + speed.X * dtime > 0) && + (relbox.MinEdge.Z + speed.Z * dtime < zsize) && + (relbox.MaxEdge.Z + speed.Z * dtime > 0)) + return 1; + } + else if(relbox.MaxEdge.Y < 0) + { + return -1; + } + } + + // NO else if here + + if(speed.Z > 0) // Check for collision with Z- plane + { + if(relbox.MaxEdge.Z <= d) + { + dtime = - relbox.MaxEdge.Z / speed.Z; + if((relbox.MinEdge.X + speed.X * dtime < xsize) && + (relbox.MaxEdge.X + speed.X * dtime > 0) && + (relbox.MinEdge.Y + speed.Y * dtime < ysize) && + (relbox.MaxEdge.Y + speed.Y * dtime > 0)) + return 2; + } + //else if(relbox.MinEdge.Z > zsize) + //{ + // return -1; + //} + } + else if(speed.Z < 0) // Check for collision with Z+ plane + { + if(relbox.MinEdge.Z >= zsize - d) + { + dtime = (zsize - relbox.MinEdge.Z) / speed.Z; + if((relbox.MinEdge.X + speed.X * dtime < xsize) && + (relbox.MaxEdge.X + speed.X * dtime > 0) && + (relbox.MinEdge.Y + speed.Y * dtime < ysize) && + (relbox.MaxEdge.Y + speed.Y * dtime > 0)) + return 2; + } + //else if(relbox.MaxEdge.Z < 0) + //{ + // return -1; + //} + } + + return -1; +} + +// Helper function: +// Checks if moving the movingbox up by the given distance would hit a ceiling. +bool wouldCollideWithCeiling( + const std::vector &staticboxes, + const aabb3f &movingbox, + f32 y_increase, f32 d) +{ + //TimeTaker tt("wouldCollideWithCeiling"); + + assert(y_increase >= 0); + + for(std::vector::const_iterator + i = staticboxes.begin(); + i != staticboxes.end(); i++) + { + const aabb3f& staticbox = *i; + if((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) && + (movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) && + (movingbox.MinEdge.X < staticbox.MaxEdge.X) && + (movingbox.MaxEdge.X > staticbox.MinEdge.X) && + (movingbox.MinEdge.Z < staticbox.MaxEdge.Z) && + (movingbox.MaxEdge.Z > staticbox.MinEdge.Z)) + return true; + } + + return false; +} + + +collisionMoveResult collisionMoveSimple(Map *map, + f32 pos_max_d, const aabb3f &box_0, + f32 stepheight, f32 dtime, + v3f &pos_f, v3f &speed_f, v3f &accel_f) +{ + //TimeTaker tt("collisionMoveSimple"); + ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG); + collisionMoveResult result; - v3f oldpos_f = pos_f; - v3s16 oldpos_i = floatToInt(oldpos_f, BS); + /* + Calculate new velocity + */ + if( dtime > 0.5 ) { + infostream<<"collisionMoveSimple: WARNING: maximum step interval exceeded, lost movement details!"< cboxes; + std::vector is_unloaded; + std::vector is_step_up; + std::vector node_positions; + { + //TimeTaker tt2("collisionMoveSimple collect boxes"); + ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG); + + v3s16 oldpos_i = floatToInt(pos_f, BS); + v3s16 newpos_i = floatToInt(pos_f + speed_f * dtime, BS); + s16 min_x = MYMIN(oldpos_i.X, newpos_i.X) + (box_0.MinEdge.X / BS) - 1; + s16 min_y = MYMIN(oldpos_i.Y, newpos_i.Y) + (box_0.MinEdge.Y / BS) - 1; + s16 min_z = MYMIN(oldpos_i.Z, newpos_i.Z) + (box_0.MinEdge.Z / BS) - 1; + s16 max_x = MYMAX(oldpos_i.X, newpos_i.X) + (box_0.MaxEdge.X / BS) + 1; + s16 max_y = MYMAX(oldpos_i.Y, newpos_i.Y) + (box_0.MaxEdge.Y / BS) + 1; + s16 max_z = MYMAX(oldpos_i.Z, newpos_i.Z) + (box_0.MaxEdge.Z / BS) + 1; + + for(s16 x = min_x; x <= max_x; x++) + for(s16 y = min_y; y <= max_y; y++) + for(s16 z = min_z; z <= max_z; z++) + { + v3s16 p(x,y,z); + try{ + // Object collides into walkable nodes + MapNode n = map->getNode(p); + const ContentFeatures &f = content_features(n); + if(f.walkable == false) + continue; + + std::vector nodeboxes = f.getNodeBoxes(); + for(std::vector::iterator + i = nodeboxes.begin(); + i != nodeboxes.end(); i++) + { + aabb3f box = *i; + box.MinEdge += v3f(x, y, z)*BS; + box.MaxEdge += v3f(x, y, z)*BS; + cboxes.push_back(box); + is_unloaded.push_back(false); + is_step_up.push_back(false); + node_positions.push_back(p); + } + } + catch(InvalidPositionException &e) + { + // Collide with unloaded nodes + aabb3f box = getNodeBox(p, BS); + cboxes.push_back(box); + is_unloaded.push_back(true); + is_step_up.push_back(false); + node_positions.push_back(p); + } + } + } // tt2 + + assert(cboxes.size() == is_unloaded.size()); + assert(cboxes.size() == is_step_up.size()); + assert(cboxes.size() == node_positions.size()); /* Collision detection */ - // position in nodes - v3s16 pos_i = floatToInt(pos_f, BS); - /* Collision uncertainty radius Make it a bit larger than the maximum distance of movement @@ -53,57 +282,145 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, // This should always apply, otherwise there are glitches assert(d > pos_max_d); - /* - Calculate collision box - */ - core::aabbox3d box = box_0; - box.MaxEdge += pos_f; - box.MinEdge += pos_f; - core::aabbox3d oldbox = box_0; - oldbox.MaxEdge += oldpos_f; - oldbox.MinEdge += oldpos_f; + int loopcount = 0; - /* - If the object lies on a walkable node, this is set to true. - */ - result.touching_ground = false; - try{ - // Check for liquid, and damage = lava - MapNode n = map->getNode(pos_i); - if(content_features(n).liquid_type != LIQUID_NONE) + while(dtime > BS*1e-10) + { + //TimeTaker tt3("collisionMoveSimple dtime loop"); + ScopeProfiler sp(g_profiler, "collisionMoveSimple dtime loop avg", SPT_AVG); + + // Avoid infinite loop + loopcount++; + if(loopcount >= 100) { - result.in_liquid = true; - if (content_features(n).damage_per_second > 1.0) - result.touching_lethal = true; + infostream<<"collisionMoveSimple: WARNING: Loop count exceeded, aborting to avoid infiniite loop"<getNode(v3s16(x,y,z)); - if(content_features(n).walkable == false) + aabb3f movingbox = box_0; + movingbox.MinEdge += pos_f; + movingbox.MaxEdge += pos_f; + + int nearest_collided = -1; + f32 nearest_dtime = dtime; + u32 nearest_boxindex = -1; + + /* + Go through every nodebox, find nearest collision + */ + for(u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) + { + // Ignore if already stepped up this nodebox. + if(is_step_up[boxindex]) continue; - } - catch(InvalidPositionException &e) - { - // Doing nothing here will block the object from - // walking over map borders + + // Find nearest collision of the two boxes (raytracing-like) + f32 dtime_tmp; + int collided = axisAlignedCollision( + cboxes[boxindex], movingbox, speed_f, d, dtime_tmp); + + if(collided == -1 || dtime_tmp >= nearest_dtime) + continue; + + nearest_dtime = dtime_tmp; + nearest_collided = collided; + nearest_boxindex = boxindex; } - core::aabbox3d nodebox = getNodeBox(v3s16(x,y,z), BS); + if(nearest_collided == -1) + { + // No collision with any collision box. + pos_f += speed_f * dtime; + dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers + } + else + { + // Otherwise, a collision occurred. + + const aabb3f& cbox = cboxes[nearest_boxindex]; + + // Check for stairs. + bool step_up = (nearest_collided != 1) && // must not be Y direction + (movingbox.MinEdge.Y < cbox.MaxEdge.Y) && + (movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) && + (!wouldCollideWithCeiling(cboxes, movingbox, + cbox.MaxEdge.Y - movingbox.MinEdge.Y, + d)); + + // Move to the point of collision and reduce dtime by nearest_dtime + if(nearest_dtime < 0) + { + // Handle negative nearest_dtime (can be caused by the d allowance) + if(!step_up) + { + if(nearest_collided == 0) + pos_f.X += speed_f.X * nearest_dtime; + if(nearest_collided == 1) + pos_f.Y += speed_f.Y * nearest_dtime; + if(nearest_collided == 2) + pos_f.Z += speed_f.Z * nearest_dtime; + } + } + else + { + pos_f += speed_f * nearest_dtime; + dtime -= nearest_dtime; + } + + bool is_collision = true; + if(is_unloaded[nearest_boxindex]) + is_collision = false; + + CollisionInfo info; + info.t = COLLISION_NODE; + info.node_p = node_positions[nearest_boxindex]; + info.old_speed = speed_f; + + // Set the speed component that caused the collision to zero + if(step_up) + { + // Special case: Handle stairs + is_step_up[nearest_boxindex] = true; + is_collision = false; + } + else if(nearest_collided == 0) // X + { + speed_f.X = 0; + result.collides = true; + result.collides_xz = true; + } + else if(nearest_collided == 1) // Y + { + speed_f.Y = 0; + result.collides = true; + } + else if(nearest_collided == 2) // Z + { + speed_f.Z = 0; + result.collides = true; + result.collides_xz = true; + } + + info.new_speed = speed_f; + if(info.new_speed.getDistanceFrom(info.old_speed) < 0.1*BS) + is_collision = false; + + if(is_collision){ + result.collisions.push_back(info); + } + } + } + + /* + Final touches: Check if standing on ground, step up stairs. + */ + aabb3f box = box_0; + box.MinEdge += pos_f; + box.MaxEdge += pos_f; + for(u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) + { + const aabb3f& cbox = cboxes[boxindex]; /* See if the object is touching ground. @@ -115,141 +432,26 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, Use 0.15*BS so that it is easier to get on a node. */ if( - //fabs(nodebox.MaxEdge.Y-box.MinEdge.Y) < d - fabs(nodebox.MaxEdge.Y-box.MinEdge.Y) < 0.15*BS - && nodebox.MaxEdge.X-d > box.MinEdge.X - && nodebox.MinEdge.X+d < box.MaxEdge.X - && nodebox.MaxEdge.Z-d > box.MinEdge.Z - && nodebox.MinEdge.Z+d < box.MaxEdge.Z + cbox.MaxEdge.X-d > box.MinEdge.X && + cbox.MinEdge.X+d < box.MaxEdge.X && + cbox.MaxEdge.Z-d > box.MinEdge.Z && + cbox.MinEdge.Z+d < box.MaxEdge.Z ){ - result.touching_ground = true; - } - - // If object doesn't intersect with node, ignore node. - if(box.intersectsWithBox(nodebox) == false) - continue; - - /* - Go through every axis - */ - v3f dirs[3] = { - v3f(0,0,1), // back-front - v3f(0,1,0), // top-bottom - v3f(1,0,0), // right-left - }; - for(u16 i=0; i<3; i++) - { - /* - Calculate values along the axis - */ - f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]); - f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]); - f32 objectmax = box.MaxEdge.dotProduct(dirs[i]); - f32 objectmin = box.MinEdge.dotProduct(dirs[i]); - f32 objectmax_old = oldbox.MaxEdge.dotProduct(dirs[i]); - f32 objectmin_old = oldbox.MinEdge.dotProduct(dirs[i]); - - /* - Check collision for the axis. - Collision happens when object is going through a surface. - */ - bool negative_axis_collides = - (nodemax > objectmin && nodemax <= objectmin_old + d - && speed_f.dotProduct(dirs[i]) < 0); - bool positive_axis_collides = - (nodemin < objectmax && nodemin >= objectmax_old - d - && speed_f.dotProduct(dirs[i]) > 0); - bool main_axis_collides = - negative_axis_collides || positive_axis_collides; - - /* - Check overlap of object and node in other axes - */ - bool other_axes_overlap = true; - for(u16 j=0; j<3; j++) + if(is_step_up[boxindex]) { - if(j == i) - continue; - f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]); - f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]); - f32 objectmax = box.MaxEdge.dotProduct(dirs[j]); - f32 objectmin = box.MinEdge.dotProduct(dirs[j]); - if(!(nodemax - d > objectmin && nodemin + d < objectmax)) - { - other_axes_overlap = false; - break; - } + pos_f.Y += (cbox.MaxEdge.Y - box.MinEdge.Y); + box = box_0; + box.MinEdge += pos_f; + box.MaxEdge += pos_f; } - - /* - If this is a collision, revert the pos_f in the main - direction. - */ - if(other_axes_overlap && main_axis_collides) + if(fabs(cbox.MaxEdge.Y-box.MinEdge.Y) < 0.15*BS) { - speed_f -= speed_f.dotProduct(dirs[i]) * dirs[i]; - pos_f -= pos_f.dotProduct(dirs[i]) * dirs[i]; - pos_f += oldpos_f.dotProduct(dirs[i]) * dirs[i]; + result.touching_ground = true; + if(is_unloaded[boxindex]) + result.standing_on_unloaded = true; } - } - } // xyz + } return result; } - -collisionMoveResult collisionMovePrecise(Map *map, f32 pos_max_d, - const core::aabbox3d &box_0, - f32 dtime, v3f &pos_f, v3f &speed_f) -{ - collisionMoveResult final_result; - - // Maximum time increment (for collision detection etc) - // time = distance / speed - f32 dtime_max_increment = pos_max_d / speed_f.getLength(); - - // Maximum time increment is 10ms or lower - if(dtime_max_increment > 0.01) - dtime_max_increment = 0.01; - - // Don't allow overly huge dtime - if(dtime > 2.0) - dtime = 2.0; - - f32 dtime_downcount = dtime; - - u32 loopcount = 0; - do - { - loopcount++; - - f32 dtime_part; - if(dtime_downcount > dtime_max_increment) - { - dtime_part = dtime_max_increment; - dtime_downcount -= dtime_part; - } - else - { - dtime_part = dtime_downcount; - /* - Setting this to 0 (no -=dtime_part) disables an infinite loop - when dtime_part is so small that dtime_downcount -= dtime_part - does nothing - */ - dtime_downcount = 0; - } - - collisionMoveResult result = collisionMoveSimple(map, pos_max_d, - box_0, dtime_part, pos_f, speed_f); - - if(result.touching_ground) - final_result.touching_ground = true; - } - while(dtime_downcount > 0.001); - - - return final_result; -} - - diff --git a/src/collision.h b/src/collision.h index 2912b24..6d3aa1e 100644 --- a/src/collision.h +++ b/src/collision.h @@ -21,42 +21,57 @@ with this program; if not, write to the Free Software Foundation, Inc., #define COLLISION_HEADER #include "common_irrlicht.h" +#include class Map; -struct collisionMoveResult -{ - bool touching_ground; - bool in_liquid; - bool touching_lethal; - - collisionMoveResult(): - touching_ground(false), - in_liquid(false), - touching_lethal(false) - {} -}; - -// Moves using a single iteration; speed should not exceed pos_max_d/dtime -collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, - const core::aabbox3d &box_0, - f32 dtime, v3f &pos_f, v3f &speed_f); - -// Moves using as many iterations as needed -collisionMoveResult collisionMovePrecise(Map *map, f32 pos_max_d, - const core::aabbox3d &box_0, - f32 dtime, v3f &pos_f, v3f &speed_f); - enum CollisionType { - COLLISION_FALL + COLLISION_FALL, + COLLISION_NODE }; struct CollisionInfo { CollisionType t; f32 speed; + v3s16 node_p; // COLLISION_NODE + v3f old_speed; + v3f new_speed; + + CollisionInfo(): + t(COLLISION_NODE), + node_p(-32768,-32768,-32768), + old_speed(0,0,0), + new_speed(0,0,0) + {} }; +struct collisionMoveResult +{ + bool touching_ground; + bool in_liquid; + bool touching_lethal; + bool collides; + bool collides_xz; + bool standing_on_unloaded; + std::vector collisions; + + collisionMoveResult(): + touching_ground(false), + in_liquid(false), + touching_lethal(false), + collides(false), + collides_xz(false), + standing_on_unloaded(false) + {} +}; + +// Moves using a single iteration; speed should not exceed pos_max_d/dtime +collisionMoveResult collisionMoveSimple(Map *map, + f32 pos_max_d, const aabb3f &box_0, + f32 stepheight, f32 dtime, + v3f &pos_f, v3f &speed_f, v3f &accel_f); + #endif diff --git a/src/common_irrlicht.h b/src/common_irrlicht.h index 9339a99..fd07639 100644 --- a/src/common_irrlicht.h +++ b/src/common_irrlicht.h @@ -61,6 +61,8 @@ typedef core::vector2d v2s32; typedef core::vector2d v2u32; typedef core::vector2d v2f32; +typedef core::aabbox3d aabb3f; + #ifdef _MSC_VER // Windows typedef unsigned long long u64; diff --git a/src/content_craft.cpp b/src/content_craft.cpp index 27bcdde..c91516e 100644 --- a/src/content_craft.cpp +++ b/src/content_craft.cpp @@ -107,7 +107,7 @@ struct CraftDef { */ InventoryItem *craft_get_result(InventoryItem **items) { - static CraftDef defs[33]; + static CraftDef defs[35]; static int defs_init = 0; // only initialise (and hence allocate) these once @@ -474,6 +474,27 @@ InventoryItem *craft_get_result(InventoryItem **items) defs[defs_init].item = new CraftItem("apple_iron", 1); defs_init++; } + + // cobble slabs + { + defs[defs_init].specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].item = new MaterialItem(CONTENT_COBBLE_SLAB, 3); + defs_init++; + } + + // cobble stairs + { + defs[defs_init].specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + defs[defs_init].item = new MaterialItem(CONTENT_COBBLE_STAIR, 4); + defs_init++; + } } for (int i=0; ix0(); - f32 tu1=pa->x1(); - f32 tv0=pa->y0(); - f32 tv1=pa->y1(); - f32 txus=tu1-tu0; - f32 txvs=tv1-tv0; + v3f min = box.MinEdge; + v3f max = box.MaxEdge; - video::S3DVertex v[4] = + if(txc == NULL) { - video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv1), - video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv1), - video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv0), - video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv0) - }; - - for(int i=0;i<6;i++) - { - switch(i) - { - case 0: // top - v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz; - v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz; - v[2].Pos.X= rx; v[2].Pos.Y= ry; v[2].Pos.Z= rz; - v[3].Pos.X= rx; v[3].Pos.Y= ry, v[3].Pos.Z=-rz; - break; - case 1: // back - v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz; - v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz; - v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz; - v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz; - break; - case 2: //right - v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz; - v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz; - v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz; - v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz; - break; - case 3: // front - v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz; - v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz; - v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz; - v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz; - break; - case 4: // left - v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz; - v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz; - v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz; - v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz; - break; - case 5: // bottom - v[0].Pos.X= rx; v[0].Pos.Y=-ry; v[0].Pos.Z= rz; - v[1].Pos.X=-rx; v[1].Pos.Y=-ry; v[1].Pos.Z= rz; - v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz; - v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz; - break; - } - - if(txc!=NULL) - { - v[0].TCoords.X=tu0+txus*txc[0]; v[0].TCoords.Y=tv0+txvs*txc[3]; - v[1].TCoords.X=tu0+txus*txc[2]; v[1].TCoords.Y=tv0+txvs*txc[3]; - v[2].TCoords.X=tu0+txus*txc[2]; v[2].TCoords.Y=tv0+txvs*txc[1]; - v[3].TCoords.X=tu0+txus*txc[0]; v[3].TCoords.Y=tv0+txvs*txc[1]; - txc+=4; - } - - for(u16 i=0; i<4; i++) - v[i].Pos += pos; - u16 indices[] = {0,1,2,2,3,0}; - collector->append(material, v, 4, indices, 6); - + static const f32 txc_default[24] = { + 0,0,1,1, + 0,0,1,1, + 0,0,1,1, + 0,0,1,1, + 0,0,1,1, + 0,0,1,1 + }; + txc = txc_default; } + video::S3DVertex vertices[24] = + { + // up + video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c, txc[0],txc[1]), + video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c, txc[2],txc[1]), + video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c, txc[2],txc[3]), + video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c, txc[0],txc[3]), + // down + video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c, txc[4],txc[5]), + video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c, txc[6],txc[5]), + video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c, txc[6],txc[7]), + video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c, txc[4],txc[7]), + // right + video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c, txc[ 8],txc[9]), + video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c, txc[10],txc[9]), + video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c, txc[10],txc[11]), + video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c, txc[ 8],txc[11]), + // left + video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c, txc[12],txc[13]), + video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c, txc[14],txc[13]), + video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c, txc[14],txc[15]), + video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c, txc[12],txc[15]), + // back + video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[16],txc[17]), + video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[18],txc[17]), + video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[18],txc[19]), + video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c, txc[16],txc[19]), + // front + video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[20],txc[21]), + video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[22],txc[21]), + video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[22],txc[23]), + video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]), + }; + + u16 indices[] = {0,1,2,2,3,0}; + + // Add to mesh collector + for(s32 j=0; j<24; j+=4) + { + collector->append(material, vertices+j, 4, indices, 6); + } } #endif @@ -127,7 +110,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data, Some settings */ bool new_style_water = g_settings->getBool("new_style_water"); - bool invisible_stone = g_settings->getBool("invisible_stone"); float node_liquid_level = 1.0; if(new_style_water) @@ -135,7 +117,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE; - // New-style leaves material + // leaves material video::SMaterial material_leaves1; material_leaves1.setFlag(video::EMF_LIGHTING, false); material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false); @@ -165,6 +147,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data, g_texturesource->getTextureId("wood.png")); material_wood.setTexture(0, pa_wood.atlas); + // Cobble material + video::SMaterial material_cobble; + material_cobble.setFlag(video::EMF_LIGHTING, false); + material_cobble.setFlag(video::EMF_BILINEAR_FILTER, false); + material_cobble.setFlag(video::EMF_FOG_ENABLE, true); + material_cobble.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + AtlasPointer pa_cobble = g_texturesource->getTexture( + g_texturesource->getTextureId("cobble.png")); + material_cobble.setTexture(0, pa_cobble.atlas); + // General ground material for special output // Texture is modified just before usage video::SMaterial material_general; @@ -216,6 +208,11 @@ void mapblock_mesh_generate_special(MeshMakeData *data, g_texturesource->getTextureId("junglegrass.png")); material_junglegrass.setTexture(0, pa_junglegrass.atlas); + // sign material + AtlasPointer ap_sign_wall = g_texturesource->getTexture("sign_wall.png"); + // ladder material + AtlasPointer ap_ladder = g_texturesource->getTexture("ladder.png"); + // generic material pointer video::SMaterial *material_current; AtlasPointer *pa_current; @@ -231,8 +228,11 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Add torches to mesh */ - switch (content_features(n).liquid_type) { - case LIQUID_FLOWING: + switch (content_features(n).draw_type) { + case CDT_CUBELIKE: + case CDT_AIRLIKE: + break; + case CDT_LIQUID: { assert(content_features(n).special_material); video::SMaterial &liquid_material = @@ -518,7 +518,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, Add water sources to mesh if using new style */ break; - case LIQUID_SOURCE: + case CDT_LIQUID_SOURCE: if (new_style_water) { assert(content_features(n).special_material); @@ -559,9 +559,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, collector.append(liquid_material, vertices, 4, indices, 6); } break; - case LIQUID_NONE: - switch (n.getContent()) { - case CONTENT_TORCH: + case CDT_TORCHLIKE: { v3s16 dir = unpackDir(n.param2); @@ -631,9 +629,19 @@ void mapblock_mesh_generate_special(MeshMakeData *data, Signs on walls */ break; - case CONTENT_SIGN_WALL: + case CDT_SIGNLIKE: { - AtlasPointer ap = g_texturesource->getTexture("sign_wall.png"); + switch (n.getContent()) { + case CONTENT_SIGN_WALL: + pa_current = &ap_sign_wall; + break; + case CONTENT_LADDER: + pa_current = &ap_ladder; + break; + default: + pa_current = &ap_sign_wall; + break; + } // Set material video::SMaterial material; @@ -643,7 +651,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, material.setFlag(video::EMF_FOG_ENABLE, true); material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - material.setTexture(0, ap.atlas); + material.setTexture(0, pa_current->atlas); u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); video::SColor c = MapBlock_LightColor(255, l); @@ -653,13 +661,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data, video::S3DVertex vertices[4] = { video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, - ap.x0(), ap.y1()), + pa_current->x0(), pa_current->y1()), video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, - ap.x1(), ap.y1()), + pa_current->x1(), pa_current->y1()), video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, - ap.x1(), ap.y0()), + pa_current->x1(), pa_current->y0()), video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, - ap.x0(), ap.y0()), + pa_current->x0(), pa_current->y0()), }; v3s16 dir = unpackDir(n.param2); @@ -686,103 +694,50 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // Add to mesh collector collector.append(material, vertices, 4, indices, 6); } - /* - Add flowing liquid to mesh - */ - break; /* Add leaves if using new style */ - break; - case CONTENT_LEAVES: - { - u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c = MapBlock_LightColor(255, l); - - for(u32 j=0; j<6; j++) - { - video::S3DVertex vertices[4] = - { - video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, - pa_leaves1.x0(), pa_leaves1.y1()), - video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, - pa_leaves1.x1(), pa_leaves1.y1()), - video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, - pa_leaves1.x1(), pa_leaves1.y0()), - video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, - pa_leaves1.x0(), pa_leaves1.y0()), - }; - - if(j == 0) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(0); - } - else if(j == 1) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(180); - } - else if(j == 2) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(-90); - } - else if(j == 3) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(90); - } - else if(j == 4) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateYZBy(-90); - } - else if(j == 5) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateYZBy(90); - } - - for(u16 i=0; i<4; i++) - { - vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); - } - - u16 indices[] = {0,1,2,2,3,0}; - // Add to mesh collector - collector.append(material_leaves1, vertices, 4, indices, 6); - } - } /* Add glass */ break; - case CONTENT_GLASS: + case CDT_GLASSLIKE: { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); video::SColor c = MapBlock_LightColor(255, l); + switch (n.getContent()) { + case CONTENT_GLASS: + pa_current = &pa_glass; + material_current = &material_glass; + break; + case CONTENT_LEAVES: + pa_current = &pa_leaves1; + material_current = &material_leaves1; + break; + default: + pa_current = &pa_glass; + material_current = &material_glass; + break; + } + 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, - pa_glass.x0(), pa_glass.y1()), + pa_current->x0(), pa_current->y1()), video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, - pa_glass.x1(), pa_glass.y1()), + pa_current->x1(), pa_current->y1()), video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, - pa_glass.x1(), pa_glass.y0()), + pa_current->x1(), pa_current->y0()), video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, - pa_glass.x0(), pa_glass.y0()), + pa_current->x0(), pa_current->y0()), }; // Rotations in the g_6dirs format @@ -826,14 +781,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data, u16 indices[] = {0,1,2,2,3,0}; // Add to mesh collector - collector.append(material_glass, vertices, 4, indices, 6); + collector.append(*material_current, vertices, 4, indices, 6); } } /* Add fence */ break; - case CONTENT_FENCE: + case CDT_FENCELIKE: { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); video::SColor c = MapBlock_LightColor(255, l); @@ -844,26 +799,32 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // The post - always present v3f pos = intToFloat(p+blockpos_nodes, BS); + + // The post - always present + aabb3f post(-post_rad,-BS/2,-post_rad,post_rad,BS/2,post_rad); + post.MinEdge += pos; + post.MaxEdge += pos; f32 postuv[24]={ + 0.4,0.4,0.6,0.6, 0.35,0,0.65,1, 0.35,0,0.65,1, 0.35,0,0.65,1, 0.35,0,0.65,1, 0.4,0.4,0.6,0.6}; - makeCuboid(material_wood, &collector, - &pa_wood, c, pos, - post_rad,BS/2,post_rad, postuv); + makeCuboid(material_wood, &collector, c, post, postuv); // Now a section of fence, +X, if there's a post there v3s16 p2 = p; p2.X++; MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); - if(n2.getContent() == CONTENT_FENCE) + const ContentFeatures *f2 = &content_features(n2); + if(f2->draw_type == CDT_FENCELIKE) { - pos = intToFloat(p+blockpos_nodes, BS); - pos.X += BS/2; - pos.Y += BS/4; + aabb3f bar(-bar_len+BS/2,-bar_rad+BS/4,-bar_rad, + bar_len+BS/2,bar_rad+BS/4,bar_rad); + bar.MinEdge += pos; + bar.MaxEdge += pos; f32 xrailuv[24]={ 0,0.4,1,0.6, 0,0.4,1,0.6, @@ -871,25 +832,23 @@ void mapblock_mesh_generate_special(MeshMakeData *data, 0,0.4,1,0.6, 0,0.4,1,0.6, 0,0.4,1,0.6}; - makeCuboid(material_wood, &collector, - &pa_wood, c, pos, - bar_len,bar_rad,bar_rad, xrailuv); - - pos.Y -= BS/2; - makeCuboid(material_wood, &collector, - &pa_wood, c, pos, - bar_len,bar_rad,bar_rad, xrailuv); + makeCuboid(material_wood, &collector, c, bar, xrailuv); + bar.MinEdge.Y -= BS/2; + bar.MaxEdge.Y -= BS/2; + makeCuboid(material_wood, &collector, c, bar, xrailuv); } // Now a section of fence, +Z, if there's a post there p2 = p; p2.Z++; n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); - if(n2.getContent() == CONTENT_FENCE) + f2 = &content_features(n2); + if(f2->draw_type == CDT_FENCELIKE) { - pos = intToFloat(p+blockpos_nodes, BS); - pos.Z += BS/2; - pos.Y += BS/4; + aabb3f bar(-bar_rad,-bar_rad+BS/4,-bar_len+BS/2, + bar_rad,bar_rad+BS/4,bar_len+BS/2); + bar.MinEdge += pos; + bar.MaxEdge += pos; f32 zrailuv[24]={ 0,0.4,1,0.6, 0,0.4,1,0.6, @@ -897,100 +856,32 @@ void mapblock_mesh_generate_special(MeshMakeData *data, 0,0.4,1,0.6, 0,0.4,1,0.6, 0,0.4,1,0.6}; - makeCuboid(material_wood, &collector, - &pa_wood, c, pos, - bar_rad,bar_rad,bar_len, zrailuv); - pos.Y -= BS/2; - makeCuboid(material_wood, &collector, - &pa_wood, c, pos, - bar_rad,bar_rad,bar_len, zrailuv); - + makeCuboid(material_wood, &collector, c, bar, zrailuv); + bar.MinEdge.Y -= BS/2; + bar.MaxEdge.Y -= BS/2; + makeCuboid(material_wood, &collector, c, bar, zrailuv); } } -#if 1 - /* - Add stones with minerals if stone is invisible - */ break; - case CONTENT_STONE: - if (invisible_stone && n.getMineral() != MINERAL_NONE) - { - for(u32 j=0; j<6; j++) - { - // NOTE: Hopefully g_6dirs[j] is the right direction... - v3s16 dir = g_6dirs[j]; - u8 l = 255; - video::SColor c = MapBlock_LightColor(255, l); - - // Get the right texture - TileSpec ts = n.getTile(dir); - AtlasPointer ap = ts.texture; - material_general.setTexture(0, ap.atlas); - - video::S3DVertex vertices[4] = - { - video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, - ap.x0(), ap.y1()), - video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, - ap.x1(), ap.y1()), - video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, - ap.x1(), ap.y0()), - video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, - ap.x0(), ap.y0()), - }; - - if(j == 0) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(0); - } - else if(j == 1) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(180); - } - else if(j == 2) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(-90); - } - else if(j == 3) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(90); - } - else if(j == 4) - - for(u16 i=0; i<4; i++) - { - vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); - } - - u16 indices[] = {0,1,2,2,3,0}; - // Add to mesh collector - collector.append(material_general, vertices, 4, indices, 6); - } - } -#endif - break; - case CONTENT_RAIL: + case CDT_RAILLIKE: { bool is_rail_x [] = { false, false }; /* x-1, x+1 */ bool is_rail_z [] = { false, false }; /* z-1, z+1 */ + content_t type = n.getContent(); MapNode n_minus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x-1,y,z)); MapNode n_plus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+1,y,z)); MapNode n_minus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z-1)); MapNode n_plus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z+1)); - if(n_minus_x.getContent() == CONTENT_RAIL) + if(n_minus_x.getContent() == type) is_rail_x[0] = true; - if(n_plus_x.getContent() == CONTENT_RAIL) + if(n_plus_x.getContent() == type) is_rail_x[1] = true; - if(n_minus_z.getContent() == CONTENT_RAIL) + if(n_minus_z.getContent() == type) is_rail_z[0] = true; - if(n_plus_z.getContent() == CONTENT_RAIL) + if(n_plus_z.getContent() == type) is_rail_z[1] = true; int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1]; @@ -1083,63 +974,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, collector.append(material_rail, vertices, 4, indices, 6); } break; - case CONTENT_LADDER: - { - AtlasPointer ap = g_texturesource->getTexture("ladder.png"); - - // Set material - video::SMaterial material_ladder; - material_ladder.setFlag(video::EMF_LIGHTING, false); - material_ladder.setFlag(video::EMF_BACK_FACE_CULLING, false); - material_ladder.setFlag(video::EMF_BILINEAR_FILTER, false); - material_ladder.setFlag(video::EMF_FOG_ENABLE, true); - material_ladder.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - material_ladder.setTexture(0, ap.atlas); - - u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); - video::SColor c(255,l,l,l); - - float d = (float)BS/16; - - // Assume wall is at X+ - video::S3DVertex vertices[4] = - { - video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, - ap.x0(), ap.y1()), - video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, - ap.x1(), ap.y1()), - video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, - ap.x1(), ap.y0()), - video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, - ap.x0(), ap.y0()), - }; - - v3s16 dir = unpackDir(n.param2); - - for(s32 i=0; i<4; i++) - { - if(dir == v3s16(1,0,0)) - vertices[i].Pos.rotateXZBy(0); - if(dir == v3s16(-1,0,0)) - vertices[i].Pos.rotateXZBy(180); - if(dir == v3s16(0,0,1)) - vertices[i].Pos.rotateXZBy(90); - if(dir == v3s16(0,0,-1)) - vertices[i].Pos.rotateXZBy(-90); - if(dir == v3s16(0,-1,0)) - vertices[i].Pos.rotateXYBy(-90); - if(dir == v3s16(0,1,0)) - vertices[i].Pos.rotateXYBy(90); - - vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); - } - - u16 indices[] = {0,1,2,2,3,0}; - // Add to mesh collector - collector.append(material_ladder, vertices, 4, indices, 6); - } - break; - case CONTENT_JUNGLEGRASS: + case CDT_PLANTLIKE_LGE: { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); video::SColor c = MapBlock_LightColor(255, l); @@ -1191,9 +1026,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, } } break; - case CONTENT_PAPYRUS: - case CONTENT_SAPLING: - case CONTENT_APPLE: + case CDT_PLANTLIKE: { switch (n.getContent()) { case CONTENT_PAPYRUS: @@ -1201,14 +1034,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data, pa_current = &pa_papyrus; break; case CONTENT_SAPLING: + default: material_current = &material_sapling; pa_current = &pa_sapling; break; - case CONTENT_APPLE: - default: - material_current = &material_apple; - pa_current = &pa_apple; - break; } u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); video::SColor c = MapBlock_LightColor(255, l); @@ -1259,7 +1088,123 @@ void mapblock_mesh_generate_special(MeshMakeData *data, } } break; + case CDT_PLANTLIKE_SML: + { + switch (n.getContent()) { + case CONTENT_APPLE: + default: + material_current = &material_apple; + pa_current = &pa_apple; + break; + } + u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); + video::SColor c = MapBlock_LightColor(255, l); + + for(u32 j=0; j<4; j++) + { + video::S3DVertex vertices[4] = + { + video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, + pa_current->x0(), pa_current->y1()), + video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, + pa_current->x1(), pa_current->y1()), + video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, + pa_current->x1(), pa_current->y0()), + video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, + pa_current->x0(), pa_current->y0()), + }; + + if(j == 0) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(45); + } + else if(j == 1) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-45); + } + else if(j == 2) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(135); + } + else if(j == 3) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-135); + } + + for(u16 i=0; i<4; i++) + { + vertices[i].Pos *= 0.8; + vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(*material_current, vertices, 4, indices, 6); + } } + break; + case CDT_NODEBOX: + { + material_current = &material_cobble; + + u32 lt = 0; + u8 ld = 0; + for (s16 tx=-1; tx<2; tx++) { + for (s16 ty=-1; ty<2; ty++) { + for (s16 tz=-1; tz<2; tz++) { + if (!tx && !ty && !tz) + continue; + MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+tx,y+ty,z+tz)); + if (ty<1 && n.getContent() != CONTENT_AIR) + continue; + lt += decode_light(n.getLightBlend(data->m_daynight_ratio)); + ld++; + } + } + } + + u8 l = lt/ld; + video::SColor c = MapBlock_LightColor(255, l); + + v3f pos = intToFloat(p+blockpos_nodes, BS); + std::vector boxes = content_features(n).getNodeBoxes(); + for(std::vector::iterator + i = boxes.begin(); + i != boxes.end(); i++) + { + aabb3f box = *i; + box.MinEdge += pos; + box.MaxEdge += pos; + + // Compute texture coords + f32 tx1 = (i->MinEdge.X/BS)+0.5; + f32 ty1 = (i->MinEdge.Y/BS)+0.5; + f32 tz1 = (i->MinEdge.Z/BS)+0.5; + f32 tx2 = (i->MaxEdge.X/BS)+0.5; + f32 ty2 = (i->MaxEdge.Y/BS)+0.5; + f32 tz2 = (i->MaxEdge.Z/BS)+0.5; + f32 txc[24] = { + // up + tx1, 1-tz2, tx2, 1-tz1, + // down + tx1, tz1, tx2, tz2, + // right + tz1, 1-ty2, tz2, 1-ty1, + // left + 1-tz2, 1-ty2, 1-tz1, 1-ty1, + // back + 1-tx2, 1-ty2, 1-tx1, 1-ty1, + // front + tx1, 1-ty2, tx2, 1-ty1, + }; + makeCuboid(*material_current, &collector, c, box, txc); + } + } + break; } } } diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index d34dc3f..b050437 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -119,6 +119,7 @@ void content_mapnode_init() f->setAllTextures("stone.png"); f->setInventoryTextureCube("stone.png", "stone.png", "stone.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->often_contains_mineral = true; f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1"; @@ -132,6 +133,7 @@ void content_mapnode_init() f->setTexture(0, "grass.png"); f->setTexture(1, "mud.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1"; setDirtLikeDiggingProperties(f->digging_properties, 1.0); @@ -140,6 +142,7 @@ void content_mapnode_init() f = &content_features(i); f->setAllTextures("dirt.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1"; setDirtLikeDiggingProperties(f->digging_properties, 1.0); @@ -149,6 +152,7 @@ void content_mapnode_init() f->setAllTextures("mud.png"); f->setInventoryTextureCube("mud.png", "mud.png", "mud.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setDirtLikeDiggingProperties(f->digging_properties, 1.0); @@ -158,6 +162,7 @@ void content_mapnode_init() f->setAllTextures("sand.png"); f->setInventoryTextureCube("sand.png", "sand.png", "sand.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setDirtLikeDiggingProperties(f->digging_properties, 1.0); @@ -167,6 +172,7 @@ void content_mapnode_init() f->setAllTextures("gravel.png"); f->setInventoryTextureCube("gravel.png", "gravel.png", "gravel.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setDirtLikeDiggingProperties(f->digging_properties, 1.75); @@ -176,6 +182,7 @@ void content_mapnode_init() f->setAllTextures("sandstone.png"); f->setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 4"; setDirtLikeDiggingProperties(f->digging_properties, 1.0); @@ -185,6 +192,7 @@ void content_mapnode_init() f->setAllTextures("clay.png"); f->setInventoryTextureCube("clay.png", "clay.png", "clay.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("CraftItem lump_of_clay 4"); setDirtLikeDiggingProperties(f->digging_properties, 1.0); @@ -194,6 +202,7 @@ void content_mapnode_init() f->setAllTextures("brick.png"); f->setInventoryTextureCube("brick.png", "brick.png", "brick.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("CraftItem clay_brick 4"); setStoneLikeDiggingProperties(f->digging_properties, 1.0); @@ -205,6 +214,7 @@ void content_mapnode_init() f->setTexture(1, "tree_top.png"); f->setInventoryTextureCube("tree_top.png", "tree.png", "tree.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setWoodLikeDiggingProperties(f->digging_properties, 1.0); @@ -216,6 +226,7 @@ void content_mapnode_init() f->setTexture(1, "jungletree_top.png"); f->setInventoryTextureCube("jungletree_top.png", "jungletree.png", "jungletree.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; //f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setWoodLikeDiggingProperties(f->digging_properties, 1.0); @@ -226,6 +237,7 @@ void content_mapnode_init() f->used_texturenames["junglegrass.png"] = true; f->light_propagates = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_PLANTLIKE_LGE; //f->is_ground_content = true; f->air_equivalent = false; // grass grows underneath f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; @@ -238,6 +250,7 @@ void content_mapnode_init() f->light_propagates = true; //f->param_type = CPT_MINERAL; f->param_type = CPT_LIGHT; + f->draw_type = CDT_GLASSLIKE; //f->is_ground_content = true; if(new_style_leaves) { @@ -262,6 +275,7 @@ void content_mapnode_init() f->setTexture(1, "cactus_top.png"); f->setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setWoodLikeDiggingProperties(f->digging_properties, 0.75); @@ -272,6 +286,7 @@ void content_mapnode_init() f->used_texturenames["papyrus.png"] = true; f->light_propagates = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_PLANTLIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; f->solidness = 0; // drawn separately, makes no faces @@ -285,6 +300,7 @@ void content_mapnode_init() f->setTexture(1, "wood.png"); f->setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; setWoodLikeDiggingProperties(f->digging_properties, 0.75); @@ -293,6 +309,7 @@ void content_mapnode_init() f->light_propagates = true; f->sunlight_propagates = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_GLASSLIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; f->solidness = 0; // drawn separately, makes no faces @@ -305,6 +322,7 @@ void content_mapnode_init() f = &content_features(i); f->light_propagates = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_FENCELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; f->solidness = 0; // drawn separately, makes no faces @@ -319,6 +337,7 @@ void content_mapnode_init() f->used_texturenames["rail.png"] = true; f->light_propagates = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_RAILLIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; f->solidness = 0; // drawn separately, makes no faces @@ -332,6 +351,7 @@ void content_mapnode_init() f->used_texturenames["ladder.png"] = true; f->light_propagates = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_SIGNLIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; f->wall_mounted = true; @@ -346,6 +366,7 @@ void content_mapnode_init() f = &content_features(i); f->setAllTextures("borderstone.png"); f->setInventoryTextureCube("borderstone.png", "borderstone.png", "borderstone.png"); + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; if(f->initial_metadata == NULL) @@ -356,6 +377,7 @@ void content_mapnode_init() f = &content_features(i); f->setAllTextures("wood.png"); f->setInventoryTextureCube("wood.png", "wood.png", "wood.png"); + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setWoodLikeDiggingProperties(f->digging_properties, 0.75); @@ -364,6 +386,7 @@ void content_mapnode_init() f = &content_features(i); f->setAllTextures("mese.png"); f->setInventoryTextureCube("mese.png", "mese.png", "mese.png"); + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setStoneLikeDiggingProperties(f->digging_properties, 0.5); @@ -373,6 +396,7 @@ void content_mapnode_init() f->setAllTextures("cotton.png"); f->setInventoryTextureCube("cotton.png", "cotton.png", "cotton.png"); f->param_type = CPT_MINERAL; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setDirtLikeDiggingProperties(f->digging_properties, 1.0); @@ -380,6 +404,7 @@ void content_mapnode_init() i = CONTENT_AIR; f = &content_features(i); f->param_type = CPT_LIGHT; + f->draw_type = CDT_AIRLIKE; f->light_propagates = true; f->sunlight_propagates = true; f->solidness = 0; @@ -393,6 +418,7 @@ void content_mapnode_init() f = &content_features(i); f->setInventoryTextureCube("water.png", "water.png", "water.png"); f->param_type = CPT_LIGHT; + f->draw_type = CDT_LIQUID; f->light_propagates = true; f->solidness = 0; // Drawn separately, makes no faces f->visual_solidness = 1; @@ -456,6 +482,7 @@ void content_mapnode_init() #endif } f->param_type = CPT_LIGHT; + f->draw_type = CDT_LIQUID_SOURCE; f->light_propagates = true; f->walkable = false; f->pointable = false; @@ -491,6 +518,7 @@ void content_mapnode_init() f->setInventoryTextureCube("lava.png", "lava.png", "lava.png"); f->used_texturenames["lava.png"] = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_LIQUID; f->light_propagates = false; f->light_source = LIGHT_MAX-1; f->solidness = 0; // Drawn separately, makes no faces @@ -553,6 +581,7 @@ void content_mapnode_init() #endif } f->param_type = CPT_LIGHT; + f->draw_type = CDT_LIQUID_SOURCE; f->light_propagates = false; f->light_source = LIGHT_MAX-1; f->walkable = false; @@ -593,6 +622,7 @@ void content_mapnode_init() f->used_texturenames["torch_on_floor.png"] = true; f->used_texturenames["torch.png"] = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_TORCHLIKE; f->light_propagates = true; f->sunlight_propagates = true; f->solidness = 0; // drawn separately, makes no faces @@ -608,6 +638,7 @@ void content_mapnode_init() f->setInventoryTexture("sign_wall.png"); f->used_texturenames["sign_wall.png"] = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_SIGNLIKE; f->light_propagates = true; f->sunlight_propagates = true; f->solidness = 0; // drawn separately, makes no faces @@ -622,6 +653,7 @@ void content_mapnode_init() i = CONTENT_CHEST; f = &content_features(i); f->param_type = CPT_FACEDIR_SIMPLE; + f->draw_type = CDT_CUBELIKE; f->setAllTextures("chest_side.png"); f->setTexture(0, "chest_top.png"); f->setTexture(1, "chest_top.png"); @@ -636,6 +668,7 @@ void content_mapnode_init() i = CONTENT_LOCKABLE_CHEST; f = &content_features(i); f->param_type = CPT_FACEDIR_SIMPLE; + f->draw_type = CDT_CUBELIKE; f->setAllTextures("chest_side.png"); f->setTexture(0, "chest_top.png"); f->setTexture(1, "chest_top.png"); @@ -650,6 +683,7 @@ void content_mapnode_init() i = CONTENT_FURNACE; f = &content_features(i); f->param_type = CPT_FACEDIR_SIMPLE; + f->draw_type = CDT_CUBELIKE; f->setAllTextures("furnace_side.png"); f->setTexture(5, "furnace_front.png"); // Z- f->setInventoryTextureCube("furnace_side.png", "furnace_front.png", "furnace_side.png"); @@ -663,6 +697,7 @@ void content_mapnode_init() f->setAllTextures("cobble.png"); f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png"); f->param_type = CPT_NONE; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setStoneLikeDiggingProperties(f->digging_properties, 0.9); @@ -672,6 +707,7 @@ void content_mapnode_init() f->setAllTextures("mossycobble.png"); f->setInventoryTextureCube("mossycobble.png", "mossycobble.png", "mossycobble.png"); f->param_type = CPT_NONE; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setStoneLikeDiggingProperties(f->digging_properties, 0.8); @@ -681,6 +717,7 @@ void content_mapnode_init() f->setAllTextures("steel_block.png"); f->setInventoryTextureCube("steel_block.png", "steel_block.png", "steel_block.png"); f->param_type = CPT_NONE; + f->draw_type = CDT_CUBELIKE; f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; setStoneLikeDiggingProperties(f->digging_properties, 5.0); @@ -688,6 +725,7 @@ void content_mapnode_init() i = CONTENT_NC; f = &content_features(i); f->param_type = CPT_FACEDIR_SIMPLE; + f->draw_type = CDT_CUBELIKE; f->setAllTextures("nc_side.png"); f->setTexture(5, "nc_front.png"); // Z- f->setTexture(4, "nc_back.png"); // Z+ @@ -697,6 +735,7 @@ void content_mapnode_init() i = CONTENT_NC_RB; f = &content_features(i); + f->draw_type = CDT_CUBELIKE; f->setAllTextures("nc_rb.png"); f->setInventoryTextureCube("nc_rb.png", "nc_rb.png", "nc_rb.png"); f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; @@ -705,6 +744,7 @@ void content_mapnode_init() i = CONTENT_SAPLING; f = &content_features(i); f->param_type = CPT_LIGHT; + f->draw_type = CDT_PLANTLIKE; f->setAllTextures("sapling.png"); f->setInventoryTexture("sapling.png"); f->used_texturenames["sapling.png"] = true; @@ -720,6 +760,7 @@ void content_mapnode_init() f->setInventoryTexture("apple.png"); f->used_texturenames["apple.png"] = true; f->param_type = CPT_LIGHT; + f->draw_type = CDT_PLANTLIKE_SML; f->light_propagates = true; f->sunlight_propagates = true; f->solidness = 0; // drawn separately, makes no faces @@ -728,6 +769,495 @@ void content_mapnode_init() f->dug_item = std::string("CraftItem apple 1"); f->digging_properties.set("", DiggingProperties(true, 0.0, 0)); + // slabs + i = CONTENT_COBBLE_SLAB; + f = &content_features(i); + f->setAllTextures("cobble.png"); + f->setInventoryTextureSlab("cobble.png", "cobble.png", "cobble.png"); + f->param_type = CPT_NONE; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + setStoneLikeDiggingProperties(f->digging_properties, 0.9); + + i = CONTENT_MOSSYCOBBLE_SLAB; + f = &content_features(i); + f->setAllTextures("mossycobble.png"); + f->setInventoryTextureSlab("mossycobble.png", "mossycobble.png", "mossycobble.png"); + f->param_type = CPT_NONE; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + setStoneLikeDiggingProperties(f->digging_properties, 0.8); + + i = CONTENT_STONE_SLAB; + f = &content_features(i); + f->setAllTextures("stone.png"); + f->setInventoryTextureSlab("stone.png", "stone.png", "stone.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_WOOD_SLAB; + f = &content_features(i); + f->setAllTextures("wood.png"); + f->setInventoryTextureSlab("wood.png", "wood.png", "wood.png"); + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + setWoodLikeDiggingProperties(f->digging_properties, 0.75); + + i = CONTENT_JUNGLE_SLAB; + f = &content_features(i); + f->setAllTextures("junglewood.png"); + f->setInventoryTextureSlab("junglewood.png", "junglewood.png", "junglewood.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + //f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + setWoodLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_BRICK_SLAB; + f = &content_features(i); + f->setAllTextures("brick.png"); + f->setInventoryTextureSlab("brick.png", "brick.png", "brick.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("CraftItem clay_brick 4"); + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_SANDSTONE_SLAB; + f = &content_features(i); + f->setAllTextures("sandstone.png"); + f->setInventoryTextureSlab("sandstone.png", "sandstone.png", "sandstone.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 4"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + setDirtLikeDiggingProperties(f->digging_properties, 1.0); + + // upside down slabs + i = CONTENT_COBBLE_SLAB_UD; + f = &content_features(i); + f->setAllTextures("cobble.png"); + f->setInventoryTextureSlab("cobble.png", "cobble.png", "cobble.png"); + f->param_type = CPT_NONE; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 0.9); + + i = CONTENT_MOSSYCOBBLE_SLAB_UD; + f = &content_features(i); + f->setAllTextures("mossycobble.png"); + f->setInventoryTextureSlab("mossycobble.png", "mossycobble.png", "mossycobble.png"); + f->param_type = CPT_NONE; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 0.8); + + i = CONTENT_STONE_SLAB_UD; + f = &content_features(i); + f->setAllTextures("stone.png"); + f->setInventoryTextureSlab("stone.png", "stone.png", "stone.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_WOOD_SLAB_UD; + f = &content_features(i); + f->setAllTextures("wood.png"); + f->setInventoryTextureSlab("wood.png", "wood.png", "wood.png"); + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 0.75); + + i = CONTENT_JUNGLE_SLAB_UD; + f = &content_features(i); + f->setAllTextures("junglewood.png"); + f->setInventoryTextureSlab("junglewood.png", "junglewood.png", "junglewood.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + //f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_JUNGLE_SLAB)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_BRICK_SLAB_UD; + f = &content_features(i); + f->setAllTextures("brick.png"); + f->setInventoryTextureSlab("brick.png", "brick.png", "brick.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("CraftItem clay_brick 4"); + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_SANDSTONE_SLAB_UD; + f = &content_features(i); + f->setAllTextures("sandstone.png"); + f->setInventoryTextureSlab("sandstone.png", "sandstone.png", "sandstone.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 4"; + setDirtLikeDiggingProperties(f->digging_properties, 1.0); + + // stairs + i = CONTENT_COBBLE_STAIR; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("cobble.png"); + f->setInventoryTextureStair("cobble.png", "cobble.png", "cobble.png"); + f->param_type = CPT_NONE; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + f->addNodeBox(core::aabbox3d( + -0.5*BS, + 0., + 0., + 0.5*BS, + 0.5*BS, + 0.5*BS + )); + setStoneLikeDiggingProperties(f->digging_properties, 0.9); + + i = CONTENT_MOSSYCOBBLE_STAIR; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("mossycobble.png"); + f->setInventoryTextureStair("mossycobble.png", "mossycobble.png", "mossycobble.png"); + f->param_type = CPT_NONE; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + f->addNodeBox(core::aabbox3d( + -0.5*BS, + 0., + 0., + 0.5*BS, + 0.5*BS, + 0.5*BS + )); + setStoneLikeDiggingProperties(f->digging_properties, 0.8); + + i = CONTENT_STONE_STAIR; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("stone.png"); + f->setInventoryTextureStair("stone.png", "stone.png", "stone.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->often_contains_mineral = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + f->addNodeBox(core::aabbox3d( + -0.5*BS, + 0., + 0., + 0.5*BS, + 0.5*BS, + 0.5*BS + )); + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_WOOD_STAIR; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->draw_type = CDT_NODEBOX; + f->setAllTextures("wood.png"); + f->setInventoryTextureStair("wood.png", "wood.png", "wood.png"); + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + f->addNodeBox(core::aabbox3d( + -0.5*BS, + 0., + 0., + 0.5*BS, + 0.5*BS, + 0.5*BS + )); + setWoodLikeDiggingProperties(f->digging_properties, 0.75); + + i = CONTENT_JUNGLE_STAIR; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("junglewood.png"); + f->setInventoryTextureStair("junglewood.png", "junglewood.png", "junglewood.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + //f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + f->addNodeBox(core::aabbox3d( + -0.5*BS, + 0., + 0., + 0.5*BS, + 0.5*BS, + 0.5*BS + )); + setWoodLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_BRICK_STAIR; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("brick.png"); + f->setInventoryTextureStair("brick.png", "brick.png", "brick.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->is_ground_content = true; + f->dug_item = std::string("CraftItem clay_brick 4"); + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + f->addNodeBox(core::aabbox3d( + -0.5*BS, + 0., + 0., + 0.5*BS, + 0.5*BS, + 0.5*BS + )); + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_SANDSTONE_STAIR; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("sandstone.png"); + f->setInventoryTextureStair("sandstone.png", "sandstone.png", "sandstone.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 4"; + f->setNodeBox(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0, + 0.5*BS + )); + f->addNodeBox(core::aabbox3d( + -0.5*BS, + 0., + 0., + 0.5*BS, + 0.5*BS, + 0.5*BS + )); + setDirtLikeDiggingProperties(f->digging_properties, 1.0); + + // upside down stairs + i = CONTENT_COBBLE_STAIR_UD; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("cobble.png"); + f->setInventoryTextureStair("cobble.png", "cobble.png", "cobble.png"); + f->param_type = CPT_NONE; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE_STAIR)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 0.9); + + i = CONTENT_MOSSYCOBBLE_STAIR_UD; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("mossycobble.png"); + f->setInventoryTextureStair("mossycobble.png", "mossycobble.png", "mossycobble.png"); + f->param_type = CPT_NONE; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MOSSYCOBBLE_STAIR)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 0.8); + + i = CONTENT_STONE_STAIR_UD; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("stone.png"); + f->setInventoryTextureStair("stone.png", "stone.png", "stone.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_STONE_STAIR)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_WOOD_STAIR_UD; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("wood.png"); + f->setInventoryTextureStair("wood.png", "wood.png", "wood.png"); + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_WOOD_STAIR)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 0.75); + + i = CONTENT_JUNGLE_STAIR_UD; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("junglewood.png"); + f->setInventoryTextureStair("junglewood.png", "junglewood.png", "junglewood.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + //f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_JUNGLE_STAIR)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_BRICK_STAIR_UD; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("brick.png"); + f->setInventoryTextureStair("brick.png", "brick.png", "brick.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("CraftItem clay_brick 4"); + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_SANDSTONE_STAIR_UD; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("sandstone.png"); + f->setInventoryTextureStair("sandstone.png", "sandstone.png", "sandstone.png"); + f->param_type = CPT_MINERAL; + f->draw_type = CDT_NODEBOX; + f->solidness = 0; // drawn separately, makes no faces + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 4"; + setDirtLikeDiggingProperties(f->digging_properties, 1.0); + // NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp diff --git a/src/content_mapnode.h b/src/content_mapnode.h index b615819..fdf0e89 100644 --- a/src/content_mapnode.h +++ b/src/content_mapnode.h @@ -57,6 +57,14 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version); #define CONTENT_LAVA 32 #define CONTENT_LAVASOURCE 33 +// rays stuff +#define CONTENT_STONEBRICK 34 +#define CONTENT_STEELSTONEBRICK 35 +#define CONTENT_GLASSLIGHT 36 +#define CONTENT_WOODJUNGLE 37 +#define CONTENT_COALCHECKER 38 +#define CONTENT_BRICKGREEN 39 + // 0x800...0xfff (2048...4095): higher 4 bytes of param2 are not usable #define CONTENT_GRASS 0x800 //1 #define CONTENT_TREE 0x801 //4 @@ -64,7 +72,6 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version); #define CONTENT_FARM_DIRT 0x803 //6 #define CONTENT_MESE 0x804 //7 #define CONTENT_MUD 0x805 //8 -// used to be cloud #define CONTENT_COTTON 0x806 //10 #define CONTENT_BORDERSTONE 0x807 //11 #define CONTENT_WOOD 0x808 //12 @@ -87,5 +94,41 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version); #define CONTENT_APPLE 0x819 #define CONTENT_SAPLING 0x820 +// slabs +#define CONTENT_COBBLE_SLAB 0x821 +#define CONTENT_MOSSYCOBBLE_SLAB 0x822 +#define CONTENT_STONE_SLAB 0x823 +#define CONTENT_WOOD_SLAB 0x824 +#define CONTENT_JUNGLE_SLAB 0x825 +#define CONTENT_BRICK_SLAB 0x826 +#define CONTENT_SANDSTONE_SLAB 0x827 + +// stairs +#define CONTENT_COBBLE_STAIR 0x828 +#define CONTENT_MOSSYCOBBLE_STAIR 0x829 +#define CONTENT_STONE_STAIR 0x82a +#define CONTENT_WOOD_STAIR 0x82b +#define CONTENT_JUNGLE_STAIR 0x82c +#define CONTENT_BRICK_STAIR 0x82d +#define CONTENT_SANDSTONE_STAIR 0x82e + +// upside down slabs +#define CONTENT_COBBLE_SLAB_UD 0x831 +#define CONTENT_MOSSYCOBBLE_SLAB_UD 0x832 +#define CONTENT_STONE_SLAB_UD 0x833 +#define CONTENT_WOOD_SLAB_UD 0x834 +#define CONTENT_JUNGLE_SLAB_UD 0x835 +#define CONTENT_BRICK_SLAB_UD 0x836 +#define CONTENT_SANDSTONE_SLAB_UD 0x837 + +// upside down stairs +#define CONTENT_COBBLE_STAIR_UD 0x838 +#define CONTENT_MOSSYCOBBLE_STAIR_UD 0x839 +#define CONTENT_STONE_STAIR_UD 0x83a +#define CONTENT_WOOD_STAIR_UD 0x83b +#define CONTENT_JUNGLE_STAIR_UD 0x83c +#define CONTENT_BRICK_STAIR_UD 0x83d +#define CONTENT_SANDSTONE_STAIR_UD 0x83e + #endif diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 35efb1c..0508c9a 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -158,8 +158,9 @@ void ItemSAO::step(float dtime, bool send_recommended) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime); v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; + v3f accel_f = v3f(0,0,0); moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d, - box, dtime, pos_f, m_speed_f); + box, 0.0, dtime, pos_f, m_speed_f, accel_f); if(send_recommended == false) return; @@ -390,8 +391,9 @@ void RatSAO::step(float dtime, bool send_recommended) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime); v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; + v3f accel_f = v3f(0,0,0); moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d, - box, dtime, pos_f, m_speed_f); + box, 0.0, dtime, pos_f, m_speed_f, accel_f); // basicly 'die in lava' if (moveresult.touching_lethal) @@ -630,8 +632,9 @@ void Oerkki1SAO::step(float dtime, bool send_recommended) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);*/ v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; - moveresult = collisionMovePrecise(&m_env->getMap(), pos_max_d, - box, dtime, pos_f, m_speed_f); + v3f accel_f = v3f(0,0,0); + moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d, + box, 0.0, dtime, pos_f, m_speed_f, accel_f); if (moveresult.touching_lethal) { @@ -877,8 +880,9 @@ void FireflySAO::step(float dtime, bool send_recommended) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime); v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; + v3f accel_f = v3f(0,0,0); moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d, - box, dtime, pos_f, m_speed_f); + box, 0.0, dtime, pos_f, m_speed_f, accel_f); // basicly 'die in lava' if (moveresult.touching_lethal) diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 06dae59..47f7221 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -39,6 +39,40 @@ ContentFeatures::~ContentFeatures() #endif } +static std::vector transformNodeBox(const ContentFeatures &n, + const std::vector &nodebox) +{ + std::vector boxes; + // TODO: facedir! + int facedir = 0; + for(std::vector::const_iterator + i = nodebox.begin(); + i != nodebox.end(); i++) + { + aabb3f box = *i; + if (facedir == 1) { + box.MinEdge.rotateXZBy(-90); + box.MaxEdge.rotateXZBy(-90); + box.repair(); + }else if (facedir == 2) { + box.MinEdge.rotateXZBy(180); + box.MaxEdge.rotateXZBy(180); + box.repair(); + }else if (facedir == 3) { + box.MinEdge.rotateXZBy(90); + box.MaxEdge.rotateXZBy(90); + box.repair(); + } + boxes.push_back(box); + } + return boxes; +} + +std::vector ContentFeatures::getNodeBoxes() const +{ + return transformNodeBox(*this, nodeboxes); +} + #ifndef SERVER void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha) { @@ -88,6 +122,46 @@ void ContentFeatures::setInventoryTextureCube(std::string top, imgname_full += right; inventory_texture = g_texturesource->getTextureRaw(imgname_full); } + +void ContentFeatures::setInventoryTextureSlab(std::string top, + std::string left, std::string right) +{ + if(g_texturesource == NULL) + return; + + str_replace_char(top, '^', '&'); + str_replace_char(left, '^', '&'); + str_replace_char(right, '^', '&'); + + std::string imgname_full; + imgname_full += "[inventoryslab{"; + imgname_full += top; + imgname_full += "{"; + imgname_full += left; + imgname_full += "{"; + imgname_full += right; + inventory_texture = g_texturesource->getTextureRaw(imgname_full); +} + +void ContentFeatures::setInventoryTextureStair(std::string top, + std::string left, std::string right) +{ + if(g_texturesource == NULL) + return; + + str_replace_char(top, '^', '&'); + str_replace_char(left, '^', '&'); + str_replace_char(right, '^', '&'); + + std::string imgname_full; + imgname_full += "[inventorystair{"; + imgname_full += top; + imgname_full += "{"; + imgname_full += left; + imgname_full += "{"; + imgname_full += right; + inventory_texture = g_texturesource->getTextureRaw(imgname_full); +} #endif struct ContentFeatures g_content_features[MAX_CONTENT+1]; diff --git a/src/mapnode.h b/src/mapnode.h index c98294a..3eeab07 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -77,6 +77,26 @@ void init_mapnode(); //#define CONTENT_AIR 254 #define CONTENT_AIR 126 +/* + Draw types +*/ +enum ContentDrawType +{ + CDT_AIRLIKE, + CDT_CUBELIKE, + CDT_RAILLIKE, + CDT_PLANTLIKE, + CDT_PLANTLIKE_SML, + CDT_PLANTLIKE_LGE, + CDT_LIQUID, + CDT_LIQUID_SOURCE, + CDT_SIGNLIKE, + CDT_NODEBOX, + CDT_GLASSLIKE, + CDT_TORCHLIKE, + CDT_FENCELIKE +}; + /* Content feature list */ @@ -124,6 +144,7 @@ struct ContentFeatures video::SMaterial *special_material2; AtlasPointer *special_atlas; #endif + std::vector nodeboxes; // List of all block textures that have been used (value is dummy) // Exists on server too for cleaner code in content_mapnode.cpp @@ -131,6 +152,8 @@ struct ContentFeatures // Type of MapNode::param1 ContentParamType param_type; + // drawtype + ContentDrawType draw_type; // True for all ground-like things like stone and mud, false for eg. trees bool is_ground_content; bool light_propagates; @@ -202,8 +225,18 @@ struct ContentFeatures special_material = NULL; special_material2 = NULL; special_atlas = NULL; + nodeboxes.clear(); + nodeboxes.push_back(core::aabbox3d( + -0.5*BS, + -0.5*BS, + -0.5*BS, + 0.5*BS, + 0.5*BS, + 0.5*BS + )); #endif param_type = CPT_NONE; + draw_type = CDT_AIRLIKE; is_ground_content = false; light_propagates = false; sunlight_propagates = false; @@ -235,6 +268,26 @@ struct ContentFeatures ~ContentFeatures(); + /* + Bounding Box + */ + + /* + Gets list of node boxes (used for collision) + */ + std::vector getNodeBoxes() const; + + void setNodeBox(core::aabbox3d bb) + { + nodeboxes.clear(); + nodeboxes.push_back(bb); + } + + void addNodeBox(core::aabbox3d bb) + { + nodeboxes.push_back(bb); + } + /* Quickhands for simple materials */ @@ -278,11 +331,21 @@ struct ContentFeatures void setInventoryTextureCube(std::string top, std::string left, std::string right) {} + void setInventoryTextureSlab(std::string top, + std::string left, std::string right) + {} + void setInventoryTextureStair(std::string top, + std::string left, std::string right) + {} #else void setInventoryTexture(std::string imgname); void setInventoryTextureCube(std::string top, std::string left, std::string right); + void setInventoryTextureSlab(std::string top, + std::string left, std::string right); + void setInventoryTextureStair(std::string top, + std::string left, std::string right); #endif }; diff --git a/src/player.cpp b/src/player.cpp index 840a444..a39caeb 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -324,7 +324,7 @@ LocalPlayer::~LocalPlayer() } void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, - core::list *collision_info) + core::list *collision_info) { v3f position = getPosition(); v3f oldpos = position; @@ -338,12 +338,11 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, /* Calculate new position */ - position += m_speed * dtime; + position += m_speed * dtime/2; // Skip collision detection if a special movement mode is used bool free_move = g_settings->getBool("free_move"); - if(free_move) - { + if (free_move) { setPosition(position); return; } @@ -360,20 +359,15 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, */ try{ // If in water, the threshold of coming out is at higher y - if(in_water) - { + if (in_water) { v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS); in_water = content_liquid(map.getNode(pp).getContent()); - } // If not in water, the threshold of going in is at lower y - else - { + }else{ v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS); in_water = content_liquid(map.getNode(pp).getContent()); } - } - catch(InvalidPositionException &e) - { + }catch(InvalidPositionException &e) { in_water = false; } @@ -383,9 +377,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, try{ v3s16 pp = floatToInt(position + v3f(0,0,0), BS); in_water_stable = content_liquid(map.getNode(pp).getContent()); - } - catch(InvalidPositionException &e) - { + }catch(InvalidPositionException &e) { in_water_stable = false; } @@ -393,14 +385,12 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, Check if player is climbing */ - try { + try{ v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS); v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS); is_climbing = ((content_features(map.getNode(pp).getContent()).climbable || content_features(map.getNode(pp2).getContent()).climbable) && !free_move); - } - catch(InvalidPositionException &e) - { + }catch(InvalidPositionException &e) { is_climbing = false; } @@ -421,268 +411,98 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, // Maximum distance over border for sneaking f32 sneak_max = BS*0.4; - /* - If sneaking, player has larger collision radius to keep from - falling - */ - /*if(control.sneak) - player_radius = sneak_max + d*1.1;*/ - - /* - If sneaking, keep in range from the last walked node and don't - fall off from it - */ - if(control.sneak && m_sneak_node_exists) - { + if (control.sneak && m_sneak_node_exists) { f32 maxd = 0.5*BS + sneak_max; v3f lwn_f = intToFloat(m_sneak_node, BS); position.X = rangelim(position.X, lwn_f.X-maxd, lwn_f.X+maxd); position.Z = rangelim(position.Z, lwn_f.Z-maxd, lwn_f.Z+maxd); f32 min_y = lwn_f.Y + 0.5*BS; - if(position.Y < min_y) - { + if (position.Y < min_y) { position.Y = min_y; - //v3f old_speed = m_speed; - if(m_speed.Y < 0) m_speed.Y = 0; - - /*if(collision_info) - { - // Report fall collision - if(old_speed.Y < m_speed.Y - 0.1) - { - CollisionInfo info; - info.t = COLLISION_FALL; - info.speed = m_speed.Y - old_speed.Y; - collision_info->push_back(info); - } - }*/ } } /* Calculate player collision box (new and old) */ + core::aabbox3d playerbox( - position.X - player_radius, - position.Y - 0.0, - position.Z - player_radius, - position.X + player_radius, - position.Y + player_height, - position.Z + player_radius - ); - core::aabbox3d playerbox_old( - oldpos.X - player_radius, - oldpos.Y - 0.0, - oldpos.Z - player_radius, - oldpos.X + player_radius, - oldpos.Y + player_height, - oldpos.Z + player_radius + -player_radius, + 0.0, + -player_radius, + player_radius, + player_height, + player_radius ); + float player_stepheight = touching_ground ? (BS*0.6) : (BS*0.2); + + v3f accel_f = v3f(0,0,0); + + collisionMoveResult result = collisionMoveSimple(&map, + pos_max_d, playerbox, + player_stepheight, dtime, + position, + m_speed, + accel_f); + /* If the player's feet touch the topside of any node, this is set to true. Player is allowed to jump when this is true. */ - touching_ground = false; - - /*std::cout<<"Checking collisions for (" - < (" - < nodebox = getNodeBox(v3s16(x,y,z), BS); - - /* - See if the player is touching ground. - - Player touches ground if player's minimum Y is near node's - maximum Y and player's X-Z-area overlaps with the node's - X-Z-area. - - Use 0.15*BS so that it is easier to get on a node. - */ - if( - //fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < d - fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < 0.15*BS - && nodebox.MaxEdge.X-d > playerbox.MinEdge.X - && nodebox.MinEdge.X+d < playerbox.MaxEdge.X - && nodebox.MaxEdge.Z-d > playerbox.MinEdge.Z - && nodebox.MinEdge.Z+d < playerbox.MaxEdge.Z - ){ - touching_ground = true; - if(is_unloaded) - standing_on_unloaded = true; - } - - // If player doesn't intersect with node, ignore node. - if(playerbox.intersectsWithBox(nodebox) == false) - continue; - - /* - Go through every axis - */ - v3f dirs[3] = { - v3f(0,0,1), // back-front - v3f(0,1,0), // top-bottom - v3f(1,0,0), // right-left - }; - for(u16 i=0; i<3; i++) - { - /* - Calculate values along the axis - */ - f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]); - f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]); - f32 playermax = playerbox.MaxEdge.dotProduct(dirs[i]); - f32 playermin = playerbox.MinEdge.dotProduct(dirs[i]); - f32 playermax_old = playerbox_old.MaxEdge.dotProduct(dirs[i]); - f32 playermin_old = playerbox_old.MinEdge.dotProduct(dirs[i]); - - /* - Check collision for the axis. - Collision happens when player is going through a surface. - */ - /*f32 neg_d = d; - f32 pos_d = d; - // Make it easier to get on top of a node - if(i == 1) - neg_d = 0.15*BS; - bool negative_axis_collides = - (nodemax > playermin && nodemax <= playermin_old + neg_d - && m_speed.dotProduct(dirs[i]) < 0); - bool positive_axis_collides = - (nodemin < playermax && nodemin >= playermax_old - pos_d - && m_speed.dotProduct(dirs[i]) > 0);*/ - bool negative_axis_collides = - (nodemax > playermin && nodemax <= playermin_old + d - && m_speed.dotProduct(dirs[i]) < 0); - bool positive_axis_collides = - (nodemin < playermax && nodemin >= playermax_old - d - && m_speed.dotProduct(dirs[i]) > 0); - bool main_axis_collides = - negative_axis_collides || positive_axis_collides; - - /* - Check overlap of player and node in other axes - */ - bool other_axes_overlap = true; - for(u16 j=0; j<3; j++) - { - if(j == i) - continue; - f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]); - f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]); - f32 playermax = playerbox.MaxEdge.dotProduct(dirs[j]); - f32 playermin = playerbox.MinEdge.dotProduct(dirs[j]); - if(!(nodemax - d > playermin && nodemin + d < playermax)) - { - other_axes_overlap = false; - break; - } - } - - /* - If this is a collision, revert the position in the main - direction. - */ - if(other_axes_overlap && main_axis_collides) - { - //v3f old_speed = m_speed; - - m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i]; - position -= position.dotProduct(dirs[i]) * dirs[i]; - position += oldpos.dotProduct(dirs[i]) * dirs[i]; - - /*if(collision_info) - { - // Report fall collision - if(old_speed.Y < m_speed.Y - 0.1) - { - CollisionInfo info; - info.t = COLLISION_FALL; - info.speed = m_speed.Y - old_speed.Y; - collision_info->push_back(info); - } - }*/ - } - - } - } // xyz + touching_ground = result.touching_ground; /* Check the nodes under the player to see from which node the - player is sneaking from, if any. + player is sneaking from, if any. If the node from under + the player has been removed, the player falls. */ - { + v3s16 current_node = floatToInt(position - v3f(0,BS/2,0), BS); + if (m_sneak_node_exists && map.getNodeNoEx(m_old_node_below).getContent() == CONTENT_AIR && m_old_node_below_type != CONTENT_AIR) { + // Old node appears to have been removed; that is, + // it wasn't air before but now it is + m_refresh_sneak_node = false; + m_sneak_node_exists = false; + }else if (map.getNodeNoEx(current_node).getContent() != CONTENT_AIR) { + // We are on something, so make sure to recalculate the sneak + // node. + m_refresh_sneak_node = true; + } + + if (m_refresh_sneak_node) { v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,0), BS); v2f player_p2df(position.X, position.Z); f32 min_distance_f = 100000.0*BS; - // If already seeking from some node, compare to it. - /*if(m_sneak_node_exists) - { - v3f sneaknode_pf = intToFloat(m_sneak_node, BS); - v2f sneaknode_p2df(sneaknode_pf.X, sneaknode_pf.Z); - f32 d_horiz_f = player_p2df.getDistanceFrom(sneaknode_p2df); - f32 d_vert_f = fabs(sneaknode_pf.Y + BS*0.5 - position.Y); - // Ignore if player is not on the same level (likely dropped) - if(d_vert_f < 0.15*BS) - min_distance_f = d_horiz_f; - }*/ + v3s16 new_sneak_node = m_sneak_node; - for(s16 x=-1; x<=1; x++) - for(s16 z=-1; z<=1; z++) + for (s16 x=-1; x<=1; x++) + for (s16 z=-1; z<=1; z++) { v3s16 p = pos_i_bottom + v3s16(x,0,z); v3f pf = intToFloat(p, BS); v2f node_p2df(pf.X, pf.Z); f32 distance_f = player_p2df.getDistanceFrom(node_p2df); f32 max_axis_distance_f = MYMAX( - fabs(player_p2df.X-node_p2df.X), - fabs(player_p2df.Y-node_p2df.Y)); + fabs(player_p2df.X-node_p2df.X), + fabs(player_p2df.Y-node_p2df.Y)); - if(distance_f > min_distance_f || - max_axis_distance_f > 0.5*BS + sneak_max + 0.1*BS) + if (distance_f > min_distance_f || max_axis_distance_f > 0.5*BS + sneak_max + 0.1*BS) continue; try{ // The node to be sneaked on has to be walkable - if(content_walkable(map.getNode(p).getContent()) == false) + if (content_features(map.getNode(p).getContent()).walkable == false) continue; // And the node above it has to be nonwalkable - if(content_walkable(map.getNode(p+v3s16(0,1,0)).getContent()) == true) + if (content_features(map.getNode(p+v3s16(0,1,0)).getContent()).walkable == true) continue; - } - catch(InvalidPositionException &e) - { + }catch(InvalidPositionException &e) { continue; } @@ -692,22 +512,14 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, bool sneak_node_found = (min_distance_f < 100000.0*BS*0.9); - if(control.sneak && m_sneak_node_exists) - { - if(sneak_node_found) - m_sneak_node = new_sneak_node; - } - else - { - m_sneak_node = new_sneak_node; - m_sneak_node_exists = sneak_node_found; - } + m_sneak_node = new_sneak_node; + m_sneak_node_exists = sneak_node_found; /* If sneaking, the player's collision box can be in air, so this has to be set explicitly */ - if(sneak_node_found && control.sneak) + if (sneak_node_found && control.sneak) touching_ground = true; } @@ -722,7 +534,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, if(collision_info) { // Report fall collision - if(old_speed.Y < m_speed.Y - 0.1 && !standing_on_unloaded) + if(old_speed.Y < m_speed.Y - 0.1 && !result.standing_on_unloaded) { CollisionInfo info; info.t = COLLISION_FALL; diff --git a/src/player.h b/src/player.h index ff6ade7..6b7bda2 100644 --- a/src/player.h +++ b/src/player.h @@ -367,8 +367,12 @@ public: private: // This is used for determining the sneaking range v3s16 m_sneak_node; + bool m_refresh_sneak_node; // Whether the player is allowed to sneak bool m_sneak_node_exists; + v3s16 m_old_node_below; + content_t m_old_node_below_type; + }; #endif // !SERVER diff --git a/src/tile.cpp b/src/tile.cpp index 0a2188d..94b45e6 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -1349,6 +1349,233 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, image->drop(); } } + /* + [inventoryslab{topimage{leftimage{rightimage + In every subimage, replace ^ with &. + Create an "inventory slab". + NOTE: This should be used only on its own. + Example (a grass slab (not actually used in game): + "[inventoryslab{grass.png{mud.png&grass_side.png{mud.png&grass_side.png" + */ + else if(part_of_name.substr(0,14) == "[inventoryslab") + { + if(baseimg != NULL) + { + errorstream<<"generate_image(): baseimg!=NULL " + <<"for part_of_name=\""<addTexture( + (imagename_top + "__temp__").c_str(), img_top); + video::ITexture *texture_left = driver->addTexture( + (imagename_left + "__temp__").c_str(), img_left); + video::ITexture *texture_right = driver->addTexture( + (imagename_right + "__temp__").c_str(), img_right); + assert(texture_top && texture_left && texture_right); + + // Drop images + img_top->drop(); + img_left->drop(); + img_right->drop(); + + /* + Draw a cube mesh into a render target texture + */ + scene::IMesh* cube = createCubeMesh(v3f(1, 0.5, 1)); + setMeshColor(cube, video::SColor(255, 255, 255, 255)); + cube->getMeshBuffer(0)->getMaterial().setTexture(0, texture_top); + cube->getMeshBuffer(1)->getMaterial().setTexture(0, texture_top); + cube->getMeshBuffer(2)->getMaterial().setTexture(0, texture_right); + cube->getMeshBuffer(3)->getMaterial().setTexture(0, texture_right); + cube->getMeshBuffer(4)->getMaterial().setTexture(0, texture_left); + cube->getMeshBuffer(5)->getMaterial().setTexture(0, texture_left); + + core::dimension2d dim(64,64); + std::string rtt_texture_name = part_of_name + "_RTT"; + + v3f camera_position(0, 1.0, -1.5); + camera_position.rotateXZBy(45); + v3f camera_lookat(0, 0, 0); + core::CMatrix4 camera_projection_matrix; + // Set orthogonal projection + camera_projection_matrix.buildProjectionMatrixOrthoLH( + 1.65, 1.65, 0, 100); + + video::SColorf ambient_light(0.2,0.2,0.2); + v3f light_position(10, 100, -50); + video::SColorf light_color(0.5,0.5,0.5); + f32 light_radius = 1000; + + video::ITexture *rtt = generateTextureFromMesh( + cube, device, dim, rtt_texture_name, + camera_position, + camera_lookat, + camera_projection_matrix, + ambient_light, + light_position, + light_color, + light_radius); + + // Drop mesh + cube->drop(); + + // Free textures of images + driver->removeTexture(texture_top); + driver->removeTexture(texture_left); + driver->removeTexture(texture_right); + + if(rtt == NULL) + { + baseimg = generate_image_from_scratch( + imagename_top, device); + return true; + } + + // Create image of render target + video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim); + assert(image); + + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); + + if(image) + { + image->copyTo(baseimg); + image->drop(); + } + } + /* + [inventorystair{topimage{leftimage{rightimage + In every subimage, replace ^ with &. + Create an "inventory stair". + NOTE: This should be used only on its own. + Example (a grass stair (not actually used in game): + "[inventorystair{grass.png{mud.png&grass_side.png{mud.png&grass_side.png" + TODO: not implemented, only creates a cube + */ + else if(part_of_name.substr(0,15) == "[inventorystair") + { + if(baseimg != NULL) + { + errorstream<<"generate_image(): baseimg!=NULL " + <<"for part_of_name=\""<addTexture( + (imagename_top + "__temp__").c_str(), img_top); + video::ITexture *texture_left = driver->addTexture( + (imagename_left + "__temp__").c_str(), img_left); + video::ITexture *texture_right = driver->addTexture( + (imagename_right + "__temp__").c_str(), img_right); + assert(texture_top && texture_left && texture_right); + + // Drop images + img_top->drop(); + img_left->drop(); + img_right->drop(); + + /* + Draw a cube mesh into a render target texture + */ + scene::IMesh* cube = createCubeMesh(v3f(1, 1, 1)); + setMeshColor(cube, video::SColor(255, 255, 255, 255)); + cube->getMeshBuffer(0)->getMaterial().setTexture(0, texture_top); + cube->getMeshBuffer(1)->getMaterial().setTexture(0, texture_top); + cube->getMeshBuffer(2)->getMaterial().setTexture(0, texture_right); + cube->getMeshBuffer(3)->getMaterial().setTexture(0, texture_right); + cube->getMeshBuffer(4)->getMaterial().setTexture(0, texture_left); + cube->getMeshBuffer(5)->getMaterial().setTexture(0, texture_left); + + core::dimension2d dim(64,64); + std::string rtt_texture_name = part_of_name + "_RTT"; + + v3f camera_position(0, 1.0, -1.5); + camera_position.rotateXZBy(45); + v3f camera_lookat(0, 0, 0); + core::CMatrix4 camera_projection_matrix; + // Set orthogonal projection + camera_projection_matrix.buildProjectionMatrixOrthoLH( + 1.65, 1.65, 0, 100); + + video::SColorf ambient_light(0.2,0.2,0.2); + v3f light_position(10, 100, -50); + video::SColorf light_color(0.5,0.5,0.5); + f32 light_radius = 1000; + + video::ITexture *rtt = generateTextureFromMesh( + cube, device, dim, rtt_texture_name, + camera_position, + camera_lookat, + camera_projection_matrix, + ambient_light, + light_position, + light_color, + light_radius); + + // Drop mesh + cube->drop(); + + // Free textures of images + driver->removeTexture(texture_top); + driver->removeTexture(texture_left); + driver->removeTexture(texture_right); + + if(rtt == NULL) + { + baseimg = generate_image_from_scratch( + imagename_top, device); + return true; + } + + // Create image of render target + video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim); + assert(image); + + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); + + if(image) + { + image->copyTo(baseimg); + image->drop(); + } + } else { infostream<<"generate_image(): Invalid "