Demos big update
-Added some more math functions -fixed many memory leaks -added AABB and BVHTree support to collision.d *BVHTree has only incrementally adding entities implemented by now (and bad BottomUp algorithm) *ECS Systems use two trees, one for static and one for dynamic entities, dynamic BVH is builded every frame from scratch by now -BrickBreaker now uses BVHTree to collision detection *balls only use tree for checks (they aren't adding to tree) -fixed bug leading to crash
This commit is contained in:
parent
96bbcb9956
commit
64dc099e0a
9 changed files with 973 additions and 70 deletions
|
|
@ -117,12 +117,12 @@ struct Launcher
|
||||||
gui_manager.clear();
|
gui_manager.clear();
|
||||||
//launcher.ent
|
//launcher.ent
|
||||||
|
|
||||||
if(this.demo.deinitialize)this.demo.deinitialize();
|
|
||||||
|
|
||||||
manager.begin();
|
manager.begin();
|
||||||
manager.update("clean");
|
manager.update("clean");
|
||||||
manager.end();
|
manager.end();
|
||||||
|
|
||||||
|
if(this.demo.deinitialize)this.demo.deinitialize();
|
||||||
|
|
||||||
foreach(ref system; manager.systems)
|
foreach(ref system; manager.systems)
|
||||||
{
|
{
|
||||||
if(system.id != CountSystem.system_id && system.id != CleanSystem.system_id)system.disable();
|
if(system.id != CountSystem.system_id && system.id != CleanSystem.system_id)system.disable();
|
||||||
|
|
@ -946,12 +946,19 @@ void mainLoop(void* arg)
|
||||||
|
|
||||||
void quit()
|
void quit()
|
||||||
{
|
{
|
||||||
|
import game_core.rendering : TexCoordsManager;
|
||||||
launcher.gui_manager.clear();
|
launcher.gui_manager.clear();
|
||||||
Mallocator.dispose(launcher.gui_manager);
|
Mallocator.dispose(launcher.gui_manager);
|
||||||
|
|
||||||
|
if(launcher.demo.deinitialize)launcher.demo.deinitialize();
|
||||||
|
|
||||||
launcher.manager.destroy();
|
launcher.manager.destroy();
|
||||||
launcher.manager = null;
|
launcher.manager = null;
|
||||||
|
|
||||||
|
TexCoordsManager.destroy();
|
||||||
|
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
version(WebAssembly)emscripten_cancel_main_loop();
|
version(WebAssembly)emscripten_cancel_main_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1060,10 +1067,11 @@ int app_main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImFontConfig* config = ImFontConfig_ImFontConfig();
|
//ImFontConfig* config = ImFontConfig_ImFontConfig();
|
||||||
ImGuiIO* io = igGetIO();
|
ImGuiIO* io = igGetIO();
|
||||||
const ushort* font_ranges = ImFontAtlas_GetGlyphRangesDefault(io.Fonts);
|
const ushort* font_ranges = ImFontAtlas_GetGlyphRangesDefault(io.Fonts);
|
||||||
ImFontAtlas_AddFontFromFileTTF(io.Fonts,"assets/fonts/Ruda-Bold.ttf", 15.0f, config, font_ranges);
|
ImFontAtlas_AddFontFromFileTTF(io.Fonts,"assets/fonts/Ruda-Bold.ttf", 15.0f, null, font_ranges);
|
||||||
|
//ImFontConfig_destroy(config);
|
||||||
|
|
||||||
setStyle(3);
|
setStyle(3);
|
||||||
|
|
||||||
|
|
@ -1139,9 +1147,6 @@ int app_main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TexCoordsManager.destroy();
|
|
||||||
EntityManager.destroy();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,15 @@ struct CBall
|
||||||
ubyte radius;
|
ubyte radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CHitPoints
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
|
||||||
|
alias value this;
|
||||||
|
|
||||||
|
short value;
|
||||||
|
}
|
||||||
|
|
||||||
// struct CVelocityFactor
|
// struct CVelocityFactor
|
||||||
// {
|
// {
|
||||||
// mixin ECS.Component;
|
// mixin ECS.Component;
|
||||||
|
|
@ -72,6 +81,13 @@ struct CBall
|
||||||
// vec2 value = vec2(0);
|
// vec2 value = vec2(0);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
struct EDamage
|
||||||
|
{
|
||||||
|
mixin ECS.Event;
|
||||||
|
|
||||||
|
ubyte damage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*#######################################################################################################################
|
/*#######################################################################################################################
|
||||||
------------------------------------------------ Systems ------------------------------------------------------------------
|
------------------------------------------------ Systems ------------------------------------------------------------------
|
||||||
#######################################################################################################################*/
|
#######################################################################################################################*/
|
||||||
|
|
@ -152,7 +168,7 @@ struct BallCollisionSystem
|
||||||
{
|
{
|
||||||
mixin ECS.System!64;
|
mixin ECS.System!64;
|
||||||
|
|
||||||
mixin ECS.ReadOnlyDependencies!(ShootGridDependency);
|
mixin ECS.ReadOnlyDependencies!(ShootGridDependency, BVHDependency);
|
||||||
|
|
||||||
struct EntitiesData
|
struct EntitiesData
|
||||||
{
|
{
|
||||||
|
|
@ -165,23 +181,9 @@ struct BallCollisionSystem
|
||||||
@readonly CBall[] ball_flag;
|
@readonly CBall[] ball_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShootGrid* grid;
|
struct State
|
||||||
|
|
||||||
bool onBegin()
|
|
||||||
{
|
{
|
||||||
grid = launcher.manager.getSystem!ShootGridManager().grid;
|
bool test(EntityID id)
|
||||||
if(grid is null)return false;
|
|
||||||
else return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onUpdate(EntitiesData data)
|
|
||||||
{
|
|
||||||
EntityID id;
|
|
||||||
foreach(i; 0..data.length)
|
|
||||||
{
|
|
||||||
float radius = data.scale[i].x;
|
|
||||||
//if(grid.test(id, data.location[i], ubyte.max))
|
|
||||||
if(grid.test(id, data.location[i] - radius, data.location[i] + radius, ubyte.max))
|
|
||||||
{
|
{
|
||||||
Entity* entity = launcher.manager.getEntity(id);
|
Entity* entity = launcher.manager.getEntity(id);
|
||||||
if(entity)
|
if(entity)
|
||||||
|
|
@ -190,6 +192,7 @@ struct BallCollisionSystem
|
||||||
CScale* scale = entity.getComponent!CScale;
|
CScale* scale = entity.getComponent!CScale;
|
||||||
if(location && scale)
|
if(location && scale)
|
||||||
{
|
{
|
||||||
|
float radius = data.scale[i].x;
|
||||||
vec2 rel_pos = *location - data.location[i];
|
vec2 rel_pos = *location - data.location[i];
|
||||||
vec2 abs_rel_pos = rel_pos;
|
vec2 abs_rel_pos = rel_pos;
|
||||||
if(abs_rel_pos.x < 0)abs_rel_pos.x = -abs_rel_pos.x;
|
if(abs_rel_pos.x < 0)abs_rel_pos.x = -abs_rel_pos.x;
|
||||||
|
|
@ -202,11 +205,21 @@ struct BallCollisionSystem
|
||||||
{
|
{
|
||||||
if(abs_rel_pos.x < half_scale.x)
|
if(abs_rel_pos.x < half_scale.x)
|
||||||
{
|
{
|
||||||
if(rel_pos.y * data.velocity[i].y > 0)data.velocity[i].y = -data.velocity[i].y;
|
if(rel_pos.y * data.velocity[i].y > 0)
|
||||||
|
{
|
||||||
|
data.velocity[i].y = -data.velocity[i].y;
|
||||||
|
launcher.manager.sendEvent(id,EDamage(1));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(abs_rel_pos.y < half_scale.y)
|
else if(abs_rel_pos.y < half_scale.y)
|
||||||
{
|
{
|
||||||
if(rel_pos.x * data.velocity[i].x > 0)data.velocity[i].x = -data.velocity[i].x;
|
if(rel_pos.x * data.velocity[i].x > 0)
|
||||||
|
{
|
||||||
|
data.velocity[i].x = -data.velocity[i].x;
|
||||||
|
launcher.manager.sendEvent(id,EDamage(1));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -219,16 +232,83 @@ struct BallCollisionSystem
|
||||||
{
|
{
|
||||||
vector = vector / sqrtf(pow_dist);
|
vector = vector / sqrtf(pow_dist);
|
||||||
data.velocity[i] = data.velocity[i] - vector * (2 * dot(vector, data.velocity[i]));
|
data.velocity[i] = data.velocity[i] - vector * (2 * dot(vector, data.velocity[i]));
|
||||||
|
launcher.manager.sendEvent(id,EDamage(1));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//launcher.manager.sendEvent(id, EBulletHit(data.entity[i].id,data.bullet[i].damage));
|
return true;
|
||||||
//launcher.manager.removeEntity(data.entity[i].id);
|
}
|
||||||
|
|
||||||
|
EntitiesData data;
|
||||||
|
uint i;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShootGrid* grid;
|
||||||
|
BVHTree* tree;
|
||||||
|
BVHTree* static_tree;
|
||||||
|
|
||||||
|
bool onBegin()
|
||||||
|
{
|
||||||
|
//grid = launcher.manager.getSystem!ShootGridManager().grid;
|
||||||
|
tree = launcher.manager.getSystem!BVHBuilder().tree;
|
||||||
|
static_tree = launcher.manager.getSystem!StaticBVHBuilder().tree;
|
||||||
|
//if(grid is null)return false;
|
||||||
|
if(tree is null || static_tree is null)return false;
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUpdate(EntitiesData data)
|
||||||
|
{
|
||||||
|
// State state;
|
||||||
|
// state.data = data;
|
||||||
|
// EntityID id;
|
||||||
|
// foreach(i; 0..data.length)
|
||||||
|
// {
|
||||||
|
// state.i = i;
|
||||||
|
// float radius = data.scale[i].x;
|
||||||
|
// if(grid.test(id, data.location[i] - radius, data.location[i] + radius, ubyte.max))
|
||||||
|
// {
|
||||||
|
// state.test(id);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
State state;
|
||||||
|
state.data = data;
|
||||||
|
foreach(i; 0..data.length)
|
||||||
|
{
|
||||||
|
state.i = i;
|
||||||
|
//float radius = data.scale[i].x;
|
||||||
|
AABB bounding = AABB(data.location[i]-data.scale[i], data.location[i]+data.scale[i]);
|
||||||
|
tree.test(bounding, cast(bool delegate(EntityID id))&state.test);
|
||||||
|
static_tree.test(bounding, cast(bool delegate(EntityID id))&state.test);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DamageSystem
|
||||||
|
{
|
||||||
|
mixin ECS.System!64;
|
||||||
|
|
||||||
|
mixin ECS.ReadOnlyDependencies!(ShootGridDependency);
|
||||||
|
|
||||||
|
struct EntitiesData
|
||||||
|
{
|
||||||
|
///variable named "length" contain entites count
|
||||||
|
uint length;
|
||||||
|
const (Entity)[] entity;
|
||||||
|
CHitPoints[] hit_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleEvent(Entity* entity, EDamage event)
|
||||||
|
{
|
||||||
|
EntityMeta meta = entity.getMeta();
|
||||||
|
CHitPoints* hp = meta.getComponent!CHitPoints;
|
||||||
|
hp.value -= event.damage;
|
||||||
|
if(hp.value < 0)launcher.manager.removeEntity(entity.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*#######################################################################################################################
|
/*#######################################################################################################################
|
||||||
|
|
@ -239,7 +319,7 @@ struct BrickBreakerDemo
|
||||||
{
|
{
|
||||||
__gshared const (char)* tips = "Brick breaker demo. It's a game about destroying evil bricks.";
|
__gshared const (char)* tips = "Brick breaker demo. It's a game about destroying evil bricks.";
|
||||||
|
|
||||||
EntityTemplate* tmpl;
|
//EntityTemplate* tmpl;
|
||||||
Texture texture;
|
Texture texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,12 +348,16 @@ void brickBreakerRegister()
|
||||||
launcher.manager.registerComponent!CDamping;
|
launcher.manager.registerComponent!CDamping;
|
||||||
launcher.manager.registerComponent!CVelocityFactor;
|
launcher.manager.registerComponent!CVelocityFactor;
|
||||||
launcher.manager.registerComponent!CBall;
|
launcher.manager.registerComponent!CBall;
|
||||||
|
launcher.manager.registerComponent!CHitPoints;
|
||||||
|
|
||||||
|
launcher.manager.registerEvent!EDamage;
|
||||||
|
|
||||||
launcher.manager.registerSystem!MoveSystem(-100);
|
launcher.manager.registerSystem!MoveSystem(-100);
|
||||||
launcher.manager.registerSystem!EdgeCollisionSystem(-99);
|
launcher.manager.registerSystem!EdgeCollisionSystem(-99);
|
||||||
launcher.manager.registerSystem!BallCollisionSystem(-79);
|
launcher.manager.registerSystem!BallCollisionSystem(-79);
|
||||||
launcher.manager.registerSystem!InputMovementSystem(-120);
|
launcher.manager.registerSystem!InputMovementSystem(-120);
|
||||||
launcher.manager.registerSystem!DampingSystem(-120);
|
launcher.manager.registerSystem!DampingSystem(-120);
|
||||||
|
launcher.manager.registerSystem!DamageSystem(-120);
|
||||||
|
|
||||||
launcher.manager.endRegister();
|
launcher.manager.endRegister();
|
||||||
}
|
}
|
||||||
|
|
@ -289,11 +373,14 @@ void brickBreakerStart()
|
||||||
|
|
||||||
EntityTemplate* brick_tmpl = launcher.manager.allocateTemplate(
|
EntityTemplate* brick_tmpl = launcher.manager.allocateTemplate(
|
||||||
[CLocation.component_id, CScale.component_id, CColor.component_id,
|
[CLocation.component_id, CScale.component_id, CColor.component_id,
|
||||||
CTexCoordsIndex.component_id, CShootGrid.component_id].staticArray
|
CTexCoordsIndex.component_id, CBVH.component_id, CHitPoints.component_id,
|
||||||
|
CAABB.component_id, CStatic.component_id].staticArray
|
||||||
);
|
);
|
||||||
brick_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(304,40,16,8)*px);
|
brick_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(304,40,16,8)*px);
|
||||||
brick_tmpl.getComponent!CColor().value = 0x80206020;
|
brick_tmpl.getComponent!CColor().value = 0x80206020;
|
||||||
brick_tmpl.getComponent!CScale().value = vec2(16,8);
|
brick_tmpl.getComponent!CScale().value = vec2(16,8);
|
||||||
|
brick_tmpl.getComponent!CHitPoints().value = 2;
|
||||||
|
//brick_tmpl.getComponent!CAABB().bounding = AABB(vec2(),vec2());
|
||||||
|
|
||||||
EntityTemplate* big_brick_tmpl = launcher.manager.allocateTemplate(brick_tmpl);
|
EntityTemplate* big_brick_tmpl = launcher.manager.allocateTemplate(brick_tmpl);
|
||||||
big_brick_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(320,32,16,16)*px);
|
big_brick_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(320,32,16,16)*px);
|
||||||
|
|
@ -302,7 +389,8 @@ void brickBreakerStart()
|
||||||
EntityTemplate* paddle_tmpl = launcher.manager.allocateTemplate(
|
EntityTemplate* paddle_tmpl = launcher.manager.allocateTemplate(
|
||||||
[CLocation.component_id, CScale.component_id, CInput.component_id,
|
[CLocation.component_id, CScale.component_id, CInput.component_id,
|
||||||
CTexCoordsIndex.component_id, CPaddle.component_id, CVelocity.component_id,
|
CTexCoordsIndex.component_id, CPaddle.component_id, CVelocity.component_id,
|
||||||
CDamping.component_id, CVelocityFactor.component_id, CShootGrid.component_id].staticArray
|
CDamping.component_id, CVelocityFactor.component_id, CBVH.component_id,
|
||||||
|
CAABB.component_id].staticArray
|
||||||
);
|
);
|
||||||
paddle_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(272,48,64,10)*px);
|
paddle_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(272,48,64,10)*px);
|
||||||
paddle_tmpl.getComponent!CScale().value = vec2(64,10);
|
paddle_tmpl.getComponent!CScale().value = vec2(64,10);
|
||||||
|
|
@ -330,7 +418,11 @@ void brickBreakerStart()
|
||||||
launcher.gui_manager.addComponent(CBall(), "Ball");
|
launcher.gui_manager.addComponent(CBall(), "Ball");
|
||||||
|
|
||||||
launcher.gui_manager.addSystem(MoveSystem.system_id, "Move System");
|
launcher.gui_manager.addSystem(MoveSystem.system_id, "Move System");
|
||||||
|
launcher.gui_manager.addSystem(EdgeCollisionSystem.system_id, "Edge Collision System");
|
||||||
launcher.gui_manager.addSystem(BallCollisionSystem.system_id, "Ball Collision System");
|
launcher.gui_manager.addSystem(BallCollisionSystem.system_id, "Ball Collision System");
|
||||||
|
launcher.gui_manager.addSystem(InputMovementSystem.system_id, "Input Movement System");
|
||||||
|
launcher.gui_manager.addSystem(DampingSystem.system_id, "Damping System");
|
||||||
|
launcher.gui_manager.addSystem(DamageSystem.system_id, "Damage System");
|
||||||
|
|
||||||
launcher.gui_manager.addTemplate(brick_tmpl, "Brick");
|
launcher.gui_manager.addTemplate(brick_tmpl, "Brick");
|
||||||
launcher.gui_manager.addTemplate(big_brick_tmpl, "Big Brick");
|
launcher.gui_manager.addTemplate(big_brick_tmpl, "Big Brick");
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ struct Snake
|
||||||
bool move_system = true;
|
bool move_system = true;
|
||||||
bool draw_system = true;
|
bool draw_system = true;
|
||||||
|
|
||||||
const int map_size = 18;
|
enum int map_size = 18;
|
||||||
|
|
||||||
MapElement[map_size * map_size] map;
|
MapElement[map_size * map_size] map;
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ struct Snake
|
||||||
if(apple_tmpl)launcher.manager.freeTemplate(apple_tmpl);
|
if(apple_tmpl)launcher.manager.freeTemplate(apple_tmpl);
|
||||||
if(snake_tmpl)launcher.manager.freeTemplate(snake_tmpl);
|
if(snake_tmpl)launcher.manager.freeTemplate(snake_tmpl);
|
||||||
if(snake_destroy_particle)launcher.manager.freeTemplate(snake_destroy_particle);
|
if(snake_destroy_particle)launcher.manager.freeTemplate(snake_destroy_particle);
|
||||||
texture.destory();
|
texture.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapElement element(ivec2 pos)
|
MapElement element(ivec2 pos)
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ struct SpaceInvaders
|
||||||
{
|
{
|
||||||
if(tmpl)launcher.manager.freeTemplate(tmpl);
|
if(tmpl)launcher.manager.freeTemplate(tmpl);
|
||||||
}
|
}
|
||||||
texture.destory();
|
texture.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ struct SceneGrid
|
||||||
cells = Mallocator.makeArray!Cell(cells_count.x * cells_count.y);
|
cells = Mallocator.makeArray!Cell(cells_count.x * cells_count.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destory()
|
void destroy()
|
||||||
{
|
{
|
||||||
if(cells)
|
if(cells)
|
||||||
{
|
{
|
||||||
|
|
@ -707,6 +707,7 @@ struct ShipWeaponSystem
|
||||||
|
|
||||||
void onDestroy()
|
void onDestroy()
|
||||||
{
|
{
|
||||||
|
__xdtor();
|
||||||
/*launcher.manager.freeTemplate(laser1_tmpl);
|
/*launcher.manager.freeTemplate(laser1_tmpl);
|
||||||
launcher.manager.freeTemplate(laser2_tmpl);
|
launcher.manager.freeTemplate(laser2_tmpl);
|
||||||
launcher.manager.freeTemplate(main_weapon_tmpl);*/
|
launcher.manager.freeTemplate(main_weapon_tmpl);*/
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
module game_core.collision;
|
module game_core.collision;
|
||||||
|
|
||||||
import bubel.ecs.attributes;
|
import bubel.ecs.attributes;
|
||||||
|
import bubel.ecs.block_allocator;
|
||||||
import bubel.ecs.core;
|
import bubel.ecs.core;
|
||||||
import bubel.ecs.std;
|
import bubel.ecs.std;
|
||||||
|
import bubel.ecs.vector;
|
||||||
|
|
||||||
import ecs_utils.math.vector;
|
import ecs_utils.math.vector;
|
||||||
|
import ecs_utils.utils;
|
||||||
|
|
||||||
import game_core.basic;
|
import game_core.basic;
|
||||||
|
|
||||||
|
|
@ -12,22 +15,54 @@ import game_core.basic;
|
||||||
void registerCollisionModule(EntityManager* manager)
|
void registerCollisionModule(EntityManager* manager)
|
||||||
{
|
{
|
||||||
manager.registerDependency(ShootGridDependency);
|
manager.registerDependency(ShootGridDependency);
|
||||||
|
manager.registerDependency(BVHDependency);
|
||||||
|
manager.registerDependency(StaticBVHDependency);
|
||||||
|
|
||||||
manager.registerComponent!CShootGrid;
|
manager.registerComponent!CShootGrid;
|
||||||
manager.registerComponent!CShootGridMask;
|
manager.registerComponent!CShootGridMask;
|
||||||
manager.registerComponent!CColliderScale;
|
manager.registerComponent!CColliderScale;
|
||||||
|
manager.registerComponent!CBVH;
|
||||||
|
manager.registerComponent!CAABB;
|
||||||
|
manager.registerComponent!CStatic;
|
||||||
|
|
||||||
manager.registerSystem!ShootGridManager(-80);
|
manager.registerSystem!ShootGridManager(-80);
|
||||||
manager.registerSystem!ShootGridCleaner(-101);
|
manager.registerSystem!ShootGridCleaner(-101);
|
||||||
|
manager.registerSystem!BVHBuilder(-80);
|
||||||
|
manager.registerSystem!StaticBVHBuilder(-80);
|
||||||
|
//manager.registerSystem!BVHBuilder2(-79);
|
||||||
|
manager.registerSystem!AABBUpdater(-81);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ShootGridDependency = "ShootGridDependency";
|
enum ShootGridDependency = "ShootGridDependency";
|
||||||
|
enum BVHDependency = "BVHDependency";
|
||||||
|
enum StaticBVHDependency = "StaticBVHDependency";
|
||||||
|
|
||||||
struct CShootGrid
|
struct CShootGrid
|
||||||
{
|
{
|
||||||
mixin ECS.Component;
|
mixin ECS.Component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CBVH
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
|
||||||
|
uint index;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CStatic
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CAABB
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
|
||||||
|
alias bounding this;
|
||||||
|
|
||||||
|
AABB bounding;
|
||||||
|
}
|
||||||
|
|
||||||
struct CShootGridMask
|
struct CShootGridMask
|
||||||
{
|
{
|
||||||
mixin ECS.Component;
|
mixin ECS.Component;
|
||||||
|
|
@ -46,6 +81,7 @@ struct CColliderScale
|
||||||
vec2 value = vec2(16,16);
|
vec2 value = vec2(16,16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct ShootGrid
|
struct ShootGrid
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -230,3 +266,758 @@ struct ShootGridManager
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AABB
|
||||||
|
{
|
||||||
|
vec2 size()
|
||||||
|
{
|
||||||
|
return max-min;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 center()
|
||||||
|
{
|
||||||
|
return (max+min) * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
float area()
|
||||||
|
{
|
||||||
|
return size.x * size.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(ref AABB base, vec2 position, float angle, vec2 scale)
|
||||||
|
{
|
||||||
|
import std.algorithm.comparison : max;
|
||||||
|
|
||||||
|
float sr = sinf(angle);
|
||||||
|
float cr = cosf(angle);
|
||||||
|
/*mat2 m = mat2(cr,-sr,
|
||||||
|
sr,cr);*/
|
||||||
|
|
||||||
|
|
||||||
|
//vec2 pos = ;//m * ((base.max + base.min)*0.5*scale);
|
||||||
|
vec2 size = (base.max - base.min)*scale;
|
||||||
|
vec2[2] axis = [vec2(cr*size.x,sr*size.y),vec2(-sr*size.x,cr*size.y)];
|
||||||
|
|
||||||
|
this.max.x = max(fabs(axis[0].x),fabs(axis[1].x));
|
||||||
|
this.max.y = max(fabs(axis[0].y),fabs(axis[1].y));
|
||||||
|
|
||||||
|
this.min = -this.max;
|
||||||
|
|
||||||
|
this.min += center + position;
|
||||||
|
this.max += center + position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(ref AABB base, vec2 position, vec2 scale)
|
||||||
|
{
|
||||||
|
vec2 size = (base.max - base.min)*scale;
|
||||||
|
|
||||||
|
this.min = -size;
|
||||||
|
this.max = size;
|
||||||
|
|
||||||
|
this.min += center + position;
|
||||||
|
this.max += center + position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(ref AABB base, vec2 position, float angle)
|
||||||
|
{
|
||||||
|
import std.algorithm.comparison : max;
|
||||||
|
|
||||||
|
float sr = sinf(angle);
|
||||||
|
float cr = cosf(angle);
|
||||||
|
/*mat2 m = mat2(cr,-sr,
|
||||||
|
sr,cr);*/
|
||||||
|
|
||||||
|
|
||||||
|
//vec2 pos = ;//m * ((base.max + base.min)*0.5*scale);
|
||||||
|
vec2 size = (base.max - base.min);//*scale;
|
||||||
|
vec2[2] axis = [vec2(cr*size.x,sr*size.y),vec2(-sr*size.x,cr*size.y)];
|
||||||
|
|
||||||
|
this.max.x = max(fabs(axis[0].x),fabs(axis[1].x));
|
||||||
|
this.max.y = max(fabs(axis[0].y),fabs(axis[1].y));
|
||||||
|
|
||||||
|
this.min = -this.max;
|
||||||
|
|
||||||
|
this.min += center + position;
|
||||||
|
this.max += center + position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(ref AABB base, vec2 position)
|
||||||
|
{
|
||||||
|
min = base.min + position;
|
||||||
|
max = base.max + position;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 min;
|
||||||
|
vec2 max;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test(AABB a, AABB b)
|
||||||
|
{
|
||||||
|
if((a.max.x>b.min.x && a.max.y>b.min.y) &&
|
||||||
|
(a.min.x<b.max.x && a.min.y<b.max.y))return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte intersectTest(AABB a, AABB b)
|
||||||
|
{
|
||||||
|
if(a.min.x < b.min.x && a.min.y < b.min.y &&
|
||||||
|
a.max.x > b.max.x && a.max.y > b.max.y)return 2;
|
||||||
|
else if((a.max.x>b.min.x && a.max.y>b.min.y) &&
|
||||||
|
(a.min.x<b.max.x && a.min.y<b.max.y))return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test(vec2 point, AABB b)
|
||||||
|
{
|
||||||
|
if((point.x>b.min.x && point.y>b.min.y) &&
|
||||||
|
(point.x<b.max.x && point.y<b.max.y))return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB merge(AABB a, AABB b)
|
||||||
|
{
|
||||||
|
import std.algorithm.comparison: min, max;
|
||||||
|
return AABB(vec2(min(a.min.x,b.min.x),min(a.min.y,b.min.y)),vec2(max(a.max.x,b.max.x),max(a.max.y,b.max.y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Quadtree
|
||||||
|
{
|
||||||
|
|
||||||
|
Node* add(EntityID id, AABB aabb)
|
||||||
|
{
|
||||||
|
ubyte depth = void;
|
||||||
|
vec2 ratio = aabb.size / this.aabb.size;
|
||||||
|
//if(ratio.x < ratio.y)depth = log2f();
|
||||||
|
//else depth = 0;
|
||||||
|
return null;
|
||||||
|
//2^x = size2/size;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
|
||||||
|
AABB aabb;
|
||||||
|
Node*[4] nodes;
|
||||||
|
MemoryBlock* block;
|
||||||
|
MemoryBlock* last_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MemoryBlock
|
||||||
|
{
|
||||||
|
EntityID[10] entities;
|
||||||
|
MemoryBlock* next_block;
|
||||||
|
void* Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MetaBlock
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
MemoryBlock _alignment;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Quadtree* quadtree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB aabb;
|
||||||
|
|
||||||
|
Node main_node;
|
||||||
|
uint max_depth;
|
||||||
|
|
||||||
|
BlockAllocator allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BVHTree
|
||||||
|
{
|
||||||
|
|
||||||
|
void generateTopDown()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateBottomUp()
|
||||||
|
{
|
||||||
|
clearNodes();
|
||||||
|
uint index = 0;
|
||||||
|
while(index < nodes.length - 1)
|
||||||
|
{
|
||||||
|
Node* node = &nodes[index];
|
||||||
|
if(node.parent != uint.max)
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint best_index = 0;
|
||||||
|
float best_cost = float.max;
|
||||||
|
foreach(i;index+1 .. nodes.length)
|
||||||
|
{
|
||||||
|
Node* test_node = &nodes[i];
|
||||||
|
if(test_node.parent != uint.max)continue;
|
||||||
|
// vec2 rel_pos = node.bounding.center - test_node.bounding.center;
|
||||||
|
// float cost = fabs(rel_pos.x) + fabs(rel_pos.y);
|
||||||
|
// float cost = rel_pos.length;
|
||||||
|
// float cost = rel_pos.length2;
|
||||||
|
float cost = merge(node.bounding, test_node.bounding).area();
|
||||||
|
if(cost < best_cost)
|
||||||
|
{
|
||||||
|
best_cost = cost;
|
||||||
|
best_index = cast(uint)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint new_index = getNode();
|
||||||
|
Node* new_node = &nodes[new_index];
|
||||||
|
Node* best_node = &nodes[best_index];
|
||||||
|
|
||||||
|
new_node.childs[0] = index;
|
||||||
|
new_node.childs[1] = best_index;
|
||||||
|
new_node.bounding = merge(best_node.bounding, node.bounding);
|
||||||
|
|
||||||
|
best_node.parent = new_index;
|
||||||
|
node.parent = new_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
root = cast(uint)nodes.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint addIncrementally(AABB bounding, EntityID id)
|
||||||
|
{
|
||||||
|
if(root == uint.max)
|
||||||
|
{
|
||||||
|
root = getNode();
|
||||||
|
Node* new_node = &nodes[root];
|
||||||
|
new_node.parent = uint.max;
|
||||||
|
new_node.entity = id;
|
||||||
|
new_node.bounding = bounding;
|
||||||
|
//new_node.childs = [uint.max, uint.max].staticArray;
|
||||||
|
new_node.childs[0] = uint.max;
|
||||||
|
new_node.childs[1] = uint.max;
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
float cost = float.max;
|
||||||
|
uint best_index = 0;
|
||||||
|
findBest(bounding, root, best_index, cost, 0);
|
||||||
|
|
||||||
|
uint new_index = getNode();
|
||||||
|
uint leaf_index = getNode();
|
||||||
|
|
||||||
|
Node* new_node = &nodes[new_index];
|
||||||
|
Node* node = &nodes[best_index];
|
||||||
|
Node* parent = &nodes[node.parent];
|
||||||
|
Node* leaf_node = &nodes[leaf_index];
|
||||||
|
|
||||||
|
leaf_node.entity = id;
|
||||||
|
leaf_node.bounding = bounding;
|
||||||
|
leaf_node.parent = new_index;
|
||||||
|
|
||||||
|
new_node.parent = node.parent;
|
||||||
|
new_node.childs[0] = best_index;
|
||||||
|
new_node.childs[1] = leaf_index;
|
||||||
|
new_node.bounding = merge(bounding, node.bounding);
|
||||||
|
|
||||||
|
if(node.parent != uint.max)
|
||||||
|
{
|
||||||
|
if(parent.childs[0] == best_index)
|
||||||
|
{
|
||||||
|
parent.childs[0] = new_index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent.childs[1] = new_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root = new_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.parent = new_index;
|
||||||
|
|
||||||
|
uint index = new_node.parent;
|
||||||
|
|
||||||
|
while(index != uint.max)
|
||||||
|
{
|
||||||
|
Node* lnode = &nodes[index];
|
||||||
|
|
||||||
|
recalculate(lnode);
|
||||||
|
|
||||||
|
rotate(lnode);
|
||||||
|
|
||||||
|
index = lnode.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return leaf_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearNodes()
|
||||||
|
{
|
||||||
|
root = uint.max;
|
||||||
|
uint i = 0;
|
||||||
|
while(i < nodes.length)
|
||||||
|
{
|
||||||
|
Node* node = &nodes[i];
|
||||||
|
if(node.childs[0] == uint.max)
|
||||||
|
{
|
||||||
|
node.parent = uint.max;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removeNode(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void findBest(AABB bounding, uint node_index, ref uint best_index, ref float best_cost, float cost)
|
||||||
|
{
|
||||||
|
Node* node = &nodes[node_index];
|
||||||
|
//float area = nodes.bounding.area;
|
||||||
|
AABB new_bounding = merge(node.bounding, bounding);
|
||||||
|
float new_area = new_bounding.area;
|
||||||
|
if(new_area + cost < best_cost)
|
||||||
|
{
|
||||||
|
best_index = node_index;
|
||||||
|
best_cost = cost + new_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node.childs[0] == uint.max)return;
|
||||||
|
float area_delta = new_area - node.bounding.area;
|
||||||
|
|
||||||
|
if(bounding.area + area_delta + cost < best_cost)
|
||||||
|
{
|
||||||
|
findBest(bounding, node.childs[0], best_index, best_cost, cost + area_delta);
|
||||||
|
findBest(bounding, node.childs[1], best_index, best_cost, cost + area_delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(AABB bounding, EntityID id)
|
||||||
|
{
|
||||||
|
Node* node = &nodes[getNode()];
|
||||||
|
node.entity = id;
|
||||||
|
node.bounding = bounding;
|
||||||
|
// node.childs = [uint.max,uint.max];
|
||||||
|
node.childs[0] = uint.max;
|
||||||
|
node.childs[1] = uint.max;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test(AABB bounding, bool delegate(EntityID id) callback)
|
||||||
|
{
|
||||||
|
bool traverse(Node* node)
|
||||||
|
{
|
||||||
|
if(.test(bounding, node.bounding))
|
||||||
|
{
|
||||||
|
if(node.childs[0] == uint.max)
|
||||||
|
{
|
||||||
|
return callback(node.entity);
|
||||||
|
}
|
||||||
|
if(!traverse(&nodes[node.childs[0]]))return false;
|
||||||
|
if(!traverse(&nodes[node.childs[1]]))return false;
|
||||||
|
}
|
||||||
|
/*node.bounding.max.x = max(nodes[node.childs[0]].bounding.max.x,nodes[node.childs[1]].bounding.max.x);
|
||||||
|
node.bounding.max.y = max(nodes[node.childs[0]].bounding.max.y,nodes[node.childs[1]].bounding.max.y);
|
||||||
|
node.bounding.min.x = min(nodes[node.childs[0]].bounding.min.x,nodes[node.childs[1]].bounding.min.x);
|
||||||
|
node.bounding.min.y = min(nodes[node.childs[0]].bounding.min.y,nodes[node.childs[1]].bounding.min.y);*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(root < nodes.length)traverse(&nodes[root]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float computeCost()
|
||||||
|
{
|
||||||
|
float cost = 0;
|
||||||
|
foreach(ref Node node;nodes)
|
||||||
|
{
|
||||||
|
if(node.childs[0] != uint.max)
|
||||||
|
{
|
||||||
|
cost += node.bounding.area();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recalculate(Node* node)
|
||||||
|
{
|
||||||
|
import std.algorithm.comparison: min, max;
|
||||||
|
node.bounding = merge(nodes[node.childs[0]].bounding, nodes[node.childs[1]].bounding);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rotate(Node* node)
|
||||||
|
{
|
||||||
|
import std.algorithm.comparison: min, max;
|
||||||
|
if(node.parent == uint.max)return;
|
||||||
|
Node* parent = &nodes[node.parent];
|
||||||
|
Node* child1 = &nodes[node.childs[0]];
|
||||||
|
Node* child2 = &nodes[node.childs[1]];
|
||||||
|
|
||||||
|
uint child_index = void;
|
||||||
|
if(parent.childs[0] == child1.parent)
|
||||||
|
{
|
||||||
|
child_index = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
child_index = 0;
|
||||||
|
}
|
||||||
|
Node* to_rotate = &nodes[parent.childs[child_index]];
|
||||||
|
|
||||||
|
float cost = node.bounding.area();
|
||||||
|
AABB bounding1 = merge(child1.bounding, to_rotate.bounding);
|
||||||
|
AABB bounding2 = merge(child2.bounding, to_rotate.bounding);
|
||||||
|
float area1 = bounding1.area;
|
||||||
|
float area2 = bounding2.area;
|
||||||
|
if(area1 < area2)
|
||||||
|
{
|
||||||
|
if(area1 < cost)
|
||||||
|
{
|
||||||
|
to_rotate.parent = child1.parent;
|
||||||
|
child2.parent = node.parent;
|
||||||
|
uint swap_index = node.childs[1];
|
||||||
|
node.childs[1] = parent.childs[child_index];
|
||||||
|
parent.childs[child_index] = swap_index;
|
||||||
|
node.bounding = bounding1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(area2 < cost)
|
||||||
|
{
|
||||||
|
to_rotate.parent = child1.parent;
|
||||||
|
child1.parent = node.parent;
|
||||||
|
uint swap_index = node.childs[0];
|
||||||
|
node.childs[0] = parent.childs[child_index];
|
||||||
|
parent.childs[child_index] = swap_index;
|
||||||
|
node.bounding = bounding2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(uint i)
|
||||||
|
{
|
||||||
|
//foreach(i, ref Node node; nodes)
|
||||||
|
//{
|
||||||
|
// if(node.entity == id)
|
||||||
|
// {
|
||||||
|
Node* node = &nodes[i];
|
||||||
|
if(node.parent != uint.max)
|
||||||
|
{
|
||||||
|
///parent isn't root, most common beaviour
|
||||||
|
Node* parent = &nodes[node.parent];
|
||||||
|
if(parent.parent == uint.max)
|
||||||
|
{
|
||||||
|
//delete leaf attached to root
|
||||||
|
if(parent.childs[0] == i)
|
||||||
|
{
|
||||||
|
root = parent.childs[1];
|
||||||
|
nodes[parent.childs[1]].parent = uint.max;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root = parent.childs[0];
|
||||||
|
nodes[parent.childs[0]].parent = uint.max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
///remove node from inside of tree
|
||||||
|
Node* grand_parent = &nodes[parent.parent];
|
||||||
|
uint remain_index = void;
|
||||||
|
if(parent.childs[0] == i)remain_index = parent.childs[1];
|
||||||
|
else remain_index = parent.childs[0];
|
||||||
|
if(grand_parent.childs[0] == node.parent)
|
||||||
|
{
|
||||||
|
grand_parent.childs[0] = remain_index;
|
||||||
|
nodes[remain_index].parent = parent.parent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grand_parent.childs[1] = remain_index;
|
||||||
|
nodes[remain_index].parent = parent.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint index = parent.parent;
|
||||||
|
|
||||||
|
while(index != uint.max)
|
||||||
|
{
|
||||||
|
Node* lnode = &nodes[index];
|
||||||
|
|
||||||
|
recalculate(lnode);
|
||||||
|
|
||||||
|
rotate(lnode);
|
||||||
|
|
||||||
|
index = lnode.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeNode(node.parent);
|
||||||
|
}
|
||||||
|
else root = uint.max;
|
||||||
|
removeNode(cast(uint)i);
|
||||||
|
//return;
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
last_node = uint.max;
|
||||||
|
nodes.clear();
|
||||||
|
root = uint.max;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint getNode()
|
||||||
|
{
|
||||||
|
if(last_node == uint.max)
|
||||||
|
{
|
||||||
|
//nodes.length = nodes.length + 1;
|
||||||
|
nodes.add(Node());
|
||||||
|
return cast(uint)nodes.length - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint ret = last_node;
|
||||||
|
last_node = nodes[last_node].parent;
|
||||||
|
nodes[ret] = Node();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeNode(uint index)
|
||||||
|
{
|
||||||
|
Node* node = &nodes[index];
|
||||||
|
node.parent = last_node;
|
||||||
|
node.ptr = null;
|
||||||
|
last_node = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void create()
|
||||||
|
{
|
||||||
|
root = getNode();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
EntityID entity;
|
||||||
|
void* ptr;
|
||||||
|
}
|
||||||
|
AABB bounding;
|
||||||
|
uint parent = uint.max;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct //workaround betterC compilation issue with _memset
|
||||||
|
{
|
||||||
|
uint _c1 = uint.max;
|
||||||
|
uint _c2 = uint.max;
|
||||||
|
}
|
||||||
|
uint[2] childs;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector!Node nodes;
|
||||||
|
//uint nodes_count;
|
||||||
|
uint last_node = uint.max;
|
||||||
|
uint root = uint.max;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StaticBVHBuilder
|
||||||
|
{
|
||||||
|
mixin ECS.System!1;
|
||||||
|
|
||||||
|
mixin ECS.WritableDependencies!(StaticBVHDependency);
|
||||||
|
|
||||||
|
struct EntitiesData
|
||||||
|
{
|
||||||
|
uint length;
|
||||||
|
//uint thread_id;
|
||||||
|
const (Entity)[] entity;
|
||||||
|
CBVH[] bvh;
|
||||||
|
@readonly CStatic[] static_flag;
|
||||||
|
@readonly CLocation[] locations;
|
||||||
|
@readonly CAABB[] bounding;
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHTree* tree;
|
||||||
|
|
||||||
|
void onCreate()
|
||||||
|
{
|
||||||
|
tree = Mallocator.make!BVHTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDestroy()
|
||||||
|
{
|
||||||
|
Mallocator.dispose(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool onBegin()
|
||||||
|
// {
|
||||||
|
// tree.clear();
|
||||||
|
// return true;
|
||||||
|
// // return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void onAddEntity(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i;0..data.length)
|
||||||
|
{
|
||||||
|
data.bvh[i].index = tree.addIncrementally(data.bounding[i], data.entity[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onRemoveEntity(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i;0..data.length)
|
||||||
|
{
|
||||||
|
tree.remove(data.bvh[i].index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// void onUpdate(EntitiesData data)
|
||||||
|
// {
|
||||||
|
// foreach(i; 0..data.length)
|
||||||
|
// {
|
||||||
|
// // tree.add(data.bounding[i], data.entity[i].id);
|
||||||
|
// tree.addIncrementally(data.bounding[i], data.entity[i].id);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// import std.stdio;
|
||||||
|
// writeln("Cost: ",tree.computeCost());
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BVHBuilder
|
||||||
|
{
|
||||||
|
mixin ECS.System!1;
|
||||||
|
|
||||||
|
mixin ECS.WritableDependencies!(BVHDependency);
|
||||||
|
|
||||||
|
struct EntitiesData
|
||||||
|
{
|
||||||
|
uint length;
|
||||||
|
//uint thread_id;
|
||||||
|
const (Entity)[] entity;
|
||||||
|
CBVH[] bvh;
|
||||||
|
@readonly CLocation[] locations;
|
||||||
|
@readonly CAABB[] bounding;
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin ECS.ExcludedComponents!(CStatic);
|
||||||
|
|
||||||
|
BVHTree* tree;
|
||||||
|
|
||||||
|
void onCreate()
|
||||||
|
{
|
||||||
|
tree = Mallocator.make!BVHTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDestroy()
|
||||||
|
{
|
||||||
|
Mallocator.dispose(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool onBegin()
|
||||||
|
{
|
||||||
|
tree.clear();
|
||||||
|
return true;
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void onAddEntity(EntitiesData data)
|
||||||
|
// {
|
||||||
|
// foreach(i;0..data.length)
|
||||||
|
// {
|
||||||
|
// tree.add(data.bounding[i], data.entity[i].id);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void onRemoveEntity(EntitiesData data)
|
||||||
|
// {
|
||||||
|
// foreach(i;0..data.length)
|
||||||
|
// {
|
||||||
|
// tree.remove(data.entity[i].id);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
void onUpdate(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i; 0..data.length)
|
||||||
|
{
|
||||||
|
// tree.add(data.bounding[i], data.entity[i].id);
|
||||||
|
data.bvh[i].index = tree.addIncrementally(data.bounding[i], data.entity[i].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import std.stdio;
|
||||||
|
// writeln("Cost: ",tree.computeCost());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
struct BVHBuilder2
|
||||||
|
{
|
||||||
|
mixin ECS.System!1;
|
||||||
|
|
||||||
|
mixin ECS.WritableDependencies!(BVHDependency);
|
||||||
|
|
||||||
|
struct EntitiesData
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHTree* tree;
|
||||||
|
|
||||||
|
void onCreate()
|
||||||
|
{
|
||||||
|
tree = gEM.getSystem!BVHBuilder().tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool onBegin()
|
||||||
|
{
|
||||||
|
//if(tree.nodes.length-1 != tree.root)tree.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUpdate(EntitiesData data)
|
||||||
|
{
|
||||||
|
if(tree.nodes.length-1 != tree.root)
|
||||||
|
{
|
||||||
|
tree.generateBottomUp();
|
||||||
|
import std.stdio;
|
||||||
|
writeln("Cost: ",tree.computeCost());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}//*/
|
||||||
|
|
||||||
|
struct AABBUpdater
|
||||||
|
{
|
||||||
|
mixin ECS.System!64;
|
||||||
|
|
||||||
|
struct EntitiesData
|
||||||
|
{
|
||||||
|
uint length;
|
||||||
|
//uint thread_id;
|
||||||
|
const (Entity)[] entity;
|
||||||
|
CAABB[] bounding;
|
||||||
|
|
||||||
|
@readonly CLocation[] location;
|
||||||
|
@readonly CScale[] scale;
|
||||||
|
@optional @readonly CRotation[] rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onAddEntity(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i; 0..data.length)
|
||||||
|
{
|
||||||
|
data.bounding[i] = AABB(data.location[i]-data.scale[i],data.location[i]+data.scale[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUpdate(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i; 0..data.length)
|
||||||
|
{
|
||||||
|
data.bounding[i] = AABB(data.location[i]-data.scale[i],data.location[i]+data.scale[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -33,6 +33,11 @@ struct GUIManager
|
||||||
int selected_template = 0;
|
int selected_template = 0;
|
||||||
int selected_component = 0;
|
int selected_component = 0;
|
||||||
|
|
||||||
|
~this()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
void selectTemplate(int id)
|
void selectTemplate(int id)
|
||||||
{
|
{
|
||||||
if(templates.length == 0)return;
|
if(templates.length == 0)return;
|
||||||
|
|
@ -133,6 +138,7 @@ struct GUIManager
|
||||||
edit_components.length = comp.component_id+1;//.extend(comp.component_id + 1);
|
edit_components.length = comp.component_id+1;//.extend(comp.component_id + 1);
|
||||||
}
|
}
|
||||||
//edit_components[comp.component_id] = ComponentEditGUI(name);
|
//edit_components[comp.component_id] = ComponentEditGUI(name);
|
||||||
|
if(edit_components[comp.component_id].variables)return;
|
||||||
ComponentEditGUI comp_edit;
|
ComponentEditGUI comp_edit;
|
||||||
comp_edit.name = T.stringof;
|
comp_edit.name = T.stringof;
|
||||||
//enum fields = __traits(allMembers, T);
|
//enum fields = __traits(allMembers, T);
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ struct Texture
|
||||||
data.bpp = surf.format.BytesPerPixel;
|
data.bpp = surf.format.BytesPerPixel;
|
||||||
data.data = Mallocator.makeArray!ubyte(surf.w*surf.h*surf.format.BytesPerPixel);
|
data.data = Mallocator.makeArray!ubyte(surf.w*surf.h*surf.format.BytesPerPixel);
|
||||||
data.data[0..$] = (cast(ubyte*)surf.pixels)[0..data.data.length];
|
data.data[0..$] = (cast(ubyte*)surf.pixels)[0..data.data.length];
|
||||||
|
data.size = ivec2(surf.w, surf.h);
|
||||||
|
|
||||||
SDL_FreeSurface(surf);
|
SDL_FreeSurface(surf);
|
||||||
|
|
||||||
|
|
@ -67,8 +68,8 @@ struct Texture
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
if(data.bpp == 3)glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,surf.w,surf.h,0,GL_RGB,GL_UNSIGNED_BYTE,data.data.ptr);
|
if(data.bpp == 3)glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,data.size.x,data.size.y,0,GL_RGB,GL_UNSIGNED_BYTE,data.data.ptr);
|
||||||
else if(data.bpp == 4)glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,surf.w,surf.h,0,GL_RGBA,GL_UNSIGNED_BYTE,data.data.ptr);
|
else if(data.bpp == 4)glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,data.size.x,data.size.y,0,GL_RGBA,GL_UNSIGNED_BYTE,data.data.ptr);
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,7 +83,7 @@ struct Texture
|
||||||
glBindTexture(GL_TEXTURE_2D, data.gl_handle);
|
glBindTexture(GL_TEXTURE_2D, data.gl_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destory() @nogc nothrow
|
void destroy() @nogc nothrow
|
||||||
{
|
{
|
||||||
if(data)
|
if(data)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,11 @@ struct vec2
|
||||||
else static assert(0, "Operator "~op~" not implemented");
|
else static assert(0, "Operator "~op~" not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec2 opUnary(string op)()if (op == "-")
|
||||||
|
{
|
||||||
|
return vec2(-x,-y);
|
||||||
|
}
|
||||||
|
|
||||||
ivec2 opCast()
|
ivec2 opCast()
|
||||||
{
|
{
|
||||||
return ivec2(cast(int)x,cast(int)y);
|
return ivec2(cast(int)x,cast(int)y);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ extern(C) float sinf(float x) @nogc nothrow @system;
|
||||||
extern(C) float cosf(float x) @nogc nothrow @system;
|
extern(C) float cosf(float x) @nogc nothrow @system;
|
||||||
extern(C) float powf(float x, float y) @nogc nothrow @system;
|
extern(C) float powf(float x, float y) @nogc nothrow @system;
|
||||||
extern(C) float fabs(float x) @nogc nothrow @system;
|
extern(C) float fabs(float x) @nogc nothrow @system;
|
||||||
|
extern(C) float log2f(float arg) @nogc nothrow @system;
|
||||||
|
|
||||||
|
|
||||||
int randomRange(int min, int max) nothrow @nogc @trusted
|
int randomRange(int min, int max) nothrow @nogc @trusted
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue