Move to cmake
This commit is contained in:
parent
bea16cbf81
commit
bde42f320f
|
@ -1,3 +1,5 @@
|
|||
demo/allegro5/atomorph-gui
|
||||
demo/atomorph
|
||||
libatomorph.a
|
||||
cmake-build-*
|
||||
.idea
|
|
@ -0,0 +1,8 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/atomorph.iml" filepath="$PROJECT_DIR$/.idea/atomorph.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,46 @@
|
|||
cmake_minimum_required(VERSION 3.16)
|
||||
project("atomorph")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_compile_options(-Wall -Wextra -Werror)
|
||||
|
||||
option(WINDOWS "Whether the build target is Windows or not." OFF)
|
||||
option(SHARED "Whether we should build a shared library, instead of a static one." OFF)
|
||||
|
||||
if (NOT WINDOWS)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
else()
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
|
||||
endif()
|
||||
|
||||
set(LIBTYPE STATIC)
|
||||
if (SHARED)
|
||||
set(LIBTYPE SHARED)
|
||||
endif (SHARED)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
add_link_options(-fuse-ld=lld)
|
||||
endif ()
|
||||
|
||||
file(GLOB_RECURSE SRC_FILES "src/*.cpp")
|
||||
add_library(atomorph ${LIBTYPE} ${SRC_FILES})
|
||||
|
||||
if (WINDOWS)
|
||||
MESSAGE(WARNING, "Using Windows Build.")
|
||||
# Add a definition for the compiler, so we can use it in C++ as well.
|
||||
ADD_DEFINITIONS(-D WINDOWS=1)
|
||||
# -m64: Build a 64 bit library
|
||||
add_compile_options(-m64)
|
||||
if (SHARED)
|
||||
set_target_properties(atomorph PROPERTIES SUFFIX ".dll")
|
||||
endif()
|
||||
endif (WINDOWS)
|
||||
|
||||
if (STATICC)
|
||||
message("Linking dependencies statically.")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
|
||||
set(LINKS -static-libgcc -static-libstdc++ -Wl,-Bstatic -lm -lstdc++ -lpthread -Wl,-Bdynamic ${LINKS})
|
||||
endif(STATICC)
|
||||
target_link_libraries(atomorph ${LINKS})
|
39
Makefile
39
Makefile
|
@ -1,39 +0,0 @@
|
|||
NAME = atomorph
|
||||
CC = gcc
|
||||
PROF = -O2
|
||||
C_FLAGS = -std=c++11 -Wall -pedantic $(PROF)
|
||||
OBJ_DIR = obj
|
||||
|
||||
SRC_FILES := $(wildcard *.cpp)
|
||||
O_FILES := $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
|
||||
|
||||
OUT = ./lib$(NAME).a
|
||||
|
||||
all:
|
||||
@printf "\033[0mHINT: On errors, try \033[1;33m-std=gnu++11 -stdlib=libc++\033[0m compiler flags.\033[0m\n"
|
||||
@printf "\033[0mHINT: Use \033[1;33mmake opencv\033[0m for OpenCV optimizations (experimental).\033[0m\n"
|
||||
@printf "\033[0mHINT: Use \033[1;33mmake deprecated\033[0m to compile the old version.\033[0m\n"
|
||||
@$(MAKE) $(OUT) -s
|
||||
|
||||
opencv: DEFINES = -D ATOMORPH_OPENCV
|
||||
opencv: $(O_FILES)
|
||||
@ar rcs $(OUT) $(O_FILES)
|
||||
@printf "\033[1;32mOpenCV dependent lib$(NAME).a DONE!\033[0m\n"
|
||||
|
||||
deprecated: DEFINES = -D ATOMORPH_DEPRECATED
|
||||
deprecated: $(O_FILES)
|
||||
@ar rcs $(OUT) $(O_FILES)
|
||||
@printf "\033[1;32mDeprecated lib$(NAME).a DONE!\033[0m\n"
|
||||
|
||||
$(OUT): $(O_FILES)
|
||||
@ar rcs $(OUT) $(O_FILES)
|
||||
@printf "\033[1;32mlib$(NAME).a DONE!\033[0m\n"
|
||||
|
||||
$(OBJ_DIR)/%.o: %.cpp
|
||||
@printf "\033[1m\033[31mCompiling \033[37m....\033[34m %-20s\t\033[33m%6s\033[31m lines\033[0m \n" $*.cpp "`wc -l $*.cpp | cut -f1 -d' '`"
|
||||
@$(CC) $(INCLUDE) $< $(DEFINES) $(C_FLAGS) -c -o $@
|
||||
|
||||
clean:
|
||||
@printf "\033[1;36mCleaning \033[37m ...."
|
||||
@rm -f $(O_FILES) $(OUT) *~ *.bak *.orig *.rej
|
||||
@printf "\033[1;37m lib$(NAME).a cleaned!\033[0m\n"
|
|
@ -1,48 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="AtoMorph GUI" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="atomorph-gui" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/" />
|
||||
<Option type="0" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="atomorph-gui" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/" />
|
||||
<Option type="0" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-std=c++11" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add library="liballegro" />
|
||||
<Add library="liballegro_image" />
|
||||
<Add library="liballegro_font" />
|
||||
<Add library="liballegro_primitives" />
|
||||
<Add library="../../libatomorph.a" />
|
||||
</Linker>
|
||||
<Unit filename="main.cpp" />
|
||||
<Unit filename="main.h" />
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<debugger />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
|
@ -1,44 +0,0 @@
|
|||
NAME = atomorph-gui
|
||||
CC = gcc
|
||||
PROF = -O2
|
||||
C_FLAGS = -std=c++11 -Wall $(PROF)
|
||||
L_FLAGS = ../../libatomorph.a -lm -lstdc++ $(PROF)
|
||||
OBJ_DIR = obj
|
||||
DEFINES = -D ATOMORPH_DEPRECATED
|
||||
|
||||
#Change the LIB_DIR to the path where the MODULES are located:
|
||||
LIB_DIR = /usr/lib/
|
||||
MODULES = allegro.so allegro_image.so allegro_font.so allegro_primitives.so
|
||||
|
||||
SRC_FILES := $(wildcard *.cpp)
|
||||
LIB_FILES := $(patsubst %,$(LIB_DIR)/lib%,$(MODULES))
|
||||
O_FILES := $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
|
||||
|
||||
OUT = ./$(NAME)
|
||||
|
||||
all:
|
||||
@printf "\033[0mHINT: libatomorph.a has to be compiled using the \033[1;33mmake deprecated\033[0m command.\033[0m\n"
|
||||
@printf "\033[0mHINT: Use \033[1;33mmake static\033[0m to link statically.\033[0m\n"
|
||||
@$(MAKE) dynamically_linked -s
|
||||
|
||||
static:
|
||||
@$(MAKE) statically_linked -s
|
||||
|
||||
statically_linked: $(O_FILES)
|
||||
@printf "\033[1;33mMaking \033[37m ...."
|
||||
$(CC) -static -o ./$(NAME) $(O_FILES) $(LIB_FILES) $(L_FLAGS)
|
||||
@printf "\033[1;32m Statically linked %s DONE!\033[0m\n" $(NAME)
|
||||
|
||||
dynamically_linked: $(O_FILES)
|
||||
@printf "\033[1;33mMaking \033[37m ...."
|
||||
$(CC) -o ./$(NAME) $(O_FILES) $(LIB_FILES) $(L_FLAGS)
|
||||
@printf "\033[1;32m Dynamically linked %s DONE!\033[0m\n" $(NAME)
|
||||
|
||||
$(OBJ_DIR)/%.o: %.cpp
|
||||
@printf "\033[1m\033[31mCompiling \033[37m....\033[34m %-20s\t\033[33m%6s\033[31m lines\033[0m \n" $*.cpp "`wc -l $*.cpp | cut -f1 -d' '`"
|
||||
@$(CC) $< $(DEFINES) $(C_FLAGS) -c -o $@
|
||||
|
||||
clean:
|
||||
@printf "\033[1;36mCleaning \033[37m ...."
|
||||
@rm -f $(O_FILES) $(OUT) *~ *.bak *.orig *.rej
|
||||
@printf "\033[1;37m $(NAME) cleaned!\033[0m\n"
|
|
@ -1,15 +0,0 @@
|
|||
This AtoMorph-GUI implementation is deprecated because it uses
|
||||
an older version of the AtoMorph Library. The latter has to be
|
||||
compiled using the `deprecated` build target.
|
||||
|
||||
AtoMorph-GUI requires Allegro5.1 installed on your system.
|
||||
|
||||
Build instructions:
|
||||
Run make in this folder.
|
||||
Edit the Makefile if needed.
|
||||
|
||||
Alternative build instructions:
|
||||
Use CodeBlocks and open AtoMorph-GUI.cbp.
|
||||
|
||||
If you like this software, please consider making a donation
|
||||
by sending Bitcoins to 1Erich1YUdkUAp9ynf4Rfw2ug8nBtuUmMu.
|
Binary file not shown.
|
@ -1,561 +0,0 @@
|
|||
/*
|
||||
* See Copyright Notice in main.h
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
const float FPS = 60.0; // Maximum FPS.
|
||||
const int SCREEN_W = 800;
|
||||
const int SCREEN_H = 600;
|
||||
const int MORPH_W = 128; // Width of the morph. Should be at most the width of the input image.
|
||||
const int MORPH_H = 128; // Height of the morph. Should be at most the height of the input image.
|
||||
const int ATOMS = 10000; // Number of atoms used in one thread.
|
||||
const size_t THREAD_N = 5; // Number of threads to use to find a perfect morph.
|
||||
const size_t SLOWNESS = 50; // How many frames to render per animation cycle.
|
||||
|
||||
size_t morph_time = 0;
|
||||
int view_frame = 0;
|
||||
bool pressed_keys[ALLEGRO_KEY_MAX];
|
||||
|
||||
size_t active_thread = 0; // When render is ON, morph only one thread at a time.
|
||||
int color_fade = AM_NONE; // Color interpolation method.
|
||||
int trajectory = AM_NONE; // Atom trajectory interpolation method.
|
||||
bool median_combining = false; // Noise reduction method. FALSE for averaging.
|
||||
bool stop_morphing = false; // To halt the morph time temporarily.
|
||||
bool no_render = false; // When TRUE no blending is done, just atom morphing.
|
||||
|
||||
ALLEGRO_DISPLAY *display = NULL;
|
||||
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
|
||||
ALLEGRO_TIMER *timer = NULL;
|
||||
ALLEGRO_FONT *font = NULL;
|
||||
ALLEGRO_BITMAP *morph_bmp = NULL; // Holds the final morph as a bitmap.
|
||||
ALLEGRO_BITMAP *thread_bmp[THREAD_N]; // Holds the results of the morphing threads.
|
||||
|
||||
// Helper function to initially populate the AM_SCENE object according to the provided
|
||||
// image file.
|
||||
bool fill_scene(AM_SCENE *scene, size_t frame, const char *png_file) {
|
||||
std::random_device rd;
|
||||
std::default_random_engine re(rd());
|
||||
std::uniform_real_distribution<double> uniform_dist(0.0, 1.0);
|
||||
|
||||
ALLEGRO_BITMAP * bmp = al_load_bitmap(png_file);
|
||||
int bmp_w = al_get_bitmap_width(bmp);
|
||||
int bmp_h = al_get_bitmap_height(bmp);
|
||||
|
||||
al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);
|
||||
|
||||
for (int j=0; j<bmp_h; j++) {
|
||||
for (int i=0; i<bmp_w; i++) {
|
||||
ALLEGRO_COLOR c = al_get_pixel(bmp, i, j);
|
||||
|
||||
unsigned char r,g,b,a;
|
||||
al_unmap_rgba(c, &r, &g, &b, &a);
|
||||
|
||||
if (a == 0) continue;
|
||||
double px,py;
|
||||
px = double(i) / double(bmp_w);
|
||||
py = double(j) / double(bmp_h);
|
||||
scene->push_atom(frame, am_create_atom(px,py,r,g,b,a));
|
||||
}
|
||||
}
|
||||
|
||||
al_unlock_bitmap(bmp);
|
||||
al_destroy_bitmap(bmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (!init(argc, argv)) {
|
||||
fprintf(stderr, "Failed to initialize!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::random_device rd;
|
||||
std::default_random_engine seed_engine(rd());
|
||||
std::uniform_int_distribution<unsigned> uniform_dist(1, std::numeric_limits<unsigned>::max());
|
||||
|
||||
morph_bmp = al_create_bitmap(MORPH_W, MORPH_H);
|
||||
al_set_target_bitmap(morph_bmp);
|
||||
al_clear_to_color(al_map_rgba(0,0,0,0));
|
||||
|
||||
AM_BLENDER blender; // Used to combine the thread results into the final morph.
|
||||
blender.set_resolution(MORPH_W, MORPH_H);
|
||||
blender.set_median_combining(median_combining);
|
||||
blender.start();
|
||||
|
||||
AM_THREAD scene_thread[THREAD_N]; // Each of these will morph its own version of the animation.
|
||||
AM_SCENE scene_buf [THREAD_N]; // Temporarily holds the last results of the morphing threads.
|
||||
AM_IMAGE image_buf [THREAD_N]; // Used to render the final image of the provided scene.
|
||||
|
||||
{
|
||||
AM_SCENE scene; // Needed temporarily to store the raw input data.
|
||||
|
||||
scene.init(ATOMS, 6); // Reserve 6 frames for this scene.
|
||||
fill_scene(&scene, 0, "../tests/data/battlelord_1.png");
|
||||
fill_scene(&scene, 1, "../tests/data/battlelord_2.png");
|
||||
fill_scene(&scene, 2, "../tests/data/battlelord_3.png");
|
||||
fill_scene(&scene, 3, "../tests/data/battlelord_4.png");
|
||||
fill_scene(&scene, 4, "../tests/data/battlelord_5.png");
|
||||
fill_scene(&scene, 5, "../tests/data/battlelord_6.png");
|
||||
|
||||
for (size_t i=0; i<THREAD_N; ++i) {
|
||||
scene_buf [i].init(scene.atom_count(), scene.frame_count());
|
||||
scene_thread[i].init(&scene); // Give the initial work to the worker thread.
|
||||
scene_thread[i].set_seed(uniform_dist(seed_engine)); // Seed for its RNG.
|
||||
scene_thread[i].set_step_size(100); // Number of iterations to make per step.
|
||||
scene_thread[i].set_magic_exponent(3.0); // Affects the generated trajectories.
|
||||
scene_thread[i].set_gradient_importance(0.0); // Importance of the color values.
|
||||
scene_thread[i].start();
|
||||
|
||||
thread_bmp[i] = al_create_bitmap(MORPH_W, MORPH_H);
|
||||
al_set_target_bitmap(thread_bmp[i]);
|
||||
al_clear_to_color(al_map_rgba(0,0,0,0));
|
||||
|
||||
image_buf[i].set_scene(&scene); // Prepares the image rendering object.
|
||||
image_buf[i].set_resolution(MORPH_W, MORPH_H);
|
||||
image_buf[i].set_seed(i); // Seed for its RNG (used in Perlin noise).
|
||||
image_buf[i].start();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper variables:
|
||||
bool redraw = true;
|
||||
bool doexit = false;
|
||||
bool started = false;
|
||||
bool debug = false;
|
||||
int frame = 0;
|
||||
double scene_cost = 0.0; // Lower cost means better quality. Cost decreases over time.
|
||||
int old_morph_time = 0;
|
||||
bool refresh = false;
|
||||
|
||||
while(!doexit) {
|
||||
ALLEGRO_EVENT ev;
|
||||
al_wait_for_event(event_queue, &ev);
|
||||
|
||||
if(ev.type == ALLEGRO_EVENT_TIMER) {
|
||||
redraw = true;
|
||||
}
|
||||
else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
|
||||
break;
|
||||
}
|
||||
else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
|
||||
pressed_keys[ev.keyboard.keycode] = true;
|
||||
switch(ev.keyboard.keycode) {
|
||||
case ALLEGRO_KEY_PAD_PLUS: view_frame++; break;
|
||||
case ALLEGRO_KEY_PAD_MINUS: view_frame--; break;
|
||||
case ALLEGRO_KEY_D: debug = !debug; break;
|
||||
case ALLEGRO_KEY_M: median_combining = !median_combining; break;
|
||||
case ALLEGRO_KEY_S: stop_morphing = !stop_morphing; break;
|
||||
case ALLEGRO_KEY_R: no_render = !no_render;
|
||||
if (no_render) old_morph_time = morph_time;
|
||||
else {
|
||||
morph_time = old_morph_time;
|
||||
refresh = true;
|
||||
}
|
||||
break;
|
||||
case ALLEGRO_KEY_C:
|
||||
if (color_fade == AM_NONE) color_fade = AM_LINEAR;
|
||||
else if (color_fade == AM_LINEAR) color_fade = AM_COSINE;
|
||||
else if (color_fade == AM_COSINE) color_fade = AM_PERLIN;
|
||||
else color_fade = AM_NONE;
|
||||
break;
|
||||
case ALLEGRO_KEY_T:
|
||||
if (trajectory == AM_NONE) trajectory = AM_LINEAR;
|
||||
else if (trajectory == AM_LINEAR) trajectory = AM_SPLINE;
|
||||
else trajectory = AM_NONE;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
|
||||
pressed_keys[ev.keyboard.keycode] = false;
|
||||
switch(ev.keyboard.keycode) {
|
||||
case ALLEGRO_KEY_ESCAPE:
|
||||
doexit = true;
|
||||
break;
|
||||
case ALLEGRO_KEY_SPACE:
|
||||
started = !started;
|
||||
|
||||
for (size_t i=0; i<THREAD_N; ++i) {
|
||||
if (!scene_thread[i].is_running()) continue;
|
||||
if (!started) scene_thread[i].pause();
|
||||
else scene_thread[i].resume();
|
||||
}
|
||||
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES ||
|
||||
ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY);
|
||||
else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) ;
|
||||
else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) ;
|
||||
|
||||
if(redraw && al_is_event_queue_empty(event_queue)) {
|
||||
int fps;
|
||||
if ( (fps = calculate_fps()) == -1) continue;
|
||||
|
||||
frame++;
|
||||
|
||||
if (started) {
|
||||
size_t i;
|
||||
bool skip_render = false;
|
||||
|
||||
if (morph_time%SLOWNESS == 0 || refresh) {
|
||||
double cost =0.0;
|
||||
|
||||
active_thread = (active_thread + 1) % THREAD_N;
|
||||
|
||||
for (i=0; i<THREAD_N; ++i) {
|
||||
if (!scene_thread[i].is_paused()) {
|
||||
// Before thread results can be read it must be paused.
|
||||
scene_thread[i].pause();
|
||||
cost += scene_thread[i].get_cost();
|
||||
if (!no_render) {
|
||||
scene_thread[i].fetch_scene(&(scene_buf[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// When rendering is disabled all morphing threads will work,
|
||||
// othwerwise only the active morphing thread works.
|
||||
if (active_thread == i || no_render) scene_thread[i].resume();
|
||||
}
|
||||
scene_cost = cost / THREAD_N;
|
||||
skip_render = true;
|
||||
refresh = false;
|
||||
}
|
||||
else if (no_render) active_thread = (active_thread + 1) % THREAD_N;
|
||||
|
||||
if (no_render) skip_render = true;
|
||||
|
||||
bool slow_down = false; // Is set to TRUE when image rendering in not yet finished.
|
||||
// This is to slow down the animation rather than skip frames.
|
||||
|
||||
if (!skip_render) {
|
||||
bool all_images_done = true;
|
||||
for (i=0; i<THREAD_N; ++i) {
|
||||
if (!image_buf[i].is_paused()) {
|
||||
all_images_done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_images_done && blender.is_paused()) {
|
||||
double t = (morph_time % SLOWNESS)/(double(SLOWNESS));
|
||||
|
||||
// Render blender image:
|
||||
blend_morphs(&blender, morph_bmp);
|
||||
blender.clear();
|
||||
blender.set_median_combining(median_combining);
|
||||
|
||||
for (i=0; i<THREAD_N; ++i) {
|
||||
// Render thread images:
|
||||
render_morph(&image_buf[i], thread_bmp[i]);
|
||||
|
||||
// Give a new job to image blender thread:
|
||||
blender.add_image(&image_buf[i]);
|
||||
|
||||
// Give new job to image thread:
|
||||
image_buf[i].set_scene(&scene_buf[i]);
|
||||
image_buf[i].set_time(t);
|
||||
image_buf[i].set_color_interpolation(color_fade);
|
||||
image_buf[i].set_path_interpolation(trajectory);
|
||||
image_buf[i].resume();
|
||||
}
|
||||
blender.resume();
|
||||
}
|
||||
else slow_down = true; // Image rendering is lagging behind!
|
||||
}
|
||||
|
||||
if (!stop_morphing) {
|
||||
if (!slow_down && ++morph_time == SLOWNESS) morph_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
redraw = false;
|
||||
|
||||
double k = double(MORPH_H) /double(MORPH_W); // Aspect ratio.
|
||||
int merged_h = SCREEN_H - SCREEN_H/8;
|
||||
int merged_w = merged_h * k;
|
||||
|
||||
al_set_target_bitmap(al_get_backbuffer(display));
|
||||
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
|
||||
al_clear_to_color(al_map_rgb(128,128,128));
|
||||
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
|
||||
int mh = SCREEN_H / 8;
|
||||
int mw = mh * k;
|
||||
double s = double(SCREEN_W)/double(THREAD_N);
|
||||
|
||||
// Draw the thread images to the upper side of the screen:
|
||||
for (size_t i=0; i<THREAD_N; ++i) {
|
||||
if (active_thread == i) {
|
||||
al_draw_rectangle(s*i+s/2.0 - mw/2.0, 0.0,
|
||||
s*i+s/2.0 + mw/2.0, mh,
|
||||
al_map_rgb(192,0,0), 4.0);
|
||||
}
|
||||
al_draw_scaled_bitmap(thread_bmp[i], 0.0, 0.0, MORPH_W, MORPH_H,
|
||||
s*i+s/2.0 - mw/2.0, 0.0, mw, mh, 0);
|
||||
}
|
||||
|
||||
// Draw the final morph to the center of the screen:
|
||||
al_draw_scaled_bitmap(morph_bmp, 0.0, 0.0, MORPH_W, MORPH_H,
|
||||
SCREEN_W/2 - merged_w/2, SCREEN_H - merged_h,
|
||||
merged_w, merged_h, 0);
|
||||
|
||||
// Draw textual information:
|
||||
if (font!=NULL) {
|
||||
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
|
||||
|
||||
al_draw_filled_rectangle(0, 0, SCREEN_W-SCREEN_W/4, 14, al_map_rgba(0,0,0,128));
|
||||
al_draw_textf(font, al_map_rgb(0,255,0), 0, 0, 0,
|
||||
"FPS: %3d; Atoms: %d; Cost: %2.3f; Thread: %lu/%lu; Morph time: %lu;",
|
||||
fps, ATOMS, scene_cost, active_thread+1, THREAD_N, morph_time
|
||||
);
|
||||
if (!started) {
|
||||
al_draw_filled_rectangle(0, 0, SCREEN_W, SCREEN_H/4, al_map_rgba(0,0,0,128));
|
||||
|
||||
al_draw_textf(font, al_map_rgb(0,255,0),
|
||||
SCREEN_W/2, SCREEN_H/8, ALLEGRO_ALIGN_CENTRE,
|
||||
"AtoMorph v%s Demo by Erich Erstu, 2013",
|
||||
am_get_version()
|
||||
);
|
||||
|
||||
al_draw_filled_rectangle(0, SCREEN_H - SCREEN_H/4,
|
||||
SCREEN_W, SCREEN_H, al_map_rgba(0,0,0,128)
|
||||
);
|
||||
|
||||
al_draw_textf(font, al_map_rgb(0,255,0), SCREEN_W/2,
|
||||
SCREEN_H - SCREEN_H/8, ALLEGRO_ALIGN_CENTRE, "Press SPACE to start!"
|
||||
);
|
||||
}
|
||||
else {
|
||||
al_draw_filled_rectangle(0, 14, SCREEN_W/3, SCREEN_H/5, al_map_rgba(0,0,0,128));
|
||||
al_draw_textf(font, al_map_rgb(0,255,0), 0, 12, 0,
|
||||
"[M]edian combining: %s", median_combining ? "ON" : "OFF"
|
||||
);
|
||||
|
||||
al_draw_textf(font, al_map_rgb(0,255,0), 0, 24, 0,
|
||||
"[S]top morph time.%s", stop_morphing ? " (Stopped)" : ""
|
||||
);
|
||||
|
||||
al_draw_textf(font, al_map_rgb(0,255,0), 0, 36, 0,
|
||||
"[C]olor interpolation: %s",
|
||||
color_fade == AM_NONE ? "NONE" :
|
||||
color_fade == AM_LINEAR ? "LINEAR" :
|
||||
color_fade == AM_COSINE ? "COSINE" :
|
||||
color_fade == AM_PERLIN ? "PERLIN" : ""
|
||||
);
|
||||
|
||||
al_draw_textf(font, al_map_rgb(0,255,0), 0, 48, 0,
|
||||
"[T]rajectory interpolation: %s",
|
||||
trajectory == AM_NONE ? "NONE" :
|
||||
trajectory == AM_LINEAR ? "LINEAR" :
|
||||
trajectory == AM_SPLINE ? "SPLINE" : ""
|
||||
);
|
||||
|
||||
al_draw_textf(font, al_map_rgb(0,255,0), 0, 60, 0,
|
||||
"[R]endering: %s", !no_render ? "ON" : "OFF");
|
||||
|
||||
al_draw_text (font, al_map_rgb(0,255,0), 0, 72, 0, "SPACE to pause.");
|
||||
al_draw_text (font, al_map_rgb(0,255,0), 0, 84, 0, "ESC to exit.");
|
||||
}
|
||||
}
|
||||
al_flip_display();
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t t=0; t<THREAD_N; ++t) {
|
||||
scene_thread[t].stop();
|
||||
image_buf[t].stop();
|
||||
al_destroy_bitmap(thread_bmp[t]);
|
||||
}
|
||||
blender.stop();
|
||||
|
||||
al_destroy_bitmap(morph_bmp);
|
||||
al_destroy_font(font);
|
||||
al_destroy_timer(timer);
|
||||
al_destroy_display(display);
|
||||
al_destroy_event_queue(event_queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void render_morph(AM_IMAGE *img, ALLEGRO_BITMAP *to) {
|
||||
// Clear old bitmap:
|
||||
al_set_target_bitmap(to);
|
||||
al_set_blender(ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
|
||||
al_draw_filled_rectangle(0.0, 0.0, MORPH_W, MORPH_H, al_map_rgba(0,0,0,255));
|
||||
|
||||
// Prepare to render:
|
||||
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
|
||||
ALLEGRO_LOCKED_REGION * lock = al_lock_bitmap(to,ALLEGRO_PIXEL_FORMAT_ANY,ALLEGRO_LOCK_READWRITE);
|
||||
if (lock == NULL) return;
|
||||
|
||||
// Put the pixels:
|
||||
size_t pixels = img->pixel_count();
|
||||
for (size_t i=0; i<pixels; ++i) {
|
||||
int x,y;
|
||||
unsigned char r,g,b,a;
|
||||
|
||||
img->get_xy(i, &x, &y);
|
||||
img->get_rgba(i, &r, &g, &b, &a);
|
||||
|
||||
al_put_pixel(x, y, al_map_rgba(r,g,b,a));
|
||||
}
|
||||
|
||||
// Finally unlock the bitmap:
|
||||
if (lock) al_unlock_bitmap(to);
|
||||
}
|
||||
|
||||
void blend_morphs(AM_BLENDER *blender, ALLEGRO_BITMAP *to) {
|
||||
// Clear old bitmap:
|
||||
al_set_target_bitmap(to);
|
||||
al_set_blender(ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
|
||||
al_draw_filled_rectangle(0.0, 0.0, MORPH_W, MORPH_H, al_map_rgba(0,0,0,255));
|
||||
|
||||
// Prepare to render:
|
||||
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
|
||||
ALLEGRO_LOCKED_REGION * lock = al_lock_bitmap(to,ALLEGRO_PIXEL_FORMAT_ANY,ALLEGRO_LOCK_READWRITE);
|
||||
if (lock == NULL) return;
|
||||
|
||||
// Put the pixels:
|
||||
size_t pixels = blender->pixel_count();
|
||||
for (size_t i=0; i<pixels; ++i) {
|
||||
int x,y;
|
||||
unsigned char r,g,b,a;
|
||||
|
||||
blender->get_xy(i, &x, &y);
|
||||
blender->get_rgba(i, &r, &g, &b, &a);
|
||||
|
||||
al_put_pixel(x, y, al_map_rgba(r,g,b,a));
|
||||
}
|
||||
|
||||
// Finally unlock the bitmap:
|
||||
if (lock) al_unlock_bitmap(to);
|
||||
}
|
||||
|
||||
bool init(int argc, char **argv) {
|
||||
if (true == (am_get_warning()&AM_WARN_POINTER_SIZE)) {
|
||||
fprintf(stderr, "Pointer size is insufficiently small.\n");
|
||||
}
|
||||
if (true == (am_get_warning()&AM_WARN_ATOM_SIZE)) {
|
||||
fprintf(stderr, "Atom size (%lu) is larger than optimal (%lu).\n",
|
||||
sizeof(AM_ATOM),
|
||||
sizeof(void *)
|
||||
);
|
||||
}
|
||||
|
||||
if(!al_init()) {
|
||||
fprintf(stderr, "failed to initialize allegro!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!al_install_keyboard()) {
|
||||
fprintf(stderr, "failed to initialize the keyboard!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
al_install_mouse();
|
||||
al_init_image_addon();
|
||||
al_init_font_addon();
|
||||
al_init_primitives_addon();
|
||||
|
||||
timer = al_create_timer(1.0 / FPS);
|
||||
if(!timer) {
|
||||
fprintf(stderr, "failed to create timer!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
display = al_create_display(SCREEN_W, SCREEN_H);
|
||||
if(!display) {
|
||||
fprintf(stderr, "failed to create display!\n");
|
||||
al_destroy_timer(timer);
|
||||
return false;
|
||||
}
|
||||
|
||||
al_set_new_bitmap_flags(ALLEGRO_MAG_LINEAR|ALLEGRO_MIN_LINEAR);
|
||||
|
||||
font = al_load_font("data/fixed_font.tga", 0, 0);
|
||||
if (font==NULL) {
|
||||
fprintf(stderr, "failed to load font!\n");
|
||||
al_destroy_display(display);
|
||||
al_destroy_timer(timer);
|
||||
return false;
|
||||
}
|
||||
|
||||
al_set_target_bitmap(al_get_backbuffer(display));
|
||||
|
||||
event_queue = al_create_event_queue();
|
||||
if(!event_queue) {
|
||||
fprintf(stderr, "failed to create event_queue!\n");
|
||||
al_destroy_display(display);
|
||||
al_destroy_timer(timer);
|
||||
al_destroy_font(font);
|
||||
return false;
|
||||
}
|
||||
|
||||
al_register_event_source(event_queue, al_get_display_event_source(display));
|
||||
al_register_event_source(event_queue, al_get_timer_event_source(timer));
|
||||
al_register_event_source(event_queue, al_get_keyboard_event_source());
|
||||
al_register_event_source(event_queue, al_get_mouse_event_source());
|
||||
|
||||
al_clear_to_color(al_map_rgb(0,0,0));
|
||||
al_draw_textf(font, al_map_rgb(0,255,0), SCREEN_W/2, SCREEN_H/2,
|
||||
ALLEGRO_ALIGN_CENTRE,
|
||||
"LOADING...");
|
||||
|
||||
al_flip_display();
|
||||
|
||||
al_start_timer(timer);
|
||||
calculate_fps();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int round_int( double r ) {
|
||||
return (r > 0.0) ? (r + 0.5) : (r - 0.5);
|
||||
}
|
||||
|
||||
int calculate_fps() {
|
||||
static int times = 0;
|
||||
static double old_time = 0.0;
|
||||
static double delta_sum = 0.0;
|
||||
static int old_fps = -1;
|
||||
|
||||
static bool first = true;
|
||||
if (first) {
|
||||
first = false;
|
||||
old_time = al_get_time();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rec_times = 0;
|
||||
int max_times = round_int(FPS);
|
||||
double new_time = al_get_time();
|
||||
double delta = new_time - old_time;
|
||||
delta_sum += delta;
|
||||
old_time = new_time;
|
||||
double p = delta_sum * max_times;
|
||||
rec_times = round_int(p);
|
||||
|
||||
if (times > rec_times) {
|
||||
return -1;
|
||||
}
|
||||
times++;
|
||||
|
||||
int fps = 0;
|
||||
if (delta_sum >= 1.0 || times>=max_times) {
|
||||
fps = times;
|
||||
old_fps = fps;
|
||||
times=0;
|
||||
delta_sum=0.0;
|
||||
}
|
||||
else {
|
||||
if (old_fps == -1) fps = times;
|
||||
else fps = old_fps;
|
||||
}
|
||||
|
||||
return fps;
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* AtoMorph Demo - Simple Demo showing what AtoMorph is capable of doing.
|
||||
* See Copyright Notice at the end of this file.
|
||||
*/
|
||||
|
||||
#include "../../atomorph.h"
|
||||
|
||||
#include <allegro5/allegro.h>
|
||||
#include <allegro5/allegro_font.h>
|
||||
#include <allegro5/allegro_image.h>
|
||||
#include <allegro5/allegro_color.h>
|
||||
#include <allegro5/allegro_primitives.h>
|
||||
|
||||
extern const float FPS;
|
||||
extern const int SCREEN_W;
|
||||
extern const int SCREEN_H;
|
||||
|
||||
extern ALLEGRO_DISPLAY *display ;
|
||||
extern ALLEGRO_EVENT_QUEUE *event_queue ;
|
||||
extern ALLEGRO_TIMER *timer ;
|
||||
extern ALLEGRO_FONT *font ;
|
||||
|
||||
bool init(int argc, char **argv);
|
||||
int calculate_fps();
|
||||
void draw(AM_SCENE *scene, ALLEGRO_BITMAP *to, double t, double weight);
|
||||
void render_morph(AM_IMAGE *img, ALLEGRO_BITMAP *to);
|
||||
void blend_morphs(AM_BLENDER *b, ALLEGRO_BITMAP *to);
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2014 Erich Erstu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
|
@ -1,4 +0,0 @@
|
|||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
|
@ -15,6 +15,7 @@
|
|||
#include <set>
|
||||
#include <limits>
|
||||
#include <assert.h>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef ATOMORPH_OPENCV
|
||||
#include <opencv/cv.h>
|
|
@ -2,6 +2,8 @@
|
|||
* See Copyright Notice in atomorph.h
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace am {
|
||||
|
||||
typedef struct color {
|
|
@ -162,7 +162,7 @@ FluidModel::~FluidModel() {
|
|||
}
|
||||
|
||||
|
||||
void FluidModel::step(size_t steps_left, double freedom_radius, double morph_time) {
|
||||
void FluidModel::step(size_t steps_left, double freedom_radius, [[maybe_unused]]double morph_time) {
|
||||
bool drag = false;
|
||||
double mdx = 0.0, mdy = 0.0;
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
* See Copyright Notice in atomorph.h
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
#include "atomorph.h"
|
||||
|
||||
namespace am {
|
Loading…
Reference in New Issue