boids: initial
This commit is contained in:
parent
04c265e253
commit
7f01fd0483
4
Makefile
4
Makefile
@ -33,7 +33,9 @@ OBJS = \
|
||||
src/hud.o \
|
||||
src/lighting.o \
|
||||
src/collision_scene.o \
|
||||
src/line_art.o
|
||||
src/line_art.o \
|
||||
src/boids.o \
|
||||
src/boids_scene.o
|
||||
|
||||
all: test.so
|
||||
|
||||
|
||||
53
include/boids.h
Normal file
53
include/boids.h
Normal file
@ -0,0 +1,53 @@
|
||||
namespace boids {
|
||||
|
||||
struct boid_configuration {
|
||||
float vision_length;
|
||||
|
||||
struct {
|
||||
float coefficient;
|
||||
} cohesion;
|
||||
|
||||
struct {
|
||||
float coefficient;
|
||||
} alignment;
|
||||
|
||||
struct {
|
||||
float minimum_length;
|
||||
float coefficient;
|
||||
} separation;
|
||||
|
||||
struct {
|
||||
float coefficient;
|
||||
} bounds;
|
||||
};
|
||||
|
||||
struct boid_forces {
|
||||
float vision_neighbor_count;
|
||||
|
||||
struct {
|
||||
// intermediate state
|
||||
XMVECTOR center_of_mass;
|
||||
XMVECTOR force;
|
||||
} cohesion;
|
||||
|
||||
struct {
|
||||
// intermediate state
|
||||
XMVECTOR average_velocity;
|
||||
XMVECTOR force;
|
||||
} alignment;
|
||||
|
||||
struct {
|
||||
// intermediate state
|
||||
XMVECTOR force;
|
||||
} separation;
|
||||
};
|
||||
|
||||
struct boid {
|
||||
XMVECTOR position;
|
||||
XMVECTOR velocity;
|
||||
};
|
||||
|
||||
extern boid_configuration configuration;
|
||||
|
||||
boid_forces const & evaluate(boid const * const boids, int length, int boid_index);
|
||||
}
|
||||
12
include/boids_scene.h
Normal file
12
include/boids_scene.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace boids_scene {
|
||||
|
||||
void update(int up, int down, int left, int right,
|
||||
int w, int s, int a, int d,
|
||||
int t, int g, int f, int h,
|
||||
int i, int k, int j, int l);
|
||||
|
||||
void load();
|
||||
void draw();
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "directxmath/directxmath.h"
|
||||
|
||||
namespace line_art {
|
||||
void load();
|
||||
|
||||
@ -14,5 +16,7 @@ namespace line_art {
|
||||
void draw_capsule(XMMATRIX const & transform, XMVECTOR a, XMVECTOR b, float radius);
|
||||
void draw_cube(XMMATRIX const & transform, XMVECTOR const & position);
|
||||
void scene_start(XMMATRIX const & transform);
|
||||
void draw_grid(XMMATRIX const & transform);
|
||||
void set_color(float r, float g, float b);
|
||||
void set_colorv(XMFLOAT3 const & value);
|
||||
}
|
||||
|
||||
1
main.lua
1
main.lua
@ -120,6 +120,7 @@ function love.run()
|
||||
|
||||
love.graphics.present()
|
||||
love.timer.sleep(0.001)
|
||||
--love.timer.sleep(0.1)
|
||||
--local fps = love.timer.getFPS( )
|
||||
--print(fps)
|
||||
end
|
||||
|
||||
29
minecraft/gen/arrow.obj
Normal file
29
minecraft/gen/arrow.obj
Normal file
@ -0,0 +1,29 @@
|
||||
# Blender 5.0.0
|
||||
# www.blender.org
|
||||
o Cone
|
||||
v 0.000000 -1.000000 -1.000000
|
||||
v 1.000000 -1.000000 0.000000
|
||||
v 0.000000 -1.000000 1.000000
|
||||
v -1.000000 -1.000000 0.000000
|
||||
v 0.000000 1.000000 0.000000
|
||||
vn 0.6667 0.3333 -0.6667
|
||||
vn 0.6667 0.3333 0.6667
|
||||
vn -0.0000 -1.0000 -0.0000
|
||||
vn -0.6667 0.3333 0.6667
|
||||
vn -0.6667 0.3333 -0.6667
|
||||
vt 0.250000 0.490000
|
||||
vt 0.250000 0.250000
|
||||
vt 0.490000 0.250000
|
||||
vt 0.250000 0.010000
|
||||
vt 0.990000 0.250000
|
||||
vt 0.510000 0.250000
|
||||
vt 0.750000 0.490000
|
||||
vt 0.010000 0.250000
|
||||
vt 0.750000 0.010000
|
||||
s 0
|
||||
f 1/1/1 5/2/1 2/3/1
|
||||
f 2/3/2 5/2/2 3/4/2
|
||||
f 2/5/3 4/6/3 1/7/3
|
||||
f 3/4/4 5/2/4 4/8/4
|
||||
f 4/8/5 5/2/5 1/1/5
|
||||
f 2/5/3 3/9/3 4/6/3
|
||||
102
src/boids.cpp
Normal file
102
src/boids.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "directxmath/directxmath.h"
|
||||
|
||||
#include "boids.h"
|
||||
|
||||
namespace boids {
|
||||
|
||||
boid_forces forces;
|
||||
boid_configuration configuration;
|
||||
|
||||
static inline void reset_cohesion()
|
||||
{
|
||||
forces.cohesion.center_of_mass = XMVectorZero();
|
||||
forces.cohesion.force = XMVectorZero();
|
||||
}
|
||||
|
||||
static inline void reset_alignment()
|
||||
{
|
||||
forces.alignment.average_velocity = XMVectorZero();
|
||||
forces.alignment.force = XMVectorZero();
|
||||
}
|
||||
|
||||
static inline void reset_separation()
|
||||
{
|
||||
forces.separation.force = XMVectorZero();
|
||||
}
|
||||
|
||||
inline constexpr bool vector_equal(XMVECTOR V1, XMVECTOR V2)
|
||||
{
|
||||
uint32_t CR;
|
||||
XMVectorEqualR(&CR, V1, V2);
|
||||
return XMComparisonAllTrue(CR);
|
||||
}
|
||||
|
||||
static inline XMVECTOR cohesion_force(boid const & this_boid, float const reciprocal_neighbor_count)
|
||||
{
|
||||
XMVECTOR center_of_mass = forces.cohesion.center_of_mass * reciprocal_neighbor_count;
|
||||
XMVECTOR cohesion_vector = center_of_mass - this_boid.position;
|
||||
if (vector_equal(cohesion_vector, XMVectorZero()))
|
||||
return XMVectorZero();
|
||||
XMVECTOR cohesion_direction = XMVector3NormalizeEst(cohesion_vector);
|
||||
return cohesion_direction * configuration.cohesion.coefficient;
|
||||
}
|
||||
|
||||
static inline XMVECTOR alignment_force(boid const & this_boid, float const reciprocal_neighbor_count)
|
||||
{
|
||||
XMVECTOR average_velocity = forces.alignment.average_velocity * reciprocal_neighbor_count;
|
||||
XMVECTOR alignment_vector = average_velocity - this_boid.velocity;
|
||||
if (vector_equal(alignment_vector, XMVectorZero()))
|
||||
return XMVectorZero();
|
||||
XMVECTOR alignment_direction = XMVector3NormalizeEst(alignment_vector);
|
||||
return alignment_direction * configuration.alignment.coefficient;
|
||||
}
|
||||
|
||||
boid_forces const & evaluate(boid const * const boids, int length, int boid_index)
|
||||
{
|
||||
forces.vision_neighbor_count = 0;
|
||||
|
||||
reset_cohesion();
|
||||
reset_alignment();
|
||||
reset_separation();
|
||||
|
||||
boid const & this_boid = boids[boid_index];
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == boid_index)
|
||||
continue;
|
||||
|
||||
boid const & other_boid = boids[i];
|
||||
|
||||
XMVECTOR position_vector = this_boid.position - other_boid.position;
|
||||
float position_length = XMVectorGetX(XMVector3LengthEst(position_vector));
|
||||
if (position_length < configuration.vision_length) {
|
||||
forces.vision_neighbor_count += 1;
|
||||
|
||||
// cohesion
|
||||
forces.cohesion.center_of_mass += other_boid.position;
|
||||
|
||||
// alignment
|
||||
forces.alignment.average_velocity += other_boid.velocity;
|
||||
}
|
||||
|
||||
// separation
|
||||
if (vector_equal(position_vector, XMVectorZero()))
|
||||
continue;
|
||||
if (position_length < configuration.separation.minimum_length) {
|
||||
float reciprocal_position_length = 1.0f / position_length;
|
||||
//float reciprocal_position_length = 1.0f;
|
||||
XMVECTOR separation_direction = position_vector * reciprocal_position_length;
|
||||
forces.separation.force += separation_direction * reciprocal_position_length * configuration.separation.coefficient;
|
||||
}
|
||||
}
|
||||
|
||||
if (forces.vision_neighbor_count != 0) {
|
||||
float reciprocal_vision_neighbor_count = 1.0f / forces.vision_neighbor_count;
|
||||
forces.cohesion.force = cohesion_force(this_boid, reciprocal_vision_neighbor_count);
|
||||
forces.alignment.force = alignment_force(this_boid, reciprocal_vision_neighbor_count);
|
||||
}
|
||||
|
||||
return forces;
|
||||
}
|
||||
}
|
||||
116
src/boids_scene.cpp
Normal file
116
src/boids_scene.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "glad/gl.h"
|
||||
|
||||
#include "line_art.h"
|
||||
#include "boids.h"
|
||||
|
||||
namespace boids_scene {
|
||||
|
||||
const int boids_length = 20;
|
||||
boids::boid boids[boids_length];
|
||||
|
||||
const XMFLOAT3 colors[] = {
|
||||
{(float)0xb5 / 255.0, (float)0x7f / 255.0, (float)0x50 / 255.0},
|
||||
{(float)0x37 / 255.0, (float)0xff / 255.0, (float)0x8b / 255.0},
|
||||
{(float)0x51 / 255.0, (float)0xd6 / 255.0, (float)0xff / 255.0},
|
||||
{(float)0x54 / 255.0, (float)0x2e / 255.0, (float)0x71 / 255.0},
|
||||
{(float)0xff / 255.0, (float)0x84 / 255.0, (float)0x84 / 255.0},
|
||||
};
|
||||
|
||||
void update(int up, int down, int left, int right,
|
||||
int w, int s, int a, int d,
|
||||
int t, int g, int f, int h,
|
||||
int i, int k, int j, int l)
|
||||
{
|
||||
float rate = 0.05f;
|
||||
|
||||
float forward[4];
|
||||
float strafe[4];
|
||||
|
||||
forward[0] = (rate * up + -rate * down);
|
||||
strafe[0] = (-rate * left + rate * right);
|
||||
|
||||
forward[1] = (rate * w + -rate * s);
|
||||
strafe[1] = (-rate * a + rate * d);
|
||||
|
||||
forward[2] = (rate * t + -rate * g);
|
||||
strafe[2] = (-rate * f + rate * h);
|
||||
|
||||
forward[3] = (rate * i + -rate * k);
|
||||
strafe[3] = (-rate * j + rate * l);
|
||||
|
||||
//for (int i = 0; i < 4; i++)
|
||||
//point_position[i] = XMVector3Transform(point_position[i], XMMatrixTranslation(strafe[i], forward[i], 0));
|
||||
}
|
||||
|
||||
static inline float random()
|
||||
{
|
||||
float r = 1.0f / (float)RAND_MAX;
|
||||
return (float)rand() * r * 2.0f - 1.0f;
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
srand(0x12345678);
|
||||
|
||||
for (int i = 0; i < boids_length; i++) {
|
||||
boids[i].position = XMVectorSet(random() * 5, random() * 5, 0, 0);
|
||||
boids[i].velocity = XMVectorSet(random(), random(), 0, 0);
|
||||
}
|
||||
|
||||
|
||||
boids::configuration.vision_length = 2.0f;
|
||||
boids::configuration.cohesion.coefficient = 0.001f;
|
||||
boids::configuration.alignment.coefficient = 0.01f;
|
||||
boids::configuration.separation.minimum_length = 0.7f;
|
||||
boids::configuration.separation.coefficient = 0.5f;
|
||||
boids::configuration.bounds.coefficient = 0.02f;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
XMMATRIX transform = line_art::view() * line_art::projection();
|
||||
|
||||
line_art::scene_start(transform);
|
||||
|
||||
glLineWidth(1.0f);
|
||||
|
||||
line_art::set_colorv(colors[4]);
|
||||
for (int i = 0; i < boids_length; i++)
|
||||
line_art::draw_sphere(transform, boids[i].position, 0.3);
|
||||
|
||||
for (int i = 0; i < boids_length; i++) {
|
||||
boids::boid_forces const & forces = evaluate(boids, boids_length, i);
|
||||
|
||||
glLineWidth(4.0f);
|
||||
line_art::set_colorv(colors[0]);
|
||||
line_art::draw_line(transform, boids[i].position, boids[i].position + forces.cohesion.force);
|
||||
line_art::set_colorv(colors[1]);
|
||||
line_art::draw_line(transform, boids[i].position, boids[i].position + forces.alignment.force);
|
||||
line_art::set_colorv(colors[2]);
|
||||
line_art::draw_line(transform, boids[i].position, boids[i].position + forces.separation.force);
|
||||
|
||||
boids[i].velocity += forces.cohesion.force + forces.alignment.force + forces.separation.force;
|
||||
const float speed_limit = 2.0;
|
||||
if (XMVectorGetX(XMVector3LengthEst(boids[i].velocity)) > speed_limit) {
|
||||
boids[i].velocity = XMVector3NormalizeEst(boids[i].velocity) * speed_limit;
|
||||
}
|
||||
|
||||
if (XMVectorGetX(boids[i].position) > 5.0)
|
||||
boids[i].velocity += XMVectorSetX(XMVectorZero(), -boids::configuration.bounds.coefficient);
|
||||
|
||||
if (XMVectorGetX(boids[i].position) < -5.0)
|
||||
boids[i].velocity += XMVectorSetX(XMVectorZero(), boids::configuration.bounds.coefficient);
|
||||
|
||||
if (XMVectorGetY(boids[i].position) > 5.0)
|
||||
boids[i].velocity += XMVectorSetY(XMVectorZero(), -boids::configuration.bounds.coefficient);
|
||||
|
||||
if (XMVectorGetY(boids[i].position) < -5.0)
|
||||
boids[i].velocity += XMVectorSetY(XMVectorZero(), boids::configuration.bounds.coefficient);
|
||||
|
||||
boids[i].position += boids[i].velocity * 0.05f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,7 +169,7 @@ namespace line_art {
|
||||
|
||||
XMMATRIX projection()
|
||||
{
|
||||
return XMMatrixOrthographicRH(10, 10, 0, 10);
|
||||
return XMMatrixOrthographicRH(20, 20, 0, 10);
|
||||
}
|
||||
|
||||
void set_transform(XMMATRIX const & transform)
|
||||
@ -227,6 +227,18 @@ namespace line_art {
|
||||
glDrawElementsBaseVertex(GL_LINE_STRIP, 5, GL_UNSIGNED_SHORT, (void*)(cube_base_index), cube_base_vertex);
|
||||
}
|
||||
|
||||
void draw_grid(XMMATRIX const & transform)
|
||||
{
|
||||
// grid
|
||||
glLineWidth(1.0f);
|
||||
set_transform(transform);
|
||||
glUniform3f(location.uniform.base_color, 0, 1, 0);
|
||||
glUniform1i(location.uniform.use_grid_transform, 1);
|
||||
glDrawArraysInstanced(GL_LINES, 0, 4, 7);
|
||||
|
||||
glUniform1i(location.uniform.use_grid_transform, 0);
|
||||
}
|
||||
|
||||
void scene_start(XMMATRIX const & transform)
|
||||
{
|
||||
glUseProgram(program);
|
||||
@ -238,19 +250,15 @@ namespace line_art {
|
||||
glBindVertexArray(vertex_array_object);
|
||||
glBindVertexBuffer(0, per_vertex_buffer, 0, per_vertex_size);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
|
||||
|
||||
// grid
|
||||
glLineWidth(1.0f);
|
||||
set_transform(transform);
|
||||
glUniform3f(location.uniform.base_color, 0, 1, 0);
|
||||
glUniform1i(location.uniform.use_grid_transform, 1);
|
||||
glDrawArraysInstanced(GL_LINES, 0, 4, 7);
|
||||
|
||||
glUniform1i(location.uniform.use_grid_transform, 0);
|
||||
}
|
||||
|
||||
void set_color(float r, float g, float b)
|
||||
{
|
||||
glUniform3f(location.uniform.base_color, r, g, b);
|
||||
}
|
||||
|
||||
void set_colorv(XMFLOAT3 const & value)
|
||||
{
|
||||
glUniform3fv(location.uniform.base_color, 1, (float const *)&value);
|
||||
}
|
||||
}
|
||||
|
||||
11
src/test.cpp
11
src/test.cpp
@ -20,6 +20,7 @@
|
||||
#include "line_art.h"
|
||||
#include "collision_scene.h"
|
||||
#include "collision.h"
|
||||
#include "boids_scene.h"
|
||||
|
||||
struct line_location {
|
||||
struct {
|
||||
@ -288,6 +289,7 @@ void load(const char * source_path)
|
||||
|
||||
line_art::load();
|
||||
collision_scene::load();
|
||||
boids_scene::load();
|
||||
}
|
||||
|
||||
void update_keyboard(int up, int down, int left, int right,
|
||||
@ -298,10 +300,16 @@ void update_keyboard(int up, int down, int left, int right,
|
||||
//float forward = (0.1f * up + -0.1f * down);
|
||||
//float strafe = (-0.1f * left + 0.1f * right);
|
||||
//view::third_person::apply_translation(forward, strafe, 0);
|
||||
/*
|
||||
collision_scene::update(up, down, left, right,
|
||||
w, s, a, d,
|
||||
t, g, f, h,
|
||||
i, k, j, l);
|
||||
*/
|
||||
boids_scene::update(up, down, left, right,
|
||||
w, s, a, d,
|
||||
t, g, f, h,
|
||||
i, k, j, l);
|
||||
}
|
||||
|
||||
void check_collisions(collision::Sphere const & sphere, XMVECTOR const & direction,
|
||||
@ -560,7 +568,8 @@ void draw()
|
||||
} else {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
collision_scene::draw();
|
||||
//collision_scene::draw();
|
||||
boids_scene::draw();
|
||||
}
|
||||
|
||||
last_frame_time = current_time;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user