redo collision, implement content draw type, rewrite mesh generator, implement nodeboxes, implement stairs and slabs
This commit is contained in:
parent
f61f0e2064
commit
3359eaf406
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
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<f32> &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<aabb3f> &staticboxes,
|
||||
const aabb3f &movingbox,
|
||||
f32 y_increase, f32 d)
|
||||
{
|
||||
//TimeTaker tt("wouldCollideWithCeiling");
|
||||
|
||||
assert(y_increase >= 0);
|
||||
|
||||
for(std::vector<aabb3f>::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!"<<std::endl;
|
||||
dtime = 0.5;
|
||||
}
|
||||
speed_f += accel_f * dtime;
|
||||
|
||||
// If there is no speed, there are no collisions
|
||||
if(speed_f.getLength() == 0)
|
||||
return result;
|
||||
|
||||
/*
|
||||
Calculate new position
|
||||
Collect node boxes in movement range
|
||||
*/
|
||||
pos_f += speed_f * dtime;
|
||||
std::vector<aabb3f> cboxes;
|
||||
std::vector<bool> is_unloaded;
|
||||
std::vector<bool> is_step_up;
|
||||
std::vector<v3s16> 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<aabb3f> nodeboxes = f.getNodeBoxes();
|
||||
for(std::vector<aabb3f>::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<f32> box = box_0;
|
||||
box.MaxEdge += pos_f;
|
||||
box.MinEdge += pos_f;
|
||||
core::aabbox3d<f32> 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"<<std::endl;
|
||||
dtime = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Doing nothing here will block the object from
|
||||
// walking over map borders
|
||||
}
|
||||
|
||||
/*
|
||||
Go through every node around the object
|
||||
TODO: Calculate the range of nodes that need to be checked
|
||||
*/
|
||||
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
||||
{
|
||||
try{
|
||||
// Object collides into walkable nodes
|
||||
MapNode n = map->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<f32> 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<f32> &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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,42 +21,57 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define COLLISION_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include <vector>
|
||||
|
||||
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<f32> &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<f32> &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<CollisionInfo> 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
|
||||
|
||||
|
|
|
@ -61,6 +61,8 @@ typedef core::vector2d<s32> v2s32;
|
|||
typedef core::vector2d<u32> v2u32;
|
||||
typedef core::vector2d<f32> v2f32;
|
||||
|
||||
typedef core::aabbox3d<f32> aabb3f;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
typedef unsigned long long u64;
|
||||
|
|
|
@ -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; i<defs_init; i++) {
|
||||
|
|
|
@ -40,82 +40,65 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
// If you specified 0,0,1,1 for each face, that would be the
|
||||
// same as passing NULL.
|
||||
void makeCuboid(video::SMaterial &material, MeshCollector *collector,
|
||||
AtlasPointer* pa, video::SColor &c,
|
||||
v3f &pos, f32 rx, f32 ry, f32 rz, f32* txc)
|
||||
video::SColor &c, const aabb3f &box, const f32* txc)
|
||||
{
|
||||
f32 tu0=pa->x0();
|
||||
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<aabb3f> boxes = content_features(n).getNodeBoxes();
|
||||
for(std::vector<aabb3f>::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<f32>(
|
||||
-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<f32>(
|
||||
-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<f32>(
|
||||
-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<f32>(
|
||||
-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<f32>(
|
||||
-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<f32>(
|
||||
-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<f32>(
|
||||
-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<f32>(
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
0.5*BS,
|
||||
0,
|
||||
0.5*BS
|
||||
));
|
||||
f->addNodeBox(core::aabbox3d<f32>(
|
||||
-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<f32>(
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
0.5*BS,
|
||||
0,
|
||||
0.5*BS
|
||||
));
|
||||
f->addNodeBox(core::aabbox3d<f32>(
|
||||
-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<f32>(
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
0.5*BS,
|
||||
0,
|
||||
0.5*BS
|
||||
));
|
||||
f->addNodeBox(core::aabbox3d<f32>(
|
||||
-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<f32>(
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
0.5*BS,
|
||||
0,
|
||||
0.5*BS
|
||||
));
|
||||
f->addNodeBox(core::aabbox3d<f32>(
|
||||
-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<f32>(
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
0.5*BS,
|
||||
0,
|
||||
0.5*BS
|
||||
));
|
||||
f->addNodeBox(core::aabbox3d<f32>(
|
||||
-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<f32>(
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
0.5*BS,
|
||||
0,
|
||||
0.5*BS
|
||||
));
|
||||
f->addNodeBox(core::aabbox3d<f32>(
|
||||
-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<f32>(
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
-0.5*BS,
|
||||
0.5*BS,
|
||||
0,
|
||||
0.5*BS
|
||||
));
|
||||
f->addNodeBox(core::aabbox3d<f32>(
|
||||
-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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -39,6 +39,40 @@ ContentFeatures::~ContentFeatures()
|
|||
#endif
|
||||
}
|
||||
|
||||
static std::vector<aabb3f> transformNodeBox(const ContentFeatures &n,
|
||||
const std::vector<aabb3f> &nodebox)
|
||||
{
|
||||
std::vector<aabb3f> boxes;
|
||||
// TODO: facedir!
|
||||
int facedir = 0;
|
||||
for(std::vector<aabb3f>::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<aabb3f> 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];
|
||||
|
|
|
@ -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<aabb3f> 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<f32>(
|
||||
-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<aabb3f> getNodeBoxes() const;
|
||||
|
||||
void setNodeBox(core::aabbox3d<f32> bb)
|
||||
{
|
||||
nodeboxes.clear();
|
||||
nodeboxes.push_back(bb);
|
||||
}
|
||||
|
||||
void addNodeBox(core::aabbox3d<f32> 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
|
||||
};
|
||||
|
||||
|
|
304
src/player.cpp
304
src/player.cpp
|
@ -324,7 +324,7 @@ LocalPlayer::~LocalPlayer()
|
|||
}
|
||||
|
||||
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
core::list<CollisionInfo> *collision_info)
|
||||
core::list<CollisionInfo> *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<f32> 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<f32> 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 ("
|
||||
<<oldpos_i.X<<","<<oldpos_i.Y<<","<<oldpos_i.Z
|
||||
<<") -> ("
|
||||
<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z
|
||||
<<"):"<<std::endl;*/
|
||||
|
||||
bool standing_on_unloaded = false;
|
||||
|
||||
/*
|
||||
Go through every node around the player
|
||||
*/
|
||||
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
||||
{
|
||||
bool is_unloaded = false;
|
||||
try{
|
||||
// Player collides into walkable nodes
|
||||
if(content_walkable(map.getNode(v3s16(x,y,z)).getContent()) == false)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
is_unloaded = true;
|
||||
// Doing nothing here will block the player from
|
||||
// walking over map borders
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> 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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
227
src/tile.cpp
227
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=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
str_replace_char(part_of_name, '&', '^');
|
||||
Strfnd sf(part_of_name);
|
||||
sf.next("{");
|
||||
std::string imagename_top = sf.next("{");
|
||||
std::string imagename_left = sf.next("{");
|
||||
std::string imagename_right = sf.next("{");
|
||||
|
||||
// Generate images for the faces of the cube
|
||||
video::IImage *img_top = generate_image_from_scratch(
|
||||
imagename_top, device);
|
||||
video::IImage *img_left = generate_image_from_scratch(
|
||||
imagename_left, device);
|
||||
video::IImage *img_right = generate_image_from_scratch(
|
||||
imagename_right, device);
|
||||
assert(img_top && img_left && img_right);
|
||||
|
||||
// Create textures from images
|
||||
video::ITexture *texture_top = driver->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<u32> 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<f32> 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=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
str_replace_char(part_of_name, '&', '^');
|
||||
Strfnd sf(part_of_name);
|
||||
sf.next("{");
|
||||
std::string imagename_top = sf.next("{");
|
||||
std::string imagename_left = sf.next("{");
|
||||
std::string imagename_right = sf.next("{");
|
||||
|
||||
// Generate images for the faces of the cube
|
||||
video::IImage *img_top = generate_image_from_scratch(
|
||||
imagename_top, device);
|
||||
video::IImage *img_left = generate_image_from_scratch(
|
||||
imagename_left, device);
|
||||
video::IImage *img_right = generate_image_from_scratch(
|
||||
imagename_right, device);
|
||||
assert(img_top && img_left && img_right);
|
||||
|
||||
// Create textures from images
|
||||
video::ITexture *texture_top = driver->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<u32> 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<f32> 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 "
|
||||
|
|
Loading…
Reference in New Issue