builtin/voxelworld: WIP

This commit is contained in:
Perttu Ahola 2014-10-13 16:14:29 +03:00
parent 1c7ee8ddcb
commit 6402c5c246
6 changed files with 166 additions and 12 deletions

View File

@ -529,10 +529,10 @@ struct Module: public interface::Module, public voxelworld::Interface
n->SetVar(StringHash("buildat_voxel_data"), Variant(
PODVector<uint8_t>((const uint8_t*)data.c_str(), data.size())));
// There is no collision shape initially, but add the components now
// There are no collision shapes initially, but add the rigid body now
RigidBody *body = n->CreateComponent<RigidBody>(LOCAL);
body->SetFriction(0.75f);
CollisionShape *shape = n->CreateComponent<CollisionShape>(LOCAL);
//CollisionShape *shape = n->CreateComponent<CollisionShape>(LOCAL);
}
void create_section(Section &section)
@ -752,11 +752,14 @@ struct Module: public interface::Module, public voxelworld::Interface
// TODO: Create multiple box collision shapes insteade of one mesh;
// vertical voxel sectors should work well enough maybe
SharedPtr<Model> model(interface::
create_voxel_physics_model(context, *volume,
m_voxel_reg.get()));
CollisionShape *shape = n->CreateComponent<CollisionShape>();
shape->SetBox(Vector3(10, 0, 10));
CollisionShape *shape = n->GetComponent<CollisionShape>();
/*SharedPtr<Model> model(interface::
create_voxel_physics_model(context, *volume,
m_voxel_reg.get()));*/
/*CollisionShape *shape = n->GetComponent<CollisionShape>();
if(model){
log_v(MODULE, "Chunk " PV3I_FORMAT " has collision shape",
PV3I_PARAMS(chunk_p));
@ -767,7 +770,7 @@ struct Module: public interface::Module, public voxelworld::Interface
log_v(MODULE, "Chunk " PV3I_FORMAT " does not have collision shape",
PV3I_PARAMS(chunk_p));
shape->ReleaseShape();
}
}*/
});
}

View File

@ -28,6 +28,7 @@ zone.fogEnd = 300
-- Add a node that the player can use to walk around with
local player_node = scene:CreateChild("Player")
--player_node.position = magic.Vector3(0, 30, 0)
player_node.position = magic.Vector3(55, 30, 40)
---[[
local body = player_node:CreateComponent("RigidBody")
@ -129,10 +130,10 @@ magic.SubscribeToEvent("Update", function(event_type, event_data)
--if magic.input:GetKeyPress(magic.KEY_SPACE) then
if magic.input:GetKeyDown(magic.KEY_SPACE) then
if player_touches_ground and
math.abs(body.linearVelocity.y) < JUMP_SPEED then
--if player_touches_ground and
-- math.abs(body.linearVelocity.y) < JUMP_SPEED then
wanted_v.y = wanted_v.y + JUMP_SPEED
end
--end
end
if magic.input:GetKeyDown(magic.KEY_SHIFT) then
wanted_v.y = wanted_v.y - MOVE_SPEED

View File

@ -204,6 +204,11 @@ struct Module: public interface::Module
ivoxelworld->set_voxel(p, VoxelInstance(1));
continue;
}
if(x > 18 && x < 25 && z >= 32 && z <= 37 &&
y > 20 && y < 25){
ivoxelworld->set_voxel(p, VoxelInstance(1));
continue;
}
double a = interface::NoisePerlin2D(&np, x, z, 0);
if(y < a+5){
ivoxelworld->set_voxel(p, VoxelInstance(2));

View File

@ -21,7 +21,9 @@
#include <Context.h>
#include <ResourceCache.h>
#include <Texture2D.h> // Allows cast to Texture
#include <CollisionShape.h>
#pragma GCC diagnostic pop
#include <climits>
#define MODULE "mesh"
namespace magic = Urho3D;
@ -524,5 +526,131 @@ void set_voxel_geometry(CustomGeometry *cg, Context *context,
cg->Commit();
}
void set_voxel_physics_boxes(Node *node, Context *context,
pv::RawVolume<VoxelInstance> &volume_orig,
VoxelRegistry *voxel_reg)
{
PODVector<CollisionShape*> previous_shapes;
node->GetComponents<CollisionShape>(previous_shapes);
for(size_t i = 0; i < previous_shapes.Size(); i++){
node->RemoveComponent(previous_shapes[i]);
}
int w = volume_orig.getWidth() - 2;
int h = volume_orig.getHeight() - 2;
int d = volume_orig.getDepth() - 2;
auto region = volume_orig.getEnclosingRegion();
auto &lc = region.getLowerCorner();
auto &uc = region.getUpperCorner();
// Create a new volume which only holds the solidity of the voxels
pv::RawVolume<uint8_t> volume(region);
for(int x = lc.getX(); x <= uc.getX(); x++){
for(int y = lc.getY(); y <= uc.getY(); y++){
for(int z = lc.getZ(); z <= uc.getZ(); z++){
VoxelInstance v_orig = volume_orig.getVoxelAt(x, y, z);
const interface::CachedVoxelDefinition *def =
voxel_reg->get_cached(v_orig);
uint8_t v = (def && def->physically_solid);
volume.setVoxelAt(x, y, z, v);
}
}
}
// Create minimal number of boxes to fill the solid voxels. Boxes can
// overlap. When a box is added, its voxels are set to value 2 in the
// temporary volume.
for(int z0 = lc.getZ(); z0 <= uc.getZ(); z0++){
// Loop until this z0 plane is done, then handle the next one
for(;;){
// Find a solid non-covered voxel (v=1) on the z0 plane
int x0 = INT_MAX;
int y0 = INT_MAX;
for(int x = lc.getX(); x <= uc.getX(); x++){
for(int y = lc.getY(); y <= uc.getY(); y++){
uint8_t v = volume.getVoxelAt(x, y, z0);
if(v == 1){
x0 = x;
y0 = y;
goto found_non_covered_voxel;
}
}
}
break; // Done
found_non_covered_voxel:
// Stretch this box first in x, then y and then z to be as large as
// possible without covering any non-solid voxels
int x1 = x0;
int y1 = y0;
int z1 = z0;
for(;;){
x1++;
for(int y = y0; y <= y1; y++){
for(int z = z0; z <= z1; z++){
uint8_t v = volume.getVoxelAt(x1, y, z);
if(v == 0)
goto x_plane_does_not_fit;
}
}
continue; // Fits
x_plane_does_not_fit:
x1--;
break;
}
for(;;){
y1++;
for(int x = x0; x <= x1; x++){
for(int z = z0; z <= z1; z++){
uint8_t v = volume.getVoxelAt(x, y1, z);
if(v == 0)
goto y_plane_does_not_fit;
}
}
continue; // Fits
y_plane_does_not_fit:
y1--;
break;
}
for(;;){
z1++;
for(int x = x0; x <= x1; x++){
for(int y = y0; y <= y1; y++){
uint8_t v = volume.getVoxelAt(x, y, z1);
if(v == 0)
goto z_plane_does_not_fit;
}
}
continue; // Fits
z_plane_does_not_fit:
z1--;
break;
}
// Now we have a box; set the voxels to 2
for(int x = x0; x <= x1; x++){
for(int y = y0; y <= y1; y++){
for(int z = z0; z <= z1; z++){
volume.setVoxelAt(x, y, z, 2);
}
}
}
// Create the box
CollisionShape *shape =
node->CreateComponent<CollisionShape>();
shape->SetBox(Vector3(
x1 - x0 + 1,
y1 - y0 + 1,
z1 - z0 + 1
));
shape->SetPosition(Vector3(
(x0 + x1)/2.0f - w/2 - 0.5f,
(y0 + y1)/2.0f - h/2 - 0.5f,
(z0 + z1)/2.0f - d/2 - 0.5f
));
}
}
}
} // namespace interface
// vim: set noet ts=4 sw=4:

View File

@ -10,6 +10,7 @@ namespace Urho3D
class Context;
class Model;
class CustomGeometry;
class Node;
}
namespace interface
@ -20,12 +21,14 @@ namespace interface
// Create a model from a string; eg. (2, 2, 2, "11101111")
Model* create_simple_voxel_model(Context *context, int w, int h, int d,
const ss_ &source_data);
// Create a model from 8-bit voxel data, using a voxel registry, without
// textures or normals, based on the physically_solid flag.
// Returns nullptr if there is no geometry
Model* create_8bit_voxel_physics_model(Context *context,
int w, int h, int d, const ss_ &source_data,
VoxelRegistry *voxel_reg);
// Set custom geometry from 8-bit voxel data, using a voxel registry
void set_8bit_voxel_geometry(CustomGeometry *cg, Context *context,
int w, int h, int d, const ss_ &source_data,
@ -39,11 +42,16 @@ namespace interface
Model* create_voxel_physics_model(Context *context,
pv::RawVolume<VoxelInstance> &volume,
VoxelRegistry *voxel_reg);
// Set custom geometry from voxel volume, using a voxel registry
// Volume should be padded by one voxel on each edge
// NOTE: volume is non-const due to PolyVox deficiency
void set_voxel_geometry(CustomGeometry *cg, Context *context,
pv::RawVolume<VoxelInstance> &volume,
VoxelRegistry *voxel_reg);
void set_voxel_physics_boxes(Node *node, Context *context,
pv::RawVolume<VoxelInstance> &volume,
VoxelRegistry *voxel_reg);
}
// vim: set noet ts=4 sw=4:

View File

@ -162,7 +162,7 @@ static int l_set_voxel_geometry(lua_State *L)
cg->SetCastShadows(true);
// TODO: Don't do this here; allow caller to do this explicitly
SharedPtr<Model> model(interface::
/*SharedPtr<Model> model(interface::
create_voxel_physics_model(context, *volume, voxel_reg));
RigidBody *body = node->GetOrCreateComponent<RigidBody>(LOCAL);
body->SetFriction(0.7);
@ -173,7 +173,16 @@ static int l_set_voxel_geometry(lua_State *L)
//log_w(MODULE, "CollisionShape disabled");
} else {
shape->ReleaseShape();
}
}*/
/*RigidBody *body = node->GetOrCreateComponent<RigidBody>(LOCAL);
body->SetFriction(0.7);
CollisionShape *shape = node->CreateComponent<CollisionShape>();
shape->SetBox(Vector3(10, 0, 10));*/
// TODO: Don't do this here; allow caller to do this explicitly
RigidBody *body = node->GetOrCreateComponent<RigidBody>(LOCAL);
body->SetFriction(0.7);
interface::set_voxel_physics_boxes(node, context, *volume, voxel_reg);
return 0;
}