*.cfg
data/
*.exe
+config.mk
/* gph-cmath - C graphics math library
- * Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+ * Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
*
* This program is free software. Feel free to use, modify, and/or redistribute
* it under the terms of the MIT/X11 license. See LICENSE for details.
#ifndef CGMATH_H_
#define CGMATH_H_
-#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
-#define _USE_MATH_DEFINES
-#endif
-
#include <math.h>
#include <string.h>
-#ifndef M_PI
-#define M_PI 3.141592653589793
-#endif
+#define CGM_PI 3.141592653589793
typedef struct {
float x, y;
} cgm_euler_mode;
#ifdef __cplusplus
+#define CGM_INLINE inline
+
extern "C" {
#else
static CGM_INLINE void cgm_uvec_to_sph(float *theta, float *phi, const cgm_vec3 *v);
static CGM_INLINE void cgm_sph_to_uvec(cgm_vec3 *v, float theta, float phi);
-#ifdef _MSC_VER
-#pragma warning (disable: 4244)
-#endif
-
#include "cgmvec3.inl"
#include "cgmvec4.inl"
#include "cgmquat.inl"
/* gph-cmath - C graphics math library
- * Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+ * Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
*
* This program is free software. Feel free to use, modify, and/or redistribute
* it under the terms of the MIT/X11 license. See LICENSE for details.
static CGM_INLINE void cgm_mget_frustum_plane(const float *m, int p, cgm_vec4 *res)
{
- /*
- int row = p >> 1;
- const float *rowptr = m + row * 4;
-
- if((p & 1) == 0) {
- res->x = m[12] + rowptr[0];
- res->y = m[13] + rowptr[1];
- res->z = m[14] + rowptr[2];
- res->w = m[15] + rowptr[3];
- } else {
- res->x = m[12] - rowptr[0];
- res->y = m[13] - rowptr[1];
- res->z = m[14] - rowptr[2];
- res->w = m[15] - rowptr[3];
- }
- */
switch(p) {
case 0:
res->x = m[3] + m[0];
/* gph-cmath - C graphics math library
- * Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+ * Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
*
* This program is free software. Feel free to use, modify, and/or redistribute
* it under the terms of the MIT/X11 license. See LICENSE for details.
cgm_vec3 npos, res;
float inv_pv[16];
- cgm_mcopy(inv_pv, proj);
- cgm_mmul(inv_pv, view);
+ cgm_mcopy(inv_pv, view);
+ cgm_mmul(inv_pv, proj);
+ cgm_minverse(inv_pv);
npos.x = (winx - vp[0]) / vp[2];
npos.y = (winy - vp[1]) / vp[4];
cgm_vec3 npos, farpt;
float inv_pv[16];
- cgm_mcopy(inv_pv, projmat);
- cgm_mmul(inv_pv, viewmat);
+ cgm_mcopy(inv_pv, viewmat);
+ cgm_mmul(inv_pv, projmat);
+ cgm_minverse(inv_pv);
cgm_vcons(&npos, nx, ny, 0.0f);
cgm_unproject(&ray->origin, &npos, inv_pv);
/* gph-cmath - C graphics math library
- * Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+ * Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
*
* This program is free software. Feel free to use, modify, and/or redistribute
* it under the terms of the MIT/X11 license. See LICENSE for details.
/* gph-cmath - C graphics math library
- * Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+ * Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
*
* This program is free software. Feel free to use, modify, and/or redistribute
* it under the terms of the MIT/X11 license. See LICENSE for details.
/* gph-cmath - C graphics math library
- * Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+ * Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
*
* This program is free software. Feel free to use, modify, and/or redistribute
* it under the terms of the MIT/X11 license. See LICENSE for details.
/* gph-cmath - C graphics math library
- * Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+ * Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
*
* This program is free software. Feel free to use, modify, and/or redistribute
* it under the terms of the MIT/X11 license. See LICENSE for details.
GAW_LIGHT2,
GAW_LIGHT3,
GAW_TEXTURE_1D,
- GAW_TEXTURE_2D
+ GAW_TEXTURE_2D,
+ GAW_POLYGON_OFFSET
};
enum {
};
void gaw_viewport(int x, int y, int w, int h);
+void gaw_get_viewport(int *vp);
void gaw_matrix_mode(int mode);
void gaw_load_identity(void);
glViewport(x, y, w, h);
}
+void gaw_get_viewport(int *vp)
+{
+ glGetIntegerv(GL_VIEWPORT, vp);
+}
+
void gaw_matrix_mode(int mode)
{
mode += GL_MODELVIEW;
case GAW_TEXTURE_2D:
glEnable(GL_TEXTURE_2D);
break;
+ case GAW_POLYGON_OFFSET:
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ break;
default:
break;
}
case GAW_TEXTURE_2D:
glDisable(GL_TEXTURE_2D);
break;
+ case GAW_POLYGON_OFFSET:
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ break;
default:
break;
}
glAlphaFunc(func + GL_NEVER, ref);
}
+void gaw_zoffset(float offs)
+{
+ glPolygonOffset(1, offs);
+}
+
void gaw_clear_color(float r, float g, float b, float a)
{
glClearColor(r, g, b, a);
st.vport[3] = h;
}
+void gaw_get_viewport(int *vp)
+{
+ memcpy(vp, st.vport, sizeof st.vport);
+}
+
void gaw_matrix_mode(int mode)
{
st.mmode = mode;
void gaw_zoffset(float offs)
{
- st.zoffs = offs;
+ st.zoffs = offs * 0.1;
}
#define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
float oow = 1.0f / v[i].w;
v[i].x *= oow;
v[i].y *= oow;
- v[i].z += st.zoffs;
+ if(st.opt & (1 << GAW_POLYGON_OFFSET)) {
+ v[i].z += st.zoffs;
+ }
if(st.opt & (1 << GAW_DEPTH_TEST)) {
v[i].z *= oow;
}
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#include "rt.h"
+
+
+int ray_object(const cgm_ray *ray, const struct object *obj, struct csghit *hit)
+{
+ int i, res;
+ cgm_ray localray = *ray;
+
+ cgm_rmul_mr(&localray, obj->inv_xform);
+
+ switch(obj->type) {
+ case OBJ_SPHERE:
+ res = ray_sphere(ray, (const struct sphere*)obj, hit);
+ break;
+
+ default:
+ res = 0;
+ }
+
+ if(res && hit) {
+ for(i=0; i<hit->ivcount; i++) {
+ cgm_vmul_m4v3(&hit->ivlist[i].a.pos, obj->xform);
+ cgm_vmul_m3v3(&hit->ivlist[i].a.norm, obj->xform);
+ cgm_vmul_m4v3(&hit->ivlist[i].b.pos, obj->xform);
+ cgm_vmul_m3v3(&hit->ivlist[i].b.norm, obj->xform);
+ }
+ }
+ return res;
+}
+
+int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit)
+{
+ int i;
+ float a, b, c, d, sqrt_d, t1, t2, invrad;
+ struct rayhit *rhptr;
+
+ a = cgm_vdot(&ray->dir, &ray->dir);
+ b = 2.0f * ray->dir.x * (ray->origin.x - sph->pos.x) +
+ 2.0f * ray->dir.y * (ray->origin.y - sph->pos.y) +
+ 2.0f * ray->dir.z * (ray->origin.z - sph->pos.z);
+ c = cgm_vdot(&sph->pos, &sph->pos) + cgm_vdot(&ray->origin, &ray->origin) +
+ cgm_vdot(&sph->pos, &ray->origin) * -2.0f - sph->rad * sph->rad;
+
+ if((d = b * b - 4.0 * a * c) < 0.0) return 0;
+
+ sqrt_d = sqrt(d);
+ t1 = (-b + sqrt_d) / (2.0 * a);
+ t2 = (-b - sqrt_d) / (2.0 * a);
+
+ if((t1 < 1e-6f && t2 < 1e-6f) || (t1 > 1.0f && t2 > 1.0f)) {
+ return 0;
+ }
+
+ if(hit) {
+ if(t1 < 1e-6f || t1 > 1.0f) {
+ t1 = t2;
+ } else if(t2 < 1e-6f || t2 > 1.0f) {
+ t2 = t1;
+ }
+ if(t2 < t1) {
+ float tmp = t1;
+ t1 = t2;
+ t2 = tmp;
+ }
+
+ hit->ivcount = 1;
+ hit->ivlist[0].a.t = t1;
+ hit->ivlist[0].b.t = t2;
+ invrad = 1.0f / sph->rad;
+
+ rhptr = &hit->ivlist[0].a;
+ for(i=0; i<2; i++) {
+ cgm_raypos(&rhptr->pos, ray, rhptr->t);
+ rhptr->norm.x = rhptr->pos.x * invrad;
+ rhptr->norm.y = rhptr->pos.y * invrad;
+ rhptr->norm.z = rhptr->pos.z * invrad;
+ rhptr->uv.x = (atan2(rhptr->norm.z, rhptr->norm.x) + CGM_PI) / (2.0 * CGM_PI);
+ rhptr->uv.y = acos(rhptr->norm.y) / CGM_PI;
+ rhptr->obj = (struct object*)sph;
+ rhptr = &hit->ivlist[0].b;
+ }
+ }
+ return 1;
+}
+
+int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit)
+{
+ return 0;
+}
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef RT_H_
+#define RT_H_
+
+#include "cgmath/cgmath.h"
+#include "scene.h"
+
+struct rayhit {
+ float t;
+ cgm_vec3 pos;
+ cgm_vec3 norm;
+ cgm_vec2 uv;
+ struct object *obj;
+};
+
+struct interval {
+ struct rayhit a, b;
+};
+
+#define MAX_INTERV 32
+struct csghit {
+ struct interval ivlist[MAX_INTERV];
+ int ivcount;
+};
+
+int ray_object(const cgm_ray *ray, const struct object *obj, struct csghit *hit);
+int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit);
+int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit);
+
+#endif /* RT_H_ */
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
+#include <float.h>
#include "scene.h"
+#include "rt.h"
#include "darray.h"
#include "logger.h"
return 0;
}
-int scn_num_objects(struct scene *scn)
+int scn_rm_object(struct scene *scn, int idx)
+{
+ int numobj = darr_size(scn->objects);
+
+ if(idx < 0 || idx >= numobj) {
+ return -1;
+ }
+
+ free_object(scn->objects[idx]);
+
+ if(idx < numobj - 1) {
+ scn->objects[idx] = scn->objects[numobj - 1];
+ }
+ darr_pop(scn->objects);
+ return 0;
+}
+
+int scn_num_objects(const struct scene *scn)
{
return darr_size(scn->objects);
}
+int scn_object_index(const struct scene *scn, const struct object *obj)
+{
+ int i, num = darr_size(scn->objects);
+ for(i=0; i<num; i++) {
+ if(scn->objects[i] == obj) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int scn_intersect(const struct scene *scn, const cgm_ray *ray, struct rayhit *hit)
+{
+ int i, numobj;
+ struct rayhit hit0;
+ struct csghit chit;
+
+ hit0.t = FLT_MAX;
+ hit0.obj = 0;
+
+ numobj = darr_size(scn->objects);
+ for(i=0; i<numobj; i++) {
+ if(ray_object(ray, scn->objects[i], &chit) && chit.ivlist[0].a.t < hit0.t) {
+ hit0 = chit.ivlist[0].a;
+ }
+ }
+
+ if(hit0.obj) {
+ if(hit) *hit = hit0;
+ return 1;
+ }
+ return 0;
+}
+
struct object *create_object(int type)
{
struct object *obj;
char buf[32];
static int objid;
- if(!(obj = malloc(sizeof *obj))) {
+ if(!(obj = calloc(1, sizeof *obj))) {
errormsg("failed to allocate object\n");
return 0;
}
cgm_vcons(&obj->scale, 1, 1, 1);
cgm_vcons(&obj->pivot, 0, 0, 0);
cgm_midentity(obj->xform);
+ cgm_midentity(obj->inv_xform);
switch(type) {
case OBJ_SPHERE:
mat[2] *= obj->scale.x; mat[6] *= obj->scale.y; mat[10] *= obj->scale.z; mat[14] += obj->pos.z;
cgm_mpretranslate(mat, -obj->pivot.x, -obj->pivot.y, -obj->pivot.z);
-
/* that's basically: pivot * rotation * translation * scaling * -pivot */
+
+ cgm_mcopy(obj->inv_xform, mat);
+ cgm_minverse(obj->inv_xform);
}
enum {
OBJ_NULL,
- OBJ_SPHERE
+ OBJ_SPHERE,
+ OBJ_CSG
};
#define OBJ_COMMON_ATTR \
char *name; \
cgm_vec3 pos, scale, pivot; \
cgm_quat rot; \
- float xform[16]
+ float xform[16], inv_xform[16]
struct object {
OBJ_COMMON_ATTR;
float rad;
};
+struct csgnode {
+ OBJ_COMMON_ATTR;
+ int op;
+ struct object *subobj; /* darr */
+};
+
struct scene {
struct object **objects; /* darr */
};
+struct rayhit; /* declared in rt.h */
+
struct scene *create_scene(void);
void free_scene(struct scene *scn);
int scn_add_object(struct scene *scn, struct object *obj);
-int scn_num_objects(struct scene *scn);
+int scn_rm_object(struct scene *scn, int idx);
+int scn_num_objects(const struct scene *scn);
+int scn_object_index(const struct scene *scn, const struct object *obj);
+
+int scn_intersect(const struct scene *scn, const cgm_ray *ray, struct rayhit *hit);
struct object *create_object(int type);
void free_object(struct object *obj);
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <assert.h>
#include "gaw/gaw.h"
#include "app.h"
#include "rtk.h"
#include "scene.h"
+#include "rt.h"
#include "cmesh.h"
#include "meshgen.h"
TBN_NEW, TBN_OPEN, TBN_SAVE, TBN_SEP1,
TBN_SEL, TBN_MOVE, TBN_ROT, TBN_SCALE, TBN_SEP2,
TBN_ADD, TBN_RM, TBN_SEP3,
- TBN_MTL, TBN_REND, TBN_VIEWREND, TBN_SEP4, TBN_CFG,
+ TBN_UNION, TBN_ISECT, TBN_DIFF, TBN_SEP4,
+ TBN_MTL, TBN_REND, TBN_VIEWREND, TBN_SEP5, TBN_CFG,
NUM_TOOL_BUTTONS
};
"new", "open", "save", 0,
"sel", "move", "rot", "scale", 0,
"add", "remove", 0,
+ "union", "isect", "diff", 0,
"mtl", "rend", "viewrend", 0, "cfg"
};
static int tbn_icon_pos[][2] = {
{0,0}, {16,0}, {32,0}, {-1,-1},
{48,0}, {64,0}, {80,0}, {96,0}, {-1,-1},
{112,0}, {112,16}, {-1,-1},
+ {0,16}, {16,16}, {32,16}, {-1,-1},
{48,16}, {64,16}, {80,16}, {-1,-1}, {96,16}
};
+static int tbn_istool[] = {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0,
+ 1, 1, 1, 0,
+ 0, 0, 0, 0, 0
+};
static rtk_icon *tbn_icons[NUM_TOOL_BUTTONS];
static rtk_widget *tbn_buttons[NUM_TOOL_BUTTONS];
#define TOOLBAR_HEIGHT 26
-enum {TOOL_SEL, TOOL_MOVE, TOOL_ROT, TOOL_SCALE, NUM_TOOLS};
+enum {
+ TOOL_SEL, TOOL_MOVE, TOOL_ROT, TOOL_SCALE,
+ TOOL_UNION, TOOL_ISECT, TOOL_DIFF,
+ NUM_TOOLS
+};
+static rtk_widget *tools[NUM_TOOLS];
static int mdl_init(void);
static void mdl_mouse(int bn, int press, int x, int y);
static void mdl_motion(int x, int y);
+static void draw_object(struct object *obj);
static void draw_grid(void);
static void tbn_callback(rtk_widget *w, void *cls);
+static void draw_rband(void);
+static void primray(cgm_ray *ray, int x, int y);
+
+
struct app_screen scr_model = {
"modeller",
mdl_init, mdl_destroy,
static struct cmesh *mesh_sph;
static float cam_theta, cam_phi = 20, cam_dist = 8;
+static float view_matrix[16], proj_matrix[16];
+static float view_matrix_inv[16], proj_matrix_inv[16];
+static int viewport[4];
+static cgm_ray pickray;
-static int tool;
+static int cur_tool;
static int selobj = -1;
+static rtk_rect rband;
+static int rband_valid;
static int mdl_init(void)
{
- int i;
+ int i, toolidx;
rtk_widget *w;
if(!(icons = rtk_load_iconsheet("data/icons.png"))) {
}
rtk_win_layout(toolbar, RTK_HBOX);
+ toolidx = 0;
for(i=0; i<NUM_TOOL_BUTTONS; i++) {
if(!tbn_icons[i]) {
rtk_create_separator(toolbar);
return -1;
}
tbn_buttons[i] = w;
- rtk_set_callback(w, tbn_callback, (void*)i);
- if(i >= TBN_SEL && i <= TBN_SCALE) {
+ rtk_set_callback(w, tbn_callback, (void*)(intptr_t)i);
+ if(tbn_istool[i]) {
rtk_bn_mode(w, RTK_TOGGLEBN);
+ tools[toolidx++] = w;
}
if(i == TBN_SEL) {
rtk_set_value(w, 1);
}
}
}
+ assert(toolidx == NUM_TOOLS);
if(!(mesh_sph = cmesh_alloc())) {
errormsg("failed to allocate sphere vis mesh\n");
rtk_draw_widget(toolbar);
- gaw_viewport(0, TOOLBAR_HEIGHT, win_width, win_height - TOOLBAR_HEIGHT);
-
gaw_matrix_mode(GAW_MODELVIEW);
gaw_load_identity();
gaw_translate(0, 0, -cam_dist);
gaw_rotate(cam_phi, 1, 0, 0);
gaw_rotate(cam_theta, 0, 1, 0);
+ gaw_get_modelview(view_matrix);
+ cgm_mcopy(view_matrix_inv, view_matrix);
+ cgm_minverse(view_matrix_inv);
draw_grid();
+ gaw_mtl_diffuse(0.5, 0.5, 0.5, 1);
+
num = scn_num_objects(scn);
for(i=0; i<num; i++) {
- struct object *obj = scn->objects[i];
- struct sphere *sph;
-
- calc_object_matrix(obj);
- gaw_push_matrix();
- gaw_mult_matrix(obj->xform);
-
- switch(obj->type) {
- case OBJ_SPHERE:
- sph = (struct sphere*)obj;
- gaw_scale(sph->rad, sph->rad, sph->rad);
- gaw_zoffset(0.1);
- cmesh_draw(mesh_sph);
- gaw_zoffset(0);
+ if(i == selobj) {
+ gaw_zoffset(1);
+ gaw_enable(GAW_POLYGON_OFFSET);
+ draw_object(scn->objects[i]);
+ gaw_disable(GAW_POLYGON_OFFSET);
gaw_save();
gaw_disable(GAW_LIGHTING);
gaw_poly_wire();
gaw_color3f(0, 1, 0);
- cmesh_draw(mesh_sph);
+ draw_object(scn->objects[i]);
gaw_poly_gouraud();
gaw_restore();
- break;
-
- default:
- break;
+ } else {
+ draw_object(scn->objects[i]);
}
+ }
+
+ if(rband_valid) {
+ draw_rband();
+ }
+}
- gaw_pop_matrix();
+static void draw_object(struct object *obj)
+{
+ struct sphere *sph;
+
+ calc_object_matrix(obj);
+ gaw_push_matrix();
+ gaw_mult_matrix(obj->xform);
+
+ switch(obj->type) {
+ case OBJ_SPHERE:
+ sph = (struct sphere*)obj;
+ gaw_scale(sph->rad, sph->rad, sph->rad);
+ cmesh_draw(mesh_sph);
+ break;
+
+ default:
+ break;
}
- gaw_viewport(0, 0, win_width, win_height);
+ gaw_pop_matrix();
}
static void draw_grid(void)
{
float aspect = (float)x / (float)(y - TOOLBAR_HEIGHT);
+ viewport[0] = 0;
+ viewport[1] = TOOLBAR_HEIGHT;
+ viewport[2] = x;
+ viewport[3] = y - TOOLBAR_HEIGHT;
+ gaw_viewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+
gaw_matrix_mode(GAW_PROJECTION);
gaw_load_identity();
gaw_perspective(50, aspect, 0.5, 100.0);
+ gaw_get_projection(proj_matrix);
+ cgm_mcopy(proj_matrix_inv, proj_matrix);
+ cgm_minverse(proj_matrix_inv);
rtk_resize(toolbar, win_width, TOOLBAR_HEIGHT);
}
static void mdl_mouse(int bn, int press, int x, int y)
{
+ struct rayhit hit;
if(!vpdrag && rtk_input_mbutton(toolbar, bn, press, x, y)) {
app_redisplay();
return;
}
if(press) {
+ rband.x = x;
+ rband.y = y;
vpdrag |= (1 << bn);
} else {
vpdrag &= ~(1 << bn);
+
+ if(rband_valid) {
+ printf("rubber band: %d,%d %dx%d\n", rband.x, rband.y, rband.width, rband.height);
+ rband_valid = 0;
+
+ } else if(bn == 0 && x == rband.x && y == rband.y) {
+ primray(&pickray, x, y);
+ if(scn_intersect(scn, &pickray, &hit)) {
+ selobj = scn_object_index(scn, hit.obj);
+ } else {
+ selobj = -1;
+ }
+ }
+ app_redisplay();
}
}
dx = x - mouse_x;
dy = y - mouse_y;
- if((dx | dy) == 0) return;
-
- if(mouse_state[0]) {
- cam_theta += dx * 0.5f;
- cam_phi += dy * 0.5f;
- if(cam_phi < -90) cam_phi = -90;
- if(cam_phi > 90) cam_phi = 90;
- app_redisplay();
- }
+ if(modkeys) {
+ /* navigation */
+ if(mouse_state[0]) {
+ cam_theta += dx * 0.5f;
+ cam_phi += dy * 0.5f;
+ if(cam_phi < -90) cam_phi = -90;
+ if(cam_phi > 90) cam_phi = 90;
+ app_redisplay();
+ }
- if(mouse_state[2]) {
- cam_dist += dy * 0.1f;
- if(cam_dist < 0) cam_dist = 0;
+ if(mouse_state[2]) {
+ cam_dist += dy * 0.1f;
+ if(cam_dist < 0) cam_dist = 0;
+ app_redisplay();
+ }
+ } else {
+ if(mouse_state[0]) {
+ if(rband.x != x || rband.y != y) {
+ rband.width = x - rband.x;
+ rband.height = y - rband.y;
+ rband_valid = 1;
+ }
+ }
app_redisplay();
}
}
case TBN_MOVE:
case TBN_ROT:
case TBN_SCALE:
- tool = id - TBN_SEL;
+ idx = id - TBN_SEL;
+ if(0) {
+ case TBN_UNION:
+ case TBN_ISECT:
+ case TBN_DIFF:
+ idx = id - TBN_UNION + TOOL_UNION;
+ }
+ cur_tool = idx;
for(i=0; i<NUM_TOOLS; i++) {
- if(i != tool) {
- rtk_set_value(tbn_buttons[i + TBN_SEL], 0);
+ if(i != cur_tool) {
+ rtk_set_value(tools[i], 0);
}
}
break;
selobj = idx;
break;
+ case TBN_RM:
+ if(selobj >= 0) {
+ scn_rm_object(scn, selobj);
+ selobj = -1;
+ app_redisplay();
+ }
+ break;
+
default:
break;
}
}
+
+static void draw_rband(void)
+{
+ int i, x, y, w, h;
+ uint32_t *fbptr, *bptr;
+
+ x = rband.x;
+ y = rband.y;
+
+ if(rband.width < 0) {
+ w = -rband.width;
+ x += rband.width;
+ } else {
+ w = rband.width;
+ }
+ if(rband.height < 0) {
+ h = -rband.height;
+ y += rband.height;
+ } else {
+ h = rband.height;
+ }
+
+ fbptr = framebuf + y * win_width + x;
+ bptr = fbptr + win_width * (h - 1);
+
+ for(i=0; i<w; i++) {
+ fbptr[i] ^= 0xffffff;
+ bptr[i] ^= 0xffffff;
+ }
+ fbptr += win_width;
+ for(i=0; i<h-2; i++) {
+ fbptr[0] ^= 0xffffff;
+ fbptr[w - 1] ^= 0xffffff;
+ fbptr += win_width;
+ }
+}
+
+static void primray(cgm_ray *ray, int x, int y)
+{
+ float nx, ny;
+ cgm_vec3 npos, farpt;
+ float inv_pv[16];
+
+ y = win_height - y;
+ nx = (float)(x - viewport[0]) / (float)viewport[2];
+ ny = (float)(y - viewport[1]) / (float)viewport[3];
+
+ cgm_mcopy(inv_pv, proj_matrix_inv);
+ cgm_mmul(inv_pv, view_matrix_inv);
+
+ cgm_vcons(&npos, nx, ny, 0.0f);
+ cgm_unproject(&ray->origin, &npos, inv_pv);
+ npos.z = 1.0f;
+ cgm_unproject(&farpt, &npos, inv_pv);
+
+ ray->dir.x = farpt.x - ray->origin.x;
+ ray->dir.y = farpt.y - ray->origin.y;
+ ray->dir.z = farpt.z - ray->origin.z;
+}