Skip to content

Instantly share code, notes, and snippets.

@marionette-of-u
Created December 9, 2012 03:51
Show Gist options
  • Select an option

  • Save marionette-of-u/4243255 to your computer and use it in GitHub Desktop.

Select an option

Save marionette-of-u/4243255 to your computer and use it in GitHub Desktop.
m_shima2 - draft
#include <string>
#include <random>
#include <fstream>
#include <locale>
#include <vector>
#include <memory>
#include <array>
#include <functional>
#include <thread>
#include <mutex>
#include <cstdlib>
#include <boost/preprocessor.hpp>
#include "mpirxx.h"
#include "DxLib.h"
#include "bmp.hpp"
#include "alib.hpp"
#pragma comment(lib, "mpir.lib")
#pragma comment(lib, "mpirxx.lib")
struct set_locale_jp{
set_locale_jp(){
setlocale(LC_CTYPE, "");
std::locale::global(std::locale("japanese"));
}
} set_locale_jp_instance;
namespace const_value{
enum{
mandelbrot_width = 512,
mandelbrot_height = 512,
ui_width = mandelbrot_width,
ui_height = 128,
window_width = mandelbrot_width,
window_height = mandelbrot_height + ui_height
};
}
class input_manager_type{
public:
input_manager_type(){
for(int i = 0; i < 0x100; ++i){
key_buffer[i] = 0;
prev_flag[i] = false;
}
GetMousePoint(&cursor_x[0], &cursor_y[0]);
cursor_x[1] = cursor_x[0];
cursor_y[1] = cursor_y[0];
mouse_state = prev_mouse_state = GetMouseInput();
}
void operator ()(){
for(int i = 0; i < 0x100; ++i){
prev_flag[i] = key_buffer[i] == 1 ? true : false;
}
GetHitKeyStateAll(key_buffer);
cursor_x[1] = cursor_x[0];
cursor_y[1] = cursor_y[0];
GetMousePoint(&cursor_x[0], &cursor_y[0]);
prev_mouse_state = mouse_state;
mouse_state = GetMouseInput();
}
int cursor_coord_x() const{
return cursor_x[0];
}
int prev_cursor_coord_x() const{
return cursor_x[1];
}
int cursor_coord_y() const{
return cursor_y[0];
}
int prev_cursor_coord_y() const{
return cursor_y[1];
}
bool press(int n) const{
return key_buffer[n] == 1;
}
bool push(int n) const{
return key_buffer[n] == 1 && !prev_flag[n];
}
bool release(int n) const{
return key_buffer[n] != 1 && prev_flag[n];
}
bool mouse_press(int n) const{
return (mouse_state & n) != 0;
}
bool mouse_push(int n) const{
return (mouse_state & n) != 0 && !((prev_mouse_state & n) != 0);
}
bool mouse_release(int n) const{
return !((mouse_state & n) != 0) && (prev_mouse_state & n) != 0;
}
private:
char key_buffer[0x100];
bool prev_flag[0x100];
int cursor_x[2], cursor_y[2];
int mouse_state, prev_mouse_state;
} input_manager;
class patter_surface_type{
public:
void load(){
pattern_surface = LoadGraph("d/pattern.bmp");
if(pattern_surface == -1){
std::abort();
}
}
int get() const{
return pattern_surface;
}
private:
int pattern_surface;
} pattern_surface;
namespace pattern{
class pattern{
public:
pattern(const patter_surface_type &pattern_surface_, int x_, int y_, int w_, int h_) :
pattern_surface(&pattern_surface_),
x(x_),
y(y_),
w(w_),
h(h_)
{}
void draw(int dest_x, int dest_y) const{
DrawRectGraph(dest_x, dest_y, x, y, w, h, pattern_surface->get(), FALSE, FALSE);
}
private:
pattern(){}
const patter_surface_type *pattern_surface;
int x, y, w, h;
};
pattern gimg_zero(pattern_surface, 0, 0, 16, 16);
#define WRITE(z, i, nil) \
pattern \
gimg_ ## i(pattern_surface, 16 + i * 16, 0, 16, 16);
BOOST_PP_REPEAT(4, WRITE, nil);
#undef WRITE
pattern *gimg[4] = {
#define WRITE(z, i, nil) BOOST_PP_COMMA_IF(i) &gimg_ ## i
BOOST_PP_REPEAT(4, WRITE, nil)
#undef WRITE
};
#define WRITE(z, i, nil) \
pattern \
num_ ## i(pattern_surface, 0 + i * 5, 48, 5, 7);
BOOST_PP_REPEAT(10, WRITE, nil);
#undef WRITE
pattern *num[10] = {
#define WRITE(z, i, nil) BOOST_PP_COMMA_IF(i) &num_ ## i
BOOST_PP_REPEAT(10, WRITE, nil)
#undef WRITE
};
pattern
num_dot(pattern_surface, 50, 48, 5, 7),
num_plus(pattern_surface, 50 + 5, 48, 5, 7),
num_minus(pattern_surface, 50 + 5 * 2, 48, 5, 7),
char_x(pattern_surface, 0, 56, 4, 6),
char_y(pattern_surface, 4, 56, 4, 6),
char_hyphen(pattern_surface, 8, 56, 4, 6),
str_valueislimit(pattern_surface, 0, 62, 129, 7),
str_failed(pattern_surface, 0, 69, 18, 7),
str_sin(pattern_surface, 0, 76, 20, 7),
str_cos(pattern_surface, 20, 76, 20, 7),
str_tan(pattern_surface, 40, 76, 20, 7);
}
std::string make_filename(std::string ext){
std::time_t time = std::time(nullptr);
std::tm *tm = std::localtime(&time);
char path[0x100];
std::sprintf(
path,
"%04d_%02d_%02d_%02d_%02d_%02d.%s",
tm->tm_year + 1900,
tm->tm_mon + 1,
tm->tm_mday,
tm->tm_hour,
tm->tm_min,
tm->tm_sec,
ext.c_str()
);
return path;
}
struct plain_thread_data_draw{
int fn_pattern_r, fn_pattern_g, fn_pattern_b;
unsigned int rad_a, rad_b, rad_c;
plain_thread_data_draw() :
fn_pattern_r(0), fn_pattern_g(0), fn_pattern_b(0),
rad_a(0), rad_b(0), rad_c(0)
{}
bool operator ==(const plain_thread_data_draw &other) const{
return
fn_pattern_r == other.fn_pattern_r &&
fn_pattern_g == other.fn_pattern_g &&
fn_pattern_b == other.fn_pattern_b &&
rad_a == other.rad_a &&
rad_b == other.rad_b &&
rad_c == other.rad_c;
}
bool operator !=(const plain_thread_data_draw &other) const{
return !(*this == other);
}
};
struct thread_data_draw : plain_thread_data_draw{
mpf_class xmin, xmax, ymin, ymax;
thread_data_draw() : plain_thread_data_draw(), xmin(), xmax(), ymin(), ymax(){}
thread_data_draw &operator =(const thread_data_draw &other){
#define ASSIGN(a) a.set_prec(other.a.get_prec()), a = other.a
ASSIGN(xmin), ASSIGN(xmax), ASSIGN(ymin), ASSIGN(ymax);
#undef ASSIGN
static_cast<plain_thread_data_draw&>(*this) = static_cast<const plain_thread_data_draw&>(other);
return *this;
}
bool operator ==(const thread_data_draw &other) const{
return
(static_cast<const plain_thread_data_draw&>(*this) == static_cast<const plain_thread_data_draw&>(other)) &&
xmin == other.xmin &&
xmax == other.xmax &&
ymin == other.ymin &&
ymax == other.ymax;
}
bool operator !=(const thread_data_draw &other) const{
return !(*this == other);
}
void save() const{
std::ofstream ofile(make_filename("txt").c_str());
if(ofile.fail()){ std::abort(); }
mp_exp_t e = 1;
#define OUT_F(a) ofile << a.get_prec() << "\n" << a.get_str(e) << "\n"; ofile << e << "\n"
OUT_F(xmin), OUT_F(xmax), OUT_F(ymin), OUT_F(ymax);
#undef OUT_F
#define OUT_F(a) ofile << a << "\n"
OUT_F(fn_pattern_r), OUT_F(fn_pattern_g), OUT_F(fn_pattern_b);
OUT_F(rad_a), OUT_F(rad_b), OUT_F(rad_c);
#undef OUT_F
}
void load(){
std::ifstream ifile("read.txt");
if(ifile.fail()){ std::abort(); }
std::string str;
mp_exp_t e;
unsigned int q;
#define READ_MPF(a) READ_F(q); a.set_prec(q); READ_F(str); READ_F(e); a.set_str(str, 10)
#define READ_F(a) ifile >> a; if(ifile.fail()){ goto err; }
READ_MPF(xmin), READ_MPF(xmax), READ_MPF(ymin), READ_MPF(ymax);
READ_F(fn_pattern_r);
READ_F(fn_pattern_g);
READ_F(fn_pattern_b);
READ_F(rad_a);
READ_F(rad_b);
READ_F(rad_c);
#undef READ_F
#undef READ_MPF
return;
err:;
std::ofstream ofile("error.txt");
if(ofile.fail()){ std::abort(); }
ofile << "read.txtの読み込みに失敗\n";
#define SET_X(a, b) a.set_prec(64), a.set_str(b, 10)
SET_X(xmin, "-2"), SET_X(xmax, "2"), SET_X(ymin, "-2"), SET_X(ymax, "2");
#undef SET_X
rad_c = rad_b = rad_a = 0;
}
};
class mpf_prec_ctrl{
public:
static mp_bitcnt_t get(){
return value();
}
static void set(){
mpf_set_default_prec(value());
}
static void set(mp_bitcnt_t v){
value() = v;
mpf_set_default_prec(v);
}
static void set(mp_bitcnt_t v, thread_data_draw &ref){
set(v);
mpf_class a(0, v);
a = ref.xmin;
ref.xmin.set_prec(v);
ref.xmin = a;
a = ref.xmax;
ref.xmax.set_prec(v);
ref.xmax = a;
a = ref.ymin;
ref.ymin.set_prec(v);
ref.ymin = a;
a = ref.ymax;
ref.ymax.set_prec(v);
ref.ymax = a;
}
private:
static mp_bitcnt_t &value(){
static mp_bitcnt_t v = 64;
return v;
}
};
typedef std::array<unsigned char, 3> rgb_type;
typedef tty::alib<>::trigonometric_function<16> tf_type;
tf_type tf;
struct common_data{
std::function<void(int, int, int, rgb_type)> set_pixel;
std::pair<int, int> size;
std::pair<int, int> height_begin_end;
};
volatile bool exit_flag = false;
const unsigned int thread_num = std::thread::hardware_concurrency();
std::unique_ptr<bool[]> generate_flags(new bool[thread_num]);
std::unique_ptr<common_data[]> common_data_array(new common_data[thread_num]);
bool test_all_generate_flags(){
for(unsigned int i = 0; i < thread_num; ++i){
if(generate_flags[i]){ return true; }
}
return false;
}
void set_all_generate_flags(bool a){
for(unsigned int i = 0; i < thread_num; ++i){
generate_flags[i] = a;
}
}
struct init_flag{
init_flag(){
for(unsigned int i = 0; i < thread_num; ++i){
generate_flags[i] = false;
}
}
} init_flag_instance;
class mandelbrot{
public:
static const int maxiter = 0x100;
mandelbrot() :
bmp(nullptr),
thread_array(new std::thread[thread_num]),
color_plt(new rgb_type[maxiter])
{
data.xmin = -2.0, data.xmax = 2.0;
data.ymin = -2.0, data.ymax = 2.0;
data.fn_pattern_r = data.fn_pattern_g = data.fn_pattern_b = 0;
data.rad_a = data.rad_b = data.rad_c = 0;
}
inline static rgb_type rgb(unsigned char r, unsigned char g, unsigned char b){
rgb_type a;
a[0] = r, a[1] = g, a[2] = b;
return a;
}
private:
struct function_pattern{
enum{ sin = 0, cos = 1, tan = 2 };
typedef void (*draw_fn_type)(rgb_type *color, int maxiter, unsigned int rad_a, unsigned int rad_b, unsigned int rad_c, tf_type &tf);
struct draw_fn{
#include "draw_fn.hpp"
};
static draw_fn_type draw_dispatch(int r, int g, int b){
static draw_fn_type fn_array[3 * 3 * 3] = {
#include "draw_fn_enum.hpp"
};
return fn_array[r + g * 3 + b * 3 * 3];
}
};
public:
void make_color_plt(const thread_data_draw &data){
if(this->data != data){
rgb_type *const color = &color_plt[0];
color_plt[0][0] = color_plt[0][1] = 0, color_plt[0][2] = 0;
function_pattern::draw_dispatch(data.fn_pattern_r, data.fn_pattern_g, data.fn_pattern_b)
(&color_plt[0], maxiter, data.rad_a, data.rad_b, data.rad_c, tf);
this->data = data;
}
}
void make(
const int thread_idx,
const common_data &common,
const thread_data_draw &data
){
const int
width = common.size.first,
height = common.size.second,
height_begin = common.height_begin_end.first,
height_end = common.height_begin_end.second;
mpf_class dx = data.xmax - data.xmin, dy = data.ymax - data.ymin;
if(dx == 0 || dy == 0){
generate_flags[thread_idx] = false;
return;
}
int i_max = width, j_max = height_end;
std::unique_ptr<int[]> interrupt_array(new int[thread_num]);
auto recursive_launch_other_thread = [&](const int y, const int end){
int n = 0;
mutex_make_rec_thread.lock();
for(unsigned int i = 0; i < thread_num; ++i){
if(i == thread_idx || thread_array[i].joinable()){
continue;
}
interrupt_array[n++] = i;
}
if(n == 0){
mutex_make_rec_thread.unlock();
return end;
}
int m = end - y;
if(m >= n){
for(int i = 0; i < n - 1; ++i){
int idx = interrupt_array[i];
generate_flags[idx] = true;
common_data_array[idx].set_pixel = common.set_pixel;
common_data_array[idx].size = common.size;
common_data_array[idx].height_begin_end.first = y + (i + 1) * m / (n + 1);
common_data_array[idx].height_begin_end.second = y + (i + 2) * m / (n + 1);
thread_array[idx] = std::thread(&mandelbrot::make, std::ref(*this), idx, std::ref(common_data_array[idx]), std::ref(data));
}
int idx = interrupt_array[n - 1];
generate_flags[idx] = true;
common_data_array[idx].set_pixel = common.set_pixel;
common_data_array[idx].size = common.size;
common_data_array[idx].height_begin_end.first = (y + 1) + m / (n + 1);
common_data_array[idx].height_begin_end.second = end;
thread_array[idx] = std::thread(&mandelbrot::make, std::ref(*this), idx, std::ref(common_data_array[idx]), std::ref(data));
mutex_make_rec_thread.unlock();
return y + m / (n + 1);
}else{
mutex_make_rec_thread.unlock();
return end;
}
};
mpf_class x, y, a, b, a2, b2;
dx /= width, dy /= height;
const mpf_class two = 2, four = 4;
for(int j = height_begin; j <= j_max; ++j){
j_max = recursive_launch_other_thread(j, j_max);
for(int i = 0; i <= i_max; ++i){
x = data.xmin + i * dx;
// y = ymax - j * dy;
y = dy;
y *= -j;
y += data.ymax;
a = x, b = y;
// a2 = a * a;
a2 = a;
a2 *= a;
// b2 = b * b;
b2 = b;
b2 *= b;
int count = maxiter - 1;
while(count != 0 && (a2 + b2) <= four){
// b = 2 * a * b - y;
b *= two;
b *= a;
b -= y;
// a = a2 - b2 - x;
a = a2;
a -= b2;
a -= x;
// a2 = a * a;
a2 = a;
a2 *= a;
// b2 = b * b
b2 = b;
b2 *= b;
--count;
}
if(exit_flag){
return;
}
if(!(i / width || j / height)){
common.set_pixel((width - i - 1), j, count, color_plt[count]);
}else{ break; }
}
}
generate_flags[thread_idx] = false;
}
thread_data_draw data;
tty::bmp *bmp;
std::unique_ptr<std::thread[]> thread_array;
std::thread bmp_thread;
std::unique_ptr<rgb_type[]> color_plt;
std::mutex mutex_make_rec_thread;
private:
mandelbrot(const mandelbrot&){}
} mandelbrot_instance;
struct ui{
enum mode_enum{
mode_title,
mode_mandelbrot
};
enum message_enum{
message_n,
message_value_is_limit,
message_failed
};
enum dad_enum{
dad_off,
dad_on,
dad_lock,
dad_drop
};
ui() :
draw_pixel(),
gcount(0),
buffer_handle(MakeXRGB8ColorSoftImage(const_value::mandelbrot_width, const_value::mandelbrot_height)),
mode(mode_title),
message(message_n),
dad(dad_off),
cache_array()
{
if(buffer_handle == -1){
std::abort();
}
draw_pixel = [&](int x, int y, int pltidx, rgb_type c){
DrawPixelSoftImage_Unsafe_XRGB8(buffer_handle, x, y, c[0], c[1], c[2]);
};
current_data.xmin = -2.0, current_data.xmax = 2.0;
current_data.ymin = -2.0, current_data.ymax = 2.0;
}
bool next_mandelbrot(const thread_data_draw &data){
if(test_all_generate_flags()){ return false; }
join_all_thread();
cache_array.push_back(data);
current_data = data;
mandelbrot_instance.make_color_plt(current_data);
launch_draw_thread(draw_pixel, const_value::mandelbrot_width, const_value::mandelbrot_height, current_data);
return true;
}
bool prev_mandelbrot(){
if(test_all_generate_flags() || cache_array.size() <= 1){ return false; }
join_all_thread();
cache_array.pop_back();
current_data = cache_array.back();
mandelbrot_instance.make_color_plt(current_data);
launch_draw_thread(draw_pixel, const_value::mandelbrot_width, const_value::mandelbrot_height, current_data);
return true;
}
bool put_mandelbrot(const thread_data_draw &data, double p){
if(test_all_generate_flags() || p <= (1.0 / 512.0) || p >= (4194304.0 - 1.0)){ return false; }
current_data = data;
try{
if(mandelbrot_instance.bmp_thread.joinable()){
mandelbrot_instance.bmp_thread.join();
}
std::thread t(
[&](){
int width = static_cast<int>(const_value::mandelbrot_width * p), height = static_cast<int>(const_value::mandelbrot_height * p);
join_all_thread();
mandelbrot_instance.make_color_plt(current_data);
mandelbrot_instance.bmp = new tty::bmp(tty::bmp::ColorNum::n256, width, height);
tty::bmp &bmp(*mandelbrot_instance.bmp);
for(int i = 0xFF; i > 0; --i){
rgb_type a = mandelbrot_instance.color_plt[i];
bmp.setplt(i, tty::bmp::rgb(a[0], a[1], a[2]));
}
set_all_generate_flags(true);
launch_draw_thread(
[&](int x, int y, int pltidx, rgb_type c){
bmp.pltidx(x, y, pltidx);
},
width,
height,
current_data
);
join_generate_thread();
bmp.write(make_filename("bmp").c_str());
delete mandelbrot_instance.bmp;
mandelbrot_instance.bmp = nullptr;
}
);
mandelbrot_instance.bmp_thread.swap(t);
}catch(std::domain_error e){
return false;
}
return true;
}
void proc(){
if(input_manager.mouse_press(MOUSE_INPUT_LEFT) || input_manager.mouse_press(MOUSE_INPUT_RIGHT)){
if(
mode != mode_title &&
dad == dad_off &&
input_manager.cursor_coord_x() >= 0 &&
input_manager.cursor_coord_x() < const_value::mandelbrot_width &&
input_manager.cursor_coord_y() >= 0 &&
input_manager.cursor_coord_y() < const_value::mandelbrot_height
){ dad = dad_on; }
const int offset_y = const_value::mandelbrot_height + 39 + 9 * 5 + 20 - 6;
const unsigned int rad = input_manager.cursor_coord_x();
if(input_manager.cursor_coord_y() >= offset_y && input_manager.cursor_coord_y() <= offset_y + 6){
current_data.rad_a = rad;
}else if(input_manager.cursor_coord_y() >= offset_y + 6 && input_manager.cursor_coord_y() <= offset_y + 12){
current_data.rad_b = rad;
}else if(input_manager.cursor_coord_y() >= offset_y + 12 && input_manager.cursor_coord_y() <= offset_y + 18){
current_data.rad_c = rad;
}
}
if(test_all_generate_flags()){
++gcount;
}else{
if(mode == mode_mandelbrot){
if(input_manager.push(KEY_INPUT_A)){
mode = mode_mandelbrot;
message = message_n;
current_data.xmin = -2.0, current_data.xmax = 2;
current_data.ymin = -2.0, current_data.ymax = 2;
if(!next_mandelbrot(current_data)){
message = message_failed;
}
}else if(input_manager.push(KEY_INPUT_F)){
cache_array.clear();
}else if(input_manager.push(KEY_INPUT_S)){
current_data.save();
}else if(input_manager.push(KEY_INPUT_D)){
current_data.load();
}else if(input_manager.push(KEY_INPUT_Z)){
if(!next_mandelbrot(current_data)){
message = message_failed;
}
}else if(input_manager.push(KEY_INPUT_X)){
if(!prev_mandelbrot()){
message = message_failed;
}
}else if(input_manager.push(KEY_INPUT_B)){
if(!put_mandelbrot(current_data, 1.0)){
message = message_failed;
}
}
switch(dad){
case dad_on:
dad_x_begin = input_manager.cursor_coord_x();
if(dad_x_begin < 0){
dad_x_begin = 0;
}else if(dad_x_begin >= const_value::mandelbrot_width){
dad_x_begin = const_value::mandelbrot_width - 1;
}
dad_y_begin = input_manager.cursor_coord_y();
if(dad_y_begin < 0){
dad_y_begin = 0;
}else if(dad_y_begin >= const_value::mandelbrot_height){
dad_y_begin = const_value::mandelbrot_height - 1;
}
dad = dad_lock;
break;
case dad_drop:
{
int cursor_x = input_manager.cursor_coord_x(), cursor_y = input_manager.cursor_coord_y();
if(cursor_x < 0){
cursor_x = 0;
}else if(cursor_x >= const_value::mandelbrot_width){
cursor_x = const_value::mandelbrot_width - 1;
}
if(cursor_y < 0){
cursor_y = 0;
}else if(cursor_y >= const_value::mandelbrot_height){
cursor_y = const_value::mandelbrot_height - 1;
}
if(dad_x_begin == cursor_x || dad_y_begin == cursor_y){
break;
}
dad = dad_off;
int tx, ty, coex, coey;
if(dad_x_begin < cursor_x){
coex = 1;
tx = cursor_x - dad_x_begin;
}else{
coex = -1;
tx = dad_x_begin - cursor_x;
}
if(dad_y_begin < cursor_y){
coey = 1;
ty = cursor_y - dad_y_begin;
}else{
coey = -1;
ty = dad_y_begin - cursor_y;
}
int m = tx < ty ? tx : ty;
dad_x_end = dad_x_begin + m * coex;
dad_y_end = dad_y_begin + m * coey;
if(dad_x_begin > dad_x_end){
std::swap(dad_x_begin, dad_x_end);
}
dad_y_begin -= const_value::mandelbrot_height / 2;
dad_y_end -= const_value::mandelbrot_height / 2;
dad_y_begin *= -1;
dad_y_end *= -1;
dad_y_begin += const_value::mandelbrot_height / 2;
dad_y_end += const_value::mandelbrot_height / 2;
if(dad_y_begin > dad_y_end){
std::swap(dad_y_begin, dad_y_end);
}
tx = dad_x_end - dad_x_begin, ty = dad_y_end - dad_y_begin;
int length = length = tx < ty ? tx : ty;
{
mpf_class
quantity_x = (current_data.xmax - current_data.xmin) / const_value::mandelbrot_width,
quantity_y = (current_data.ymax - current_data.ymin) / const_value::mandelbrot_height;
current_data.xmin = current_data.xmin + dad_x_begin * quantity_x;
current_data.xmax = current_data.xmin + length * quantity_x;
current_data.ymin = current_data.ymin + dad_y_begin * quantity_y;
current_data.ymax = current_data.ymin + length * quantity_y;
}
if(next_mandelbrot(current_data)){
message = message_n;
}else{
message = message_failed;
}
}
break;
}
}else{
if(input_manager.push(KEY_INPUT_Z)){
mode = mode_mandelbrot;
current_data.xmin = -2.0, current_data.xmax = 2.0;
current_data.ymin = -2.0, current_data.ymax = 2.0;
next_mandelbrot(current_data);
message = message_n;
}
}
}
}
void draw() const{
auto draw_colorbar = [&](int ur, int ug, int ub){
const int offset_y = const_value::mandelbrot_height + 39 + 9 * 5 + 20;
int ar[] = { ur, ug, ub };
for(int i = 0; i < 3; ++i){
int y = offset_y + 6 * i - 3;
DrawLine(0, y, const_value::ui_width, y, GetColor(0x00, 0x00, 0x00));
DrawLine(ar[i], y - 3, ar[i], y + 3, GetColor(0xFF, 0x00, 0x00));
}
};
DrawBox(0, 0, const_value::window_width, const_value::window_height, GetColor(0xFF, 0xFF, 0xFF), TRUE);
pattern::char_x.draw(2, const_value::mandelbrot_height + 2);
draw_int(2, const_value::mandelbrot_height + 9, static_cast<int>(current_data.xmin.get_prec()));
pattern::char_y.draw(2, const_value::mandelbrot_height + 40);
draw_int(2, const_value::mandelbrot_height + 39 + 9, static_cast<int>(current_data.ymin.get_prec()));
draw_fn(
2,
const_value::mandelbrot_height + 39 + 9 * 4,
current_data.fn_pattern_r,
current_data.fn_pattern_g,
current_data.fn_pattern_b
);
draw_colorbar(current_data.rad_a, current_data.rad_b, current_data.rad_c);
for(int i = 0; i < 8; ++i){
pattern::char_hyphen.draw(6 + 4 * i, const_value::mandelbrot_height + 2);
pattern::char_hyphen.draw(6 + 4 * i, const_value::mandelbrot_height + 40);
}
if(test_all_generate_flags()){
pattern::gimg[(gcount / 4) % 4]->draw(const_value::ui_width - 16, const_value::mandelbrot_height);
}else{
if(dad == dad_lock){
int cursor_x = input_manager.cursor_coord_x(), cursor_y = input_manager.cursor_coord_y();
if(cursor_x < 0){
cursor_x = 0;
}else if(cursor_x >= const_value::mandelbrot_width){
cursor_x = const_value::mandelbrot_width - 1;
}
if(cursor_y < 0){
cursor_y = 0;
}else if(cursor_y >= const_value::mandelbrot_height){
cursor_y = const_value::mandelbrot_height - 1;
}
int tx, ty, coex, coey;
if(dad_x_begin < cursor_x){
coex = 1;
tx = cursor_x - dad_x_begin;
}else{
coex = -1;
tx = dad_x_begin - cursor_x;
}
if(dad_y_begin < cursor_y){
coey = 1;
ty = cursor_y - dad_y_begin;
}else{
coey = -1;
ty = dad_y_begin - cursor_y;
}
int m = (std::min)(tx, ty);
DWORD red = GetColor(0xFF, 0x00, 0x00);
DrawLine(dad_x_begin, dad_y_begin, dad_x_begin + m * coex, dad_y_begin, red);
DrawLine(dad_x_begin, dad_y_begin + m * coey, dad_x_begin + m * coex + (coex >= 0 ? 1 : -1), dad_y_begin + m * coey, red);
DrawLine(dad_x_begin, dad_y_begin, dad_x_begin, dad_y_begin + m * coey, red);
DrawLine(dad_x_begin + m * coex, dad_y_begin, dad_x_begin + m * coex, dad_y_begin + m * coey, red);
DrawLine(dad_x_begin, dad_y_begin, cursor_x, cursor_y, red);
}
pattern::gimg_zero.draw(const_value::ui_width - 16, const_value::mandelbrot_height);
}
static const int message_x = 2, message_y = const_value::mandelbrot_height + 100;
switch(message){
case message_value_is_limit:
pattern::str_valueislimit.draw(message_x, message_y);
break;
case message_failed:
pattern::str_failed.draw(message_x, message_y);
break;
}
}
static void draw_int(int x, int y, int v){
auto p10 = [](int d){
int r = 1;
for(int i = 0; i < d; ++i){ r *= 10; }
return r;
};
int d = 0;
for(int i = 0; i < d; ++i){
pattern::num[(v / p10(i)) % 10]->draw(x + i * 5, y);
}
}
static void draw_fn(int x, int y, int a, int b, int c){
int ar[] = { a, b, c };
for(int i = 0; i < 3; ++i){
switch(ar[i]){
case 0:
pattern::str_sin.draw(x + i * 20, y);
break;
case 1:
pattern::str_cos.draw(x + i * 20, y);
break;
case 2:
pattern::str_tan.draw(x + i * 20, y);
break;
}
}
}
void join_generate_thread() const{
for(unsigned int i = 0; i < thread_num; ++i){
if(mandelbrot_instance.thread_array[i].joinable()){
mandelbrot_instance.thread_array[i].join();
}
}
}
void join_all_thread() const{
if(mandelbrot_instance.bmp_thread.joinable()){
mandelbrot_instance.bmp_thread.join();
}
join_generate_thread();
}
static void launch_draw_thread(
std::function<void(int, int, int, rgb_type)> draw_pixel,
int width,
int height,
const thread_data_draw &data
){
mandelbrot_instance.mutex_make_rec_thread.lock();
set_all_generate_flags(true);
for(unsigned int i = 0; i < thread_num - 1; ++i){
common_data_array[i].set_pixel = draw_pixel;
common_data_array[i].size.first = width;
common_data_array[i].size.second = height;
common_data_array[i].height_begin_end.first = i * height / thread_num;
common_data_array[i].height_begin_end.second = (i + 1) * height / thread_num - 1;
mandelbrot_instance.thread_array[i] = std::thread(&mandelbrot::make, std::ref(mandelbrot_instance), i, std::ref(common_data_array[i]), std::ref(data));
}
{
unsigned int n = thread_num - 1;
common_data_array[n].set_pixel = draw_pixel;
common_data_array[n].size.first = width;
common_data_array[n].size.second = height;
common_data_array[n].height_begin_end.first = n * height / thread_num;
common_data_array[n].height_begin_end.second = height;
mandelbrot_instance.thread_array[n] = std::thread(&mandelbrot::make, std::ref(mandelbrot_instance), n, std::ref(common_data_array[n]), std::ref(data));
}
mandelbrot_instance.mutex_make_rec_thread.unlock();
}
std::function<void(int, int, int, rgb_type)> draw_pixel;
int
gcount,
dad_x_begin, dad_x_end,
dad_y_begin, dad_y_end;
int buffer_handle;
thread_data_draw current_data;
mode_enum mode;
message_enum message;
dad_enum dad;
std::vector<thread_data_draw> cache_array;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
if(
ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK ||
SetGraphMode(const_value::window_width, const_value::window_height, 32) != DX_CHANGESCREEN_OK ||
SetMainWindowText("m_shima2 ver 0.0.0") != 0 ||
DxLib_Init() != 0
){ return -1; }
pattern_surface.load();
ui ui_instance;
for(; ; ){
input_manager();
if(ProcessMessage() == -1){
exit_flag = true;
ui_instance.join_all_thread();
break;
}
ui_instance.proc();
ui_instance.draw();
ScreenFlip();
}
DxLib_End();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment