curvedraw

diff src/app.cc @ 0:8e524989c904

getting there
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 15 Dec 2015 07:15:53 +0200
parents
children 7dcd0f6113e5
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/app.cc	Tue Dec 15 07:15:53 2015 +0200
     1.3 @@ -0,0 +1,292 @@
     1.4 +#include <stdlib.h>
     1.5 +#include <float.h>
     1.6 +#include <vector>
     1.7 +#include <algorithm>
     1.8 +#include "opengl.h"
     1.9 +#include "app.h"
    1.10 +#include "curve.h"
    1.11 +#include "widgets.h"
    1.12 +
    1.13 +static void draw_grid(float sz, float sep, float alpha = 1.0f);
    1.14 +static void draw_curve(const Curve *curve);
    1.15 +static void on_click(int bn, float u, float v);
    1.16 +
    1.17 +static int win_width, win_height;
    1.18 +static float win_aspect;
    1.19 +
    1.20 +static float view_pan_x, view_pan_y;
    1.21 +static float view_scale = 1.0f;
    1.22 +
    1.23 +static std::vector<Curve*> curves;
    1.24 +static Curve *sel_curve, *new_curve;
    1.25 +static int sel_pidx = -1;
    1.26 +
    1.27 +static Label *weight_label;
    1.28 +
    1.29 +
    1.30 +bool app_init(int argc, char **argv)
    1.31 +{
    1.32 +	glEnable(GL_MULTISAMPLE);
    1.33 +	glEnable(GL_CULL_FACE);
    1.34 +	return true;
    1.35 +}
    1.36 +
    1.37 +void app_cleanup()
    1.38 +{
    1.39 +	for(size_t i=0; i<curves.size(); i++) {
    1.40 +		delete curves[i];
    1.41 +	}
    1.42 +	curves.clear();
    1.43 +}
    1.44 +
    1.45 +void app_draw()
    1.46 +{
    1.47 +	glClearColor(0.16, 0.16, 0.16, 1);
    1.48 +	glClear(GL_COLOR_BUFFER_BIT);
    1.49 +
    1.50 +	glMatrixMode(GL_MODELVIEW);
    1.51 +	glLoadIdentity();
    1.52 +	glTranslatef(-view_pan_x, -view_pan_y, 0);
    1.53 +	glScalef(view_scale, view_scale, view_scale);
    1.54 +
    1.55 +	draw_grid(std::max(win_aspect, 1.0f / win_aspect), 0.1);
    1.56 +
    1.57 +	for(size_t i=0; i<curves.size(); i++) {
    1.58 +		draw_curve(curves[i]);
    1.59 +	}
    1.60 +	if(new_curve) {
    1.61 +		// TODO special drawing with more feedback
    1.62 +		draw_curve(new_curve);
    1.63 +	}
    1.64 +	if(weight_label) {
    1.65 +		weight_label->draw();
    1.66 +	}
    1.67 +}
    1.68 +
    1.69 +static void draw_grid(float sz, float sep, float alpha)
    1.70 +{
    1.71 +	float x = 0.0f;
    1.72 +
    1.73 +	glLineWidth(1.0);
    1.74 +	glBegin(GL_LINES);
    1.75 +	glColor4f(0.6, 0.3, 0.2, alpha);
    1.76 +	glVertex2f(-sz, 0);
    1.77 +	glVertex2f(sz, 0);
    1.78 +	glColor4f(0.2, 0.3, 0.6, alpha);
    1.79 +	glVertex2f(0, -sz);
    1.80 +	glVertex2f(0, sz);
    1.81 +	glColor4f(0.4, 0.4, 0.4, alpha);
    1.82 +	while(x < sz) {
    1.83 +		x += sep;
    1.84 +		glVertex2f(-sz, x);
    1.85 +		glVertex2f(sz, x);
    1.86 +		glVertex2f(-sz, -x);
    1.87 +		glVertex2f(sz, -x);
    1.88 +		glVertex2f(x, -sz);
    1.89 +		glVertex2f(x, sz);
    1.90 +		glVertex2f(-x, -sz);
    1.91 +		glVertex2f(-x, sz);
    1.92 +	}
    1.93 +	glEnd();
    1.94 +}
    1.95 +
    1.96 +static void draw_curve(const Curve *curve)
    1.97 +{
    1.98 +	int numpt = curve->get_point_count();
    1.99 +	int segm = numpt * 16.0f;
   1.100 +
   1.101 +	glBegin(GL_LINE_STRIP);
   1.102 +	if(curve == sel_curve) {
   1.103 +		glLineWidth(3.0);
   1.104 +		glColor3f(0.2, 0.8, 0.3);
   1.105 +	} else {
   1.106 +		glLineWidth(2.0);
   1.107 +		glColor3f(0.8, 0.75, 0.3);
   1.108 +	}
   1.109 +	for(int i=0; i<segm; i++) {
   1.110 +		float t = (float)i / (float)(segm - 1);
   1.111 +		Vector2 v = curve->interpolate(t);
   1.112 +		glVertex2f(v.x, v.y);
   1.113 +	}
   1.114 +	glEnd();
   1.115 +	glLineWidth(1.0);
   1.116 +
   1.117 +	glPointSize(5.0);
   1.118 +	glBegin(GL_POINTS);
   1.119 +	glColor3f(1.0, 0.5, 0.2);
   1.120 +	for(int i=0; i<numpt; i++) {
   1.121 +		Vector2 pt = curve->get_point(i);
   1.122 +		glVertex2f(pt.x, pt.y);
   1.123 +	}
   1.124 +	glEnd();
   1.125 +	glPointSize(1.0);
   1.126 +}
   1.127 +
   1.128 +void app_reshape(int x, int y)
   1.129 +{
   1.130 +	win_width = x;
   1.131 +	win_height = y;
   1.132 +	win_aspect = (float)x / (float)y;
   1.133 +
   1.134 +	glViewport(0, 0, x, y);
   1.135 +	glMatrixMode(GL_PROJECTION);
   1.136 +	glLoadIdentity();
   1.137 +	glOrtho(-win_aspect, win_aspect, -1, 1, -1, 1);
   1.138 +}
   1.139 +
   1.140 +void app_keyboard(int key, bool pressed)
   1.141 +{
   1.142 +	if(pressed) {
   1.143 +		switch(key) {
   1.144 +		case 27:
   1.145 +			exit(0);
   1.146 +
   1.147 +		case 'l':
   1.148 +		case 'L':
   1.149 +			if(sel_curve) {
   1.150 +				sel_curve->set_type(CURVE_LINEAR);
   1.151 +				post_redisplay();
   1.152 +			}
   1.153 +			break;
   1.154 +
   1.155 +		case 'b':
   1.156 +		case 'B':
   1.157 +			if(sel_curve) {
   1.158 +				sel_curve->set_type(CURVE_BSPLINE);
   1.159 +				post_redisplay();
   1.160 +			}
   1.161 +			break;
   1.162 +
   1.163 +		case 'h':
   1.164 +		case 'H':
   1.165 +			if(sel_curve) {
   1.166 +				sel_curve->set_type(CURVE_HERMITE);
   1.167 +				post_redisplay();
   1.168 +			}
   1.169 +			break;
   1.170 +		}
   1.171 +	}
   1.172 +}
   1.173 +
   1.174 +static Vector2 pixel_to_uv(int x, int y)
   1.175 +{
   1.176 +	float u = win_aspect * (2.0 * (float)x / (float)win_width - 1.0);
   1.177 +	float v = 1.0 - 2.0 * (float)y / (float)win_height;
   1.178 +	return Vector2(u, v);
   1.179 +}
   1.180 +
   1.181 +static int prev_x, prev_y;
   1.182 +static int click_pos[8][2];
   1.183 +static unsigned int bnstate;
   1.184 +
   1.185 +#define BNBIT(x)	(1 << (x))
   1.186 +
   1.187 +void app_mouse_button(int bn, bool pressed, int x, int y)
   1.188 +{
   1.189 +	prev_x = x;
   1.190 +	prev_y = y;
   1.191 +	if(pressed) {
   1.192 +		bnstate |= BNBIT(bn);
   1.193 +	} else {
   1.194 +		bnstate &= ~BNBIT(bn);
   1.195 +	}
   1.196 +
   1.197 +	if(pressed) {
   1.198 +		click_pos[bn][0] = x;
   1.199 +		click_pos[bn][1] = y;
   1.200 +	} else {
   1.201 +		int dx = x - click_pos[bn][0];
   1.202 +		int dy = y - click_pos[bn][1];
   1.203 +
   1.204 +		if(abs(dx) + abs(dy) < 3) {
   1.205 +			Vector2 uv = pixel_to_uv(x, y);
   1.206 +			on_click(bn, uv.x, uv.y);
   1.207 +		}
   1.208 +
   1.209 +		if(!(bnstate & BNBIT(2))) {
   1.210 +			delete weight_label;
   1.211 +			weight_label = 0;
   1.212 +			post_redisplay();
   1.213 +		}
   1.214 +	}
   1.215 +}
   1.216 +
   1.217 +static void hover(int x, int y)
   1.218 +{
   1.219 +	float thres = pixel_to_uv(5, 0).x - pixel_to_uv(0, 0).x;
   1.220 +
   1.221 +	Vector2 uv = pixel_to_uv(x, y);
   1.222 +	for(size_t i=0; i<curves.size(); i++) {
   1.223 +		int pidx = curves[i]->nearest_point(uv);
   1.224 +		if(pidx == -1) continue;
   1.225 +
   1.226 +		Vector2 cp = curves[i]->get_point(pidx);
   1.227 +		if((cp - uv).length_sq() < thres * thres) {
   1.228 +			sel_curve = curves[i];
   1.229 +			sel_pidx = pidx;
   1.230 +			return;
   1.231 +		}
   1.232 +	}
   1.233 +
   1.234 +	sel_curve = 0;
   1.235 +	sel_pidx = -1;
   1.236 +}
   1.237 +
   1.238 +void app_mouse_motion(int x, int y)
   1.239 +{
   1.240 +	int dx = x - prev_x;
   1.241 +	int dy = y - prev_y;
   1.242 +	prev_x = x;
   1.243 +	prev_y = y;
   1.244 +
   1.245 +	if(!dx && !dy) return;
   1.246 +
   1.247 +	if(!new_curve && !bnstate) {
   1.248 +		hover(x, y);
   1.249 +		post_redisplay();
   1.250 +	}
   1.251 +
   1.252 +	if(sel_curve && sel_pidx != -1) {
   1.253 +		if(bnstate & BNBIT(0)) {
   1.254 +			float w = sel_curve->get_weight(sel_pidx);
   1.255 +			sel_curve->set_point(sel_pidx, pixel_to_uv(x, y), w);
   1.256 +			post_redisplay();
   1.257 +		}
   1.258 +
   1.259 +		if(bnstate & BNBIT(2)) {
   1.260 +			float w = sel_curve->get_weight(sel_pidx);
   1.261 +			w -= dy * 0.1;
   1.262 +			if(w < FLT_MIN) w = FLT_MIN;
   1.263 +			sel_curve->set_weight(sel_pidx, w);
   1.264 +
   1.265 +			if(!weight_label) {
   1.266 +				weight_label = new Label;
   1.267 +			}
   1.268 +			weight_label->set_position(pixel_to_uv(x, y));
   1.269 +			weight_label->set_textf("w=%g", w);
   1.270 +			post_redisplay();
   1.271 +		}
   1.272 +	}
   1.273 +}
   1.274 +
   1.275 +static void on_click(int bn, float u, float v)
   1.276 +{
   1.277 +	switch(bn) {
   1.278 +	case 0:
   1.279 +		if(!new_curve) {
   1.280 +			new_curve = new Curve;
   1.281 +		}
   1.282 +		new_curve->add_point(Vector2(u, v));
   1.283 +		post_redisplay();
   1.284 +		break;
   1.285 +
   1.286 +	case 2:
   1.287 +		curves.push_back(new_curve);
   1.288 +		new_curve = 0;
   1.289 +		post_redisplay();
   1.290 +		break;
   1.291 +
   1.292 +	default:
   1.293 +		break;
   1.294 +	}
   1.295 +}