Skip to content

Commit

Permalink
Big refactor, separate the library code and the usage examples.
Browse files Browse the repository at this point in the history
  • Loading branch information
casensiom committed Nov 11, 2023
1 parent 7cf894d commit 97b23a1
Show file tree
Hide file tree
Showing 14 changed files with 989 additions and 625 deletions.
24 changes: 2 additions & 22 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,6 @@
cmake_minimum_required(VERSION 3.16)

project(metaball)
project(metaballs)
set(CMAKE_C_STANDARD 99)
# set(CMAKE_C_STANDARD_REQUIRED TRUE)

# raylib
find_package(raylib QUIET)
if (NOT raylib_FOUND)
include(FetchContent)
FetchContent_Declare(
raylib
GIT_REPOSITORY https://github.com/raysan5/raylib.git
GIT_TAG 4.5.0
)
FetchContent_MakeAvailable(raylib)
endif()

message(STATUS "PROJECT_NAME: ${PROJECT_NAME}")
add_executable(${PROJECT_NAME} main.c metaballs.h)
target_link_libraries(${PROJECT_NAME} PUBLIC raylib)

add_custom_target(copy_assets
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets
)
add_dependencies(${PROJECT_NAME} copy_assets)
add_subdirectory(examples)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

![Thumbnail](./thumbnail.jpg)

Header only 3d metaballs generator in ANSI C
Header only 3d metaballs generator in C99

## About

[![Build Status](https://github.com/casensiom/metaballs/actions/workflows/cmake-multi-platform.yml/badge.svg)](https://github.com/casensiom/metaballs/actions)

This library computes 3d metaballs in pure ANSI C.
This library computes 3d metaballs in pure C99.

![Thumbnail](./thumbnail.gif)

Expand Down
Binary file removed assets/texel_checker.png
Binary file not shown.
34 changes: 34 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# raylib
find_package(raylib QUIET)
if (NOT raylib_FOUND)
include(FetchContent)
FetchContent_Declare(
raylib
GIT_REPOSITORY https://github.com/raysan5/raylib.git
GIT_TAG 4.5.0
)
FetchContent_MakeAvailable(raylib)
endif()

add_library(metaball_dependency
raylib_wrapper.h
raylib_wrapper.c
ball.h
ball.c
)
target_link_libraries(metaball_dependency PUBLIC raylib)

add_custom_target(copy_assets
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets
)
add_dependencies(metaball_dependency copy_assets)

add_executable(example0 example0.c)
target_link_libraries(example0 PUBLIC metaball_dependency)

add_executable(example1 example1.c)
target_link_libraries(example1 PUBLIC metaball_dependency)

add_executable(example2 example2.c)
target_link_libraries(example2 PUBLIC metaball_dependency)

Binary file added examples/assets/uv.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions examples/ball.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "ball.h"

void ball_push(BallArray *balls, Ball ball)
{
balls->items[balls->count] = ball;
balls->count++;
}

Ball ball_create_random(Grid grid)
{
float radius_x = (grid.count.x * grid.size.x) / 4;
float radius_y = (grid.count.y * grid.size.y) / 4;
float radius_z = (grid.count.z * grid.size.z) / 4;

Vector3d speed = {
.x = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f),
.y = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f),
.z = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f)};

Vector3d initial = {
.x = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f),
.y = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f),
.z = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f)};

Vector3d p = (Vector3d){
.x = grid.center.x + radius_x * cos(initial.x),
.y = grid.center.y + radius_y * sin(initial.y),
.z = grid.center.z + radius_z * cos(initial.z)};

Color4C color = (Color4C){
.r = (unsigned char)(64 + (rand() % 192)),
.g = (unsigned char)(128 + (rand() % 128)),
.b = (unsigned char)(128 + (rand() % 128)),
.a = (unsigned char)(255)
};

float ball_mass = 50.0f + (float)(rand() % 200);

return (Ball){.pos = p, .mass = ball_mass, .color = color};
}
9 changes: 9 additions & 0 deletions examples/ball.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef _BALL_H_
#define _BALL_H_

#include "../metaballs.h"

void ball_push(BallArray *balls, Ball ball);
Ball ball_create_random(Grid grid);

#endif //_BALL_H_
113 changes: 113 additions & 0 deletions examples/example0.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "ball.h"
#include "raylib_wrapper.h"

int main(int argc, char *argv[])
{
const int screenWidth = 800;
const int screenHeight = 400;
InitWindow(screenWidth, screenHeight, "Metaballs");
//DisableCursor();

Index3d count = {.x = 10, .y = 10, .z = 10};
Vector3d size = {.x = 2, .y = 2, .z = 2};
Vector3d pos = {.x = 0, .y = 0, .z = 0};
Grid grid = grid_create(count, size, pos);

BallArray balls = MB_CREATE_ARRAY(Ball, 3);

Vector3d zero = {
.x = 0.0f,
.y = 0.0f,
.z = 0.0f};

Vector3d center = (Vector3d){
.x = grid.center.x,
.y = grid.center.y,
.z = grid.center.z};

Color4C color = (Color4C){
.r = 0xff,
.g = 0xff,
.b = 0xff,
.a = 0xff
};
ball_push(&balls, (Ball){.pos = center, .mass = 15, .color = color});

// Define the camera to look into our 3d world
Camera camera = {0};
camera.position = (Vector3){grid.center.x, grid.center.y, grid.center.z - grid.count.z * grid.size.z * 1.5}; // Camera position
camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; // Camera looking at point
camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type


Material wired = LoadMaterialDefault();
wired.maps[MATERIAL_MAP_DIFFUSE].color = GRAY;
wired.maps[MATERIAL_MAP_SPECULAR].color = GRAY;

Texture2D text2d = LoadTexture("assets/uv.png");
SetTextureWrap(text2d, TEXTURE_WRAP_CLAMP);
Material material = LoadMaterialDefault();
material.maps[MATERIAL_MAP_DIFFUSE].texture = text2d;
material.maps[MATERIAL_MAP_SPECULAR].color = GRAY;

Matrix transform = (Matrix){1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};

// RL upload mesh
Mesh rayMesh = raylib_upload_mesh(grid);

while (!WindowShouldClose()) // Detect window close button or ESC key
{

UpdateCamera(&camera, CAMERA_THIRD_PERSON);
camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z};

if(IsKeyPressed(KEY_U)) {
grid.config.wired = !grid.config.wired;
}
if(IsKeyPressed(KEY_P)) {
grid.config.mapping = MAPPING_PLANAR;
}
if(IsKeyPressed(KEY_L)) {
grid.config.mapping = MAPPING_SPHERIC;
}

if(IsKeyPressed(KEY_H)) {
grid.config.threshold += 0.05f;
}
if(IsKeyPressed(KEY_J)) {
grid.config.threshold -= 0.05f;
}

generate_mesh(&grid, balls);

BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// RL render mesh
raylib_render_mesh(grid, &rayMesh, material, wired, transform);
EndMode3D();

char label_fps[256];
sprintf(label_fps, "FPS: %d", GetFPS());
DrawText(label_fps, 10, 10, 20, BLACK);

// sprintf(label_fps, "CACHE HIT: %lu, MISS: %lu", cache_hit, cache_miss);
// DrawText(label_fps, 10, 50, 20, BLACK);
EndDrawing();
}


// RL unload mesh
raylib_unload_mesh(&rayMesh);
MB_DESTROY_ARRAY(balls);
grid_destroy(&grid);

CloseWindow();

return 0;
}
128 changes: 128 additions & 0 deletions examples/example1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "ball.h"
#include "raylib_wrapper.h"


void update_balls(BallArray balls, Vector3d pos, float radius) {

float t = GetTime();

Vector3d movement[] = {{.x = 1.1, .y = 1.3, .z = 1.7},
{.x = 0.7, .y = 1.9, .z = 2.3},
{.x = 0.3, .y = 2.9, .z = 1.1},
{.x = 1.3, .y = 1.7, .z = 0.7},
{.x = 2.3, .y = 1.9, .z = 2.9}};
const size_t count = sizeof(movement) / sizeof(movement[0]);


float ec = radius;
for (size_t i = 0; i < balls.count; i++)
{
Vector3d m = movement[i % count];
balls.items[i].pos = (Vector3d){.x = pos.x - cos(t*m.x) * radius,
.y = pos.y - cos(t*m.y) * radius,
.z = pos.z - cos(t*m.z) * radius};

}
}


int main(int argc, char *argv[])
{
const int screenWidth = 800;
const int screenHeight = 400;
InitWindow(screenWidth, screenHeight, "Metaballs");
DisableCursor();

Index3d count = {.x = 20 * 2, .y = 20 * 2, .z = 20 * 2};
Vector3d size = {.x = 10 / 2, .y = 10 / 2, .z = 10 / 2};
Vector3d pos = {.x = 0, .y = 0, .z = 0};
Grid grid = grid_create(count, size, pos);

BallArray balls = MB_CREATE_ARRAY(Ball, 5);
for (size_t i = 0; i < balls.capacity; i++)
{
ball_push(&balls, ball_create_random(grid));
}

// Define the camera to look into our 3d world
Camera camera = {0};
camera.position = (Vector3){grid.center.x, grid.center.y, grid.center.z - grid.count.z * grid.size.z * 1.5}; // Camera position
camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; // Camera looking at point
camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type


Material wired = LoadMaterialDefault();
wired.maps[MATERIAL_MAP_DIFFUSE].color = GRAY;
wired.maps[MATERIAL_MAP_SPECULAR].color = GRAY;

Texture2D text2d = LoadTexture("assets/uv.png");
SetTextureWrap(text2d, TEXTURE_WRAP_MIRROR_REPEAT);
Material material = LoadMaterialDefault();
material.maps[MATERIAL_MAP_DIFFUSE].texture = text2d;
material.maps[MATERIAL_MAP_SPECULAR].color = GRAY;

Matrix transform = (Matrix){1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};

// RL upload mesh
Mesh rayMesh = raylib_upload_mesh(grid);

while (!WindowShouldClose()) // Detect window close button or ESC key
{

UpdateCamera(&camera, CAMERA_THIRD_PERSON);
camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z};

if (!IsKeyDown(KEY_SPACE))
{
update_balls(balls, grid.center, grid.size.x * 10);
}
if(IsKeyPressed(KEY_U)) {
grid.config.wired = !grid.config.wired;
}
if(IsKeyPressed(KEY_P)) {
grid.config.mapping = MAPPING_PLANAR;
}
if(IsKeyPressed(KEY_L)) {
grid.config.mapping = MAPPING_SPHERIC;
}

if(IsKeyPressed(KEY_H)) {
grid.config.threshold += 0.05f;
}
if(IsKeyPressed(KEY_J)) {
grid.config.threshold -= 0.05f;
}

generate_mesh(&grid, balls);

BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// RL render mesh
raylib_render_mesh(grid, &rayMesh, material, wired, transform);
EndMode3D();

char label_fps[256];
sprintf(label_fps, "FPS: %d", GetFPS());
DrawText(label_fps, 10, 10, 20, BLACK);

// sprintf(label_fps, "CACHE HIT: %lu, MISS: %lu", cache_hit, cache_miss);
// DrawText(label_fps, 10, 50, 20, BLACK);
EndDrawing();
}


// RL unload mesh
raylib_unload_mesh(&rayMesh);
MB_DESTROY_ARRAY(balls);
grid_destroy(&grid);

CloseWindow();

return 0;
}
Loading

0 comments on commit 97b23a1

Please sign in to comment.