# HG changeset patch # User John Tsiombikas # Date 1379821088 -10800 # Node ID 11d14f688485979091f59aa5931d0b55fe89ab62 # Parent dcfe615c4c5f8eba0e894633345bb87291960da3 added clipping diff -r dcfe615c4c5f -r 11d14f688485 Makefile --- a/Makefile Sun Sep 22 02:47:46 2013 +0300 +++ b/Makefile Sun Sep 22 06:38:08 2013 +0300 @@ -1,5 +1,5 @@ obj = src/main.o \ - src/mingl.o src/mglrast.o src/mglgen.o \ + src/mingl.o src/mglrast.o src/mglclip.o src/mglgen.o \ src/texture.o src/palman.o \ src/scene.o src/cvec.o src/fixedp.o \ dosemu/dosemu.o @@ -7,8 +7,7 @@ bin = deepstone CC = gcc -CFLAGS = -pedantic -Wall -g `pkg-config --cflags sdl` -Isrc -Idosemu -#-DRAST_FLOAT -DDBG_USE_FLOAT +CFLAGS = -pedantic -Wall -g `pkg-config --cflags sdl` -Isrc -Idosemu -DRAST_FLOAT -DDBG_USE_FLOAT LDFLAGS = `pkg-config --libs sdl` -lm $(bin): $(obj) diff -r dcfe615c4c5f -r 11d14f688485 dosemu/dosemu.c --- a/dosemu/dosemu.c Sun Sep 22 02:47:46 2013 +0300 +++ b/dosemu/dosemu.c Sun Sep 22 06:38:08 2013 +0300 @@ -14,19 +14,27 @@ /* ----- graphics (wvga.c implementation) ----- */ static SDL_Surface *fbsurf; - -#define DOUBLESZ (fbsurf->w != 320) +static int scale = 1; int set_video_mode(int mode) { int resx = 320, resy = 200; unsigned int sdl_flags = SDL_HWPALETTE; + char *env; if(getenv("DOSEMU_DOUBLESIZE")) { - resx *= 2; - resy *= 2; + scale = 2; } + if((env = getenv("DOSEMU_SCALE"))) { + int n = atoi(env); + if(n > 0) { + scale = n; + } + } + resx *= scale; + resy *= scale; + if(getenv("DOSEMU_FULLSCREEN")) { sdl_flags |= SDL_FULLSCREEN; } @@ -39,7 +47,7 @@ abort(); } SDL_WM_SetCaption("Deepstone", 0); - SDL_ShowCursor(0); + /*SDL_ShowCursor(0);*/ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); break; @@ -86,17 +94,17 @@ SDL_LockSurface(fbsurf); } - if(DOUBLESZ) { - int i, j; - Uint16 *dest = fbsurf->pixels; + if(scale > 1) { + int i, j, xsz, ysz; + unsigned char *dest = fbsurf->pixels; - for(i=0; i<200; i++) { - for(j=0; j<320; j++) { - Uint16 twopix = ((Uint16)*frame << 8) | (Uint16)*frame; - dest[j] = dest[j + 320] = twopix; - frame++; + xsz = 320 * scale; + ysz = 200 * scale; + + for(i=0; ipitch; } } else { memcpy(fbsurf->pixels, frame, 64000); @@ -163,13 +171,8 @@ return; case SDL_MOUSEMOTION: - mousex = ev.motion.x; - mousey = ev.motion.y; - - if(DOUBLESZ) { - mousex /= 2; - mousey /= 2; - } + mousex = ev.motion.x / scale; + mousey = ev.motion.y / scale; break; case SDL_MOUSEBUTTONDOWN: diff -r dcfe615c4c5f -r 11d14f688485 src/main.c --- a/src/main.c Sun Sep 22 02:47:46 2013 +0300 +++ b/src/main.c Sun Sep 22 06:38:08 2013 +0300 @@ -51,6 +51,12 @@ static int init(void) { + float vfov, hfov, aspect; + + aspect = 320.0 / 200.0; + vfov = 60.0; + hfov = vfov * aspect; + init_timer(100); set_video_mode(0x13); @@ -74,7 +80,18 @@ mgl_matrix_mode(MGL_PROJECTION); mgl_load_identity(); - mgl_perspective(45.0, 320.0 / 200.0, 0.5, 200.0); + mgl_perspective(vfov, aspect, 0.5, 200.0); + +#if 0 + mgl_enable(MGL_CLIP_PLANE0); + mgl_enable(MGL_CLIP_PLANE1); + mgl_enable(MGL_CLIP_PLANE2); + mgl_enable(MGL_CLIP_PLANE3); + mgl_clip_plane(MGL_CLIP_PLANE0, -1, 0, -1, 0); /* positive X */ + mgl_clip_plane(MGL_CLIP_PLANE1, 1, 0, -1, 0); /* negative X */ + mgl_clip_plane(MGL_CLIP_PLANE2, 0, -1, -0.5, 0); /* positive Y */ + mgl_clip_plane(MGL_CLIP_PLANE3, 0, 1, -0.5, 0); /* negative Y */ +#endif /* setup palette */ palm_add_color(255, 255, 255); diff -r dcfe615c4c5f -r 11d14f688485 src/mglclip.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mglclip.c Sun Sep 22 06:38:08 2013 +0300 @@ -0,0 +1,189 @@ +#include +#include +#include +#include "mingl.h" +#include "mglimpl.h" + +static struct state *st; + +static float distance_signed(vec3_t p, const struct plane *plane); +static int intersect(const ray3_t *ray, const struct plane *plane, float *t); +static int clip_polygon(struct vertex *vout, int *voutnum, const struct vertex *vin, int vnum, + const struct plane *plane); + +#define ZNEAR MAX_CLIP_PLANES + +int mgl_clip_init(struct state *state) +{ + st = state; + + memset(st->clip_planes, 0, sizeof st->clip_planes); + + /* always setup a near clipping plane */ + st->clip_planes[ZNEAR].normal.x = st->clip_planes[ZNEAR].normal.y = 0; + st->clip_planes[ZNEAR].normal.z = -1; + st->clip_planes[ZNEAR].pt.x = st->clip_planes[ZNEAR].pt.y = 0; + st->clip_planes[ZNEAR].pt.z = -0.5; + + return 0; +} + +int mgl_clip_poly(struct vertex *v, int vnum) +{ + int i, res, clipped_vnum; + struct vertex tmp[6]; + + for(i=0; iclip_planes + i); + if(res == -1) { + /* the polygon was completely outside */ + return 0; + } + if(res == 0) { + /* the polygon was clipped, update v and vnum */ + vnum = clipped_vnum; + memcpy(v, tmp, clipped_vnum * sizeof *v); + } + /* otherwise the polygon was completely inside, nothing to do... */ + } + + return vnum; +} + +static float distance_signed(vec3_t p, const struct plane *plane) +{ + vec3_t ptdir; + ptdir.x = p.x - plane->pt.x; + ptdir.y = p.y - plane->pt.y; + ptdir.z = p.z - plane->pt.z; + + return vec3_dot(ptdir, plane->normal); +} + +static int intersect(const ray3_t *ray, const struct plane *plane, float *t) +{ + vec3_t orig_pt_dir; + + float ndotdir = vec3_dot(plane->normal, ray->dir); + if(fabs(ndotdir) < 1e-4) { + *t = 0.0f; + return 0; + } + + orig_pt_dir.x = plane->pt.x - ray->origin.x; + orig_pt_dir.y = plane->pt.y - ray->origin.y; + orig_pt_dir.z = plane->pt.z - ray->origin.z; + + *t = vec3_dot(plane->normal, orig_pt_dir) / ndotdir; + return 1; +} + +static int clip_edge(struct vertex *poly, int *vnum, const struct vertex *v0, + const struct vertex *v1, const struct plane *plane); + +/* returns: + * 1 -> both inside + * 0 -> straddling and clipped + * -1 -> both outside + * + * the size of the vout polygon is returned throug voutnum + */ +static int clip_polygon(struct vertex *vout, int *voutnum, const struct vertex *vin, int vnum, + const struct plane *plane) +{ + int i; + int edges_clipped = 0; + int out_vnum = 0; + + for(i=0; i 0 ? 0 : 1; +} + +/* returns: + * 1 -> both inside + * 0 -> straddling and clipped + * -1 -> both outside + * + * also returns the size of the polygon through vnumptr + */ +static int clip_edge(struct vertex *poly, int *vnumptr, const struct vertex *v0, + const struct vertex *v1, const struct plane *plane) +{ + vec3_t pos0, pos1; + float d0, d1, t; + ray3_t ray; + int vnum = *vnumptr; + + pos0.x = v0->pos.x; pos0.y = v0->pos.y; pos0.z = v0->pos.z; + pos1.x = v1->pos.x; pos1.y = v1->pos.y; pos1.z = v1->pos.z; + + d0 = distance_signed(pos0, plane); + d1 = distance_signed(pos1, plane); + + ray.origin = pos0; + ray.dir.x = pos1.x - pos0.x; + ray.dir.y = pos1.y - pos0.y; + ray.dir.z = pos1.z - pos0.z; + + if(d0 >= 0.0) { + /* start inside */ + if(d1 >= 0.0) { + /* all inside */ + poly[vnum++] = *v1; /* append v1 */ + *vnumptr = vnum; + return 1; + } else { + /* going out */ + intersect(&ray, plane, &t); + + ray3_point(poly[vnum].pos, ray, t); + poly[vnum].pos.w = 1.0; + + vec3_lerp(poly[vnum].norm, v0->norm, v1->norm, t); + vec2_lerp(poly[vnum].tc, v0->tc, v1->tc, t); + poly[vnum].energy = v0->energy + (v1->energy - v0->energy) * t; + poly[vnum].cidx = v0->cidx; + vnum++; /* append new vertex on the intersection point */ + } + } else { + /* start outside */ + if(d1 >= 0) { + /* going in */ + intersect(&ray, plane, &t); + + ray3_point(poly[vnum].pos, ray, t); + poly[vnum].pos.w = 1.0; + + vec3_lerp(poly[vnum].norm, v0->norm, v1->norm, t); + vec2_lerp(poly[vnum].tc, v0->tc, v1->tc, t); + poly[vnum].energy = v0->energy + (v1->energy - v0->energy) * t; + poly[vnum].cidx = v0->cidx; + vnum++; /* append new vertex on the intersection point */ + + /* then append v1 ... */ + poly[vnum++] = *v1; + } else { + /* all outside */ + return -1; + } + } + + *vnumptr = vnum; + return 0; +} diff -r dcfe615c4c5f -r 11d14f688485 src/mglimpl.h --- a/src/mglimpl.h Sun Sep 22 02:47:46 2013 +0300 +++ b/src/mglimpl.h Sun Sep 22 06:38:08 2013 +0300 @@ -5,6 +5,7 @@ #define MATRIX_STACK_SIZE 8 #define MAX_LIGHTS 4 +#define MAX_CLIP_PLANES 6 #define ZTILE_SIZE 16384 #define ZTILE_SHIFT 14 @@ -34,6 +35,11 @@ int cidx; }; +struct plane { + vec3_t pt; + vec3_t normal; +}; + struct texture { int width, height; int xshift, yshift; @@ -47,12 +53,15 @@ int mmode, mtop[2]; mat4_t matrix[2][MATRIX_STACK_SIZE]; int prim; - struct vertex curv, v[4]; + struct vertex curv, v[6]; int vidx; int vp[4]; /* viewport */ int col_range; /* color interpolation range */ vec4_t lpos[MAX_LIGHTS]; float lint[MAX_LIGHTS]; + float ambient; + + struct plane clip_planes[MAX_CLIP_PLANES + 1]; struct texture tex; }; @@ -64,6 +73,7 @@ int num_ztiles; }; +#define IS_ENABLED(f, x) ((f) & (1 << (x))) #define vertex_to_fixedvertex(v, vx) \ do { \ @@ -91,4 +101,7 @@ void mgl_draw_line(struct vertex *v0, struct vertex *v1); void mgl_draw_poly(struct vertex *v, int numv); +int mgl_clip_init(struct state *state); +int mgl_clip_poly(struct vertex *v, int vnum); + #endif /* MGL_IMPL_H_ */ diff -r dcfe615c4c5f -r 11d14f688485 src/mglrast.c --- a/src/mglrast.c Sun Sep 22 02:47:46 2013 +0300 +++ b/src/mglrast.c Sun Sep 22 06:38:08 2013 +0300 @@ -146,13 +146,13 @@ }; int bits = 0; - if((st->flags & MGL_TEXTURE_2D) && st->tex.pixels) { + if(IS_ENABLED(st->flags, MGL_TEXTURE_2D) && st->tex.pixels) { bits |= 4; } - if(st->flags & MGL_SMOOTH) { + if(IS_ENABLED(st->flags, MGL_SMOOTH)) { bits |= 2; } - if((st->flags & MGL_DEPTH_TEST) && fb->zbuf) { + if(IS_ENABLED(st->flags, MGL_DEPTH_TEST) && fb->zbuf) { bits |= 1; } diff -r dcfe615c4c5f -r 11d14f688485 src/mingl.c --- a/src/mingl.c Sun Sep 22 02:47:46 2013 +0300 +++ b/src/mingl.c Sun Sep 22 06:38:08 2013 +0300 @@ -24,7 +24,8 @@ static void transform(vec4_t *res, vec4_t *v, float *mat); static void transform3(vec3_t *res, vec3_t *v, float *mat); -static void vertex_proc(struct vertex *vert); +static void vertex_proc_view(struct vertex *vert); +static int vertex_proc_proj(struct vertex *vert); static int calc_shiftmask(int val, int *shiftp, unsigned int *maskp); static struct state st; @@ -75,6 +76,9 @@ st.lint[i] = 0.0f; } + st.ambient = 0.1; + + mgl_clip_init(&st); return 0; } @@ -133,19 +137,19 @@ } } -void mgl_enable(unsigned int bit) +void mgl_enable(unsigned int what) { - st.flags |= bit; + st.flags |= (1 << what); } -void mgl_disable(unsigned int bit) +void mgl_disable(unsigned int what) { - st.flags &= ~bit; + st.flags &= ~(1 << what); } -int mgl_isenabled(unsigned int bit) +int mgl_isenabled(unsigned int what) { - return (st.flags & bit) != 0; + return IS_ENABLED(st.flags, what); } void mgl_front_face(int ff) @@ -158,6 +162,16 @@ st.cullface = cf; } +void mgl_set_ambient(float amb) +{ + st.ambient = amb; +} + +float mgl_get_ambient(void) +{ + return st.ambient; +} + void mgl_color_range(int rng) { st.col_range = rng; @@ -228,25 +242,43 @@ st.v[st.vidx].norm = st.curv.norm; st.v[st.vidx].tc = st.curv.tc; - vertex_proc(st.v + st.vidx); + /* T&L up to view space, to perform user-clipping */ + vertex_proc_view(st.v + st.vidx); if(++st.vidx >= st.prim) { + st.vidx = 0; + switch(st.prim) { case MGL_POINTS: + vertex_proc_proj(st.v); mgl_draw_point(st.v); break; case MGL_LINES: + vertex_proc_proj(st.v); + vertex_proc_proj(st.v + 1); mgl_draw_line(st.v, st.v + 1); break; case MGL_TRIANGLES: case MGL_QUADS: - mgl_draw_poly(st.v, st.prim); + { + int nverts = mgl_clip_poly(st.v, st.prim); + if(nverts > 0) { + int i; + /* passed clipping, perform projection for all verts and draw */ + for(i=0; iz = mat[2] * v->x + mat[6] * v->y + mat[10] * v->z; } -static void vertex_proc(struct vertex *vert) +static void vertex_proc_view(struct vertex *vert) { - vec4_t pview, pclip; + vec4_t pview; float *mvmat = st.matrix[MGL_MODELVIEW][st.mtop[MGL_MODELVIEW]]; - float *pmat = st.matrix[MGL_PROJECTION][st.mtop[MGL_PROJECTION]]; /* modelview transformation */ transform(&pview, &vert->pos, mvmat); - if(st.flags & MGL_LIGHTING) { - if((st.flags & MGL_SMOOTH) || st.vidx == 0) { + if(mgl_isenabled(MGL_LIGHTING)) { + if(mgl_isenabled(MGL_SMOOTH) || st.vidx == 0) { int i; vec3_t norm; - float irrad = 0.0f; + float irrad = st.ambient; transform3(&norm, &vert->norm, mvmat); @@ -331,18 +362,27 @@ irrad += ndotl * st.lint[i]; } } - vert->energy = irrad; + vert->energy = irrad > 1.0 ? 1.0 : irrad; } else { vert->energy = st.v[0].energy; } } - transform(&pclip, &pview, pmat); + vert->pos = pview; +} + +static int vertex_proc_proj(struct vertex *vert) +{ + vec4_t pclip; + + float *pmat = st.matrix[MGL_PROJECTION][st.mtop[MGL_PROJECTION]]; + + transform(&pclip, &vert->pos, pmat); /* TODO clipping in homogenous clip space */ - if(pclip.w < 1e-6 && pclip.w > -1e-6) { + if(pclip.w < 1e-6) { vert->pos.x = vert->pos.y = vert->pos.z = vert->pos.w = 0.0f; - return; + return -1; } /* perspective division */ @@ -354,6 +394,8 @@ /* viewport transformation */ vert->pos.x = st.vp[0] + st.vp[2] * (vert->pos.x * 0.5 + 0.5); vert->pos.y = st.vp[1] + st.vp[3] * (-vert->pos.y * 0.5 + 0.5); + + return 0; } void mgl_viewport(int x, int y, int width, int height) @@ -534,6 +576,29 @@ } } +void mgl_clip_plane(int id, float nx, float ny, float nz, float dist) +{ + id -= MGL_CLIP_PLANE0; + + if(id < 0 || id > MAX_CLIP_PLANES) { + return; + } + + st.clip_planes[id].normal.x = nx; + st.clip_planes[id].normal.y = ny; + st.clip_planes[id].normal.z = nz; + NORMALIZE(st.clip_planes[id].normal); + + st.clip_planes[id].pt.x = st.clip_planes[id].normal.x * dist; + st.clip_planes[id].pt.y = st.clip_planes[id].normal.y * dist; + st.clip_planes[id].pt.z = st.clip_planes[id].normal.z * dist; + + printf("set clip plane %d -> n[%f %f %f] p[%f %f %f]\n", id, + st.clip_planes[id].normal.x, st.clip_planes[id].normal.y, st.clip_planes[id].normal.z, + st.clip_planes[id].pt.x, st.clip_planes[id].pt.y, st.clip_planes[id].pt.z); + +} + #define MAX_SHIFT 12 static int calc_shiftmask(int val, int *shiftp, unsigned int *maskp) { diff -r dcfe615c4c5f -r 11d14f688485 src/mingl.h --- a/src/mingl.h Sun Sep 22 02:47:46 2013 +0300 +++ b/src/mingl.h Sun Sep 22 06:38:08 2013 +0300 @@ -1,29 +1,18 @@ -/* -256-color 3D graphics hack for real-mode DOS. -Copyright (C) 2011 John Tsiombikas - -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 . -*/ #ifndef MINGL_H_ #define MINGL_H_ /* enable bitflags */ -#define MGL_CULL_FACE 1 -#define MGL_DEPTH_TEST 2 -#define MGL_SMOOTH 4 -#define MGL_LIGHTING 8 -#define MGL_TEXTURE_2D 16 +#define MGL_CULL_FACE 0 +#define MGL_DEPTH_TEST 1 +#define MGL_SMOOTH 2 +#define MGL_LIGHTING 3 +#define MGL_TEXTURE_2D 4 +#define MGL_CLIP_PLANE0 5 +#define MGL_CLIP_PLANE1 6 +#define MGL_CLIP_PLANE2 7 +#define MGL_CLIP_PLANE3 8 +#define MGL_CLIP_PLANE4 9 +#define MGL_CLIP_PLANE5 10 /* primitives */ #define MGL_POINTS 1 @@ -57,6 +46,9 @@ void mgl_front_face(int ff); void mgl_cull_face(int cf); +void mgl_set_ambient(float amb); +float mgl_get_ambient(void); + void mgl_color_range(int rng); void mgl_light_intensity(int ltidx, float intens); void mgl_light_position(int ltidx, float x, float y, float z, float w); @@ -91,6 +83,8 @@ void mgl_teximage(int width, int height, unsigned char *pixels); +void mgl_clip_plane(int id, float nx, float ny, float nz, float dist); + void mgl_cube(float sz); void mgl_sphere(float rad, int usub, int vsub); void mgl_sphere_part(float rad, int usub, int vsub, float umax, float vmax); diff -r dcfe615c4c5f -r 11d14f688485 src/scantmpl.h --- a/src/scantmpl.h Sun Sep 22 02:47:46 2013 +0300 +++ b/src/scantmpl.h Sun Sep 22 06:38:08 2013 +0300 @@ -133,7 +133,7 @@ x1 = (int)fixed_round(vright[y].pos.x); if(x1 < x0) { - if(st->flags & MGL_CULL_FACE) { + if(IS_ENABLED(st->flags, MGL_CULL_FACE)) { return; } tmp = x0; diff -r dcfe615c4c5f -r 11d14f688485 src/test.c --- a/src/test.c Sun Sep 22 02:47:46 2013 +0300 +++ b/src/test.c Sun Sep 22 06:38:08 2013 +0300 @@ -286,6 +286,14 @@ prim = (prim + 1) % NUM_PRIMS; break; + case 'c': + if(mgl_isenabled(MGL_CULL_FACE)) { + mgl_disable(MGL_CULL_FACE); + } else { + mgl_enable(MGL_CULL_FACE); + } + break; + default: break; } diff -r dcfe615c4c5f -r 11d14f688485 src/vmath.h --- a/src/vmath.h Sun Sep 22 02:47:46 2013 +0300 +++ b/src/vmath.h Sun Sep 22 06:38:08 2013 +0300 @@ -32,48 +32,73 @@ fixed x, y; } vec2x_t; +typedef struct { + vec3_t origin, dir; +} ray3_t; + +#define vec3_dot(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z) + +#define vec2_lerp(res, a, b, t) \ + do { \ + (res).x = (a).x + ((b).x - (a).x) * (t); \ + (res).y = (a).y + ((b).y - (a).y) * (t); \ + } while(0) + +#define vec3_lerp(res, a, b, t) \ + do { \ + (res).x = (a).x + ((b).x - (a).x) * (t); \ + (res).y = (a).y + ((b).y - (a).y) * (t); \ + (res).z = (a).z + ((b).z - (a).z) * (t); \ + } while(0) + +#define ray3_point(res, ray, t) \ + do { \ + (res).x = (ray).origin.x + (ray).dir.x * (t); \ + (res).y = (ray).origin.y + (ray).dir.y * (t); \ + (res).z = (ray).origin.z + (ray).dir.z * (t); \ + } while(0) #define vec2_to_fixed2(v, f) \ do { \ - f.x = fixedf(v.x); \ - f.y = fixedf(v.y); \ + (f).x = fixedf((v).x); \ + (f).y = fixedf((v).y); \ } while(0) #define vec3_to_fixed3(v, f) \ do { \ - f.x = fixedf(v.x); \ - f.y = fixedf(v.y); \ - f.z = fixedf(v.z); \ + (f).x = fixedf((v).x); \ + (f).y = fixedf((v).y); \ + (f).z = fixedf((v).z); \ } while(0) #define vec4_to_fixed4(v, f) \ do { \ - f.x = fixedf(v.x); \ - f.y = fixedf(v.y); \ - f.z = fixedf(v.z); \ - f.w = fixedf(v.w); \ + (f).x = fixedf((v).x); \ + (f).y = fixedf((v).y); \ + (f).z = fixedf((v).z); \ + (f).w = fixedf((v).w); \ } while(0) #define fixed2_to_vec2(f, v) \ do { \ - v.x = fixed_float(f.x); \ - v.y = fixed_float(f.y); \ + (v).x = fixed_float((f).x); \ + (v).y = fixed_float((f).y); \ } while(0) #define fixed3_to_vec3(f, v) \ do { \ - v.x = fixed_float(f.x); \ - v.y = fixed_float(f.y); \ - v.z = fixed_float(f.z); \ + (v).x = fixed_float((f).x); \ + (v).y = fixed_float((f).y); \ + (v).z = fixed_float((f).z); \ } while(0) #define fixed4_to_vec4(f, v) \ do { \ - v.x = fixed_float(f.x); \ - v.y = fixed_float(f.y); \ - v.z = fixed_float(f.z); \ - v.w = fixed_float(f.w); \ + (v).x = fixed_float((f).x); \ + (v).y = fixed_float((f).y); \ + (v).z = fixed_float((f).z); \ + (v).w = fixed_float((f).w); \ } while(0)