#include "demo.h"
#include "screen.h"
-#include "tinyfps.h"
static int init(void);
static void destroy(void);
#define BIG_LIGHT_WIDTH 256
#define BIG_LIGHT_HEIGHT BIG_LIGHT_WIDTH
+#define NUM_PARTICLES 64
+#define PARTICLE_LIGHT_WIDTH 32
+#define PARTICLE_LIGHT_HEIGHT 32
+
+
static unsigned long startingTime;
static unsigned char *heightmap;
static unsigned short *bigLight[NUM_BIG_LIGHTS];
static struct point bigLightPoint[NUM_BIG_LIGHTS];
+static unsigned short *particleLight;
+static struct point particlePoint[NUM_PARTICLES];
+
struct screen *bump_screen(void)
{
return &scr;
const int numBlurs = 3;
const int lightRadius = BIG_LIGHT_WIDTH / 2;
+ const int particleRadius = PARTICLE_LIGHT_WIDTH / 2;
const int bigLightSize = BIG_LIGHT_WIDTH * BIG_LIGHT_HEIGHT;
+ const int particleLightSize = PARTICLE_LIGHT_WIDTH * PARTICLE_LIGHT_HEIGHT;
const int fb_size = fb_width * fb_height;
// Just some parameters to temporary test the colors of 3 lights
const float rgbMul[9] = { 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f};
- initFpsFonts();
heightmap = malloc(sizeof(*heightmap) * fb_size);
lightmap = malloc(sizeof(*lightmap) * fb_size);
for (i = 0; i < NUM_BIG_LIGHTS; i++)
bigLight[i] = malloc(sizeof(*bigLight[i]) * bigLightSize);
+ particleLight = malloc(sizeof(*particleLight) * particleLightSize);
+
memset(lightmap, 0, sizeof(*lightmap) * fb_size);
memset(bumpOffset, 0, sizeof(*bumpOffset) * fb_size);
+ memset(particlePoint, 0, sizeof(*particlePoint) * NUM_PARTICLES);
// Create random junk
for (i = 0; i < fb_size; i++)
{
for (x = 0; x < fb_width; x++)
{
- const float offsetPower = 2.0f;
+ const float offsetPower = 0.5f;
int dx, dy, xp, yp;
dx = i < fb_size - 1 ? (int)((heightmap[i] - heightmap[i + 1]) * offsetPower) : 0;
}
}
+ i = 0;
+ for (y = 0; y < PARTICLE_LIGHT_HEIGHT; y++)
+ {
+ int yc = y - (PARTICLE_LIGHT_HEIGHT / 2);
+ for (x = 0; x < PARTICLE_LIGHT_WIDTH; x++)
+ {
+ int xc = x - (PARTICLE_LIGHT_WIDTH / 2);
+
+ float invDist = ((float)particleRadius - (float)sqrt(xc * xc + yc * yc)) / (float)particleRadius;
+ if (invDist < 0.0f) invDist = 0.0f;
+
+ c = (int)(invDist * 63);
+ particleLight[i++] = ((c >> 1) << 11) | (c << 5) | (c >> 1);
+ }
+ }
+
return 0;
}
renderLight(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT, bigLight[i]);
}
+static void renderParticles()
+{
+ int i;
+ for (i = 0; i < NUM_PARTICLES; i++)
+ renderLight(&particlePoint[i], PARTICLE_LIGHT_WIDTH, PARTICLE_LIGHT_HEIGHT, particleLight);
+}
+
static void animateLights()
{
struct point center;
}
}
+static void animateParticles()
+{
+ int i;
+ struct point center;
+ float dt = (float)(time_msec - startingTime) / 1000.0f;
+
+ center.x = (fb_width >> 1) - (PARTICLE_LIGHT_WIDTH / 2);
+ center.y = (fb_height >> 1) - (PARTICLE_LIGHT_HEIGHT / 2);
+
+ for (i = 0; i < NUM_PARTICLES; i++)
+ {
+ particlePoint[i].x = center.x + sin(1.2f * (i*i*i + dt)) * 74.0f + sin(0.6f * (i + dt)) * 144.0f;
+ particlePoint[i].y = center.y + sin(1.8f * (i + dt)) * 68.0f + sin(0.5f * (i*i + dt)) * 132.0f;
+ }
+}
+
static void draw(void)
{
- eraseLights();
+ memset(lightmap, 0, fb_width * fb_height * sizeof(*lightmap));
+
+ //eraseLights();
animateLights();
renderLights();
- renderBump((unsigned short*)vmem_back);
- drawFps((unsigned short*)vmem_back);
+ animateParticles();
+ renderParticles();
+
+ renderBump((unsigned short*)vmem_back);
swap_buffers(0);
}
#include "3dgfx.h"
#include "music.h"
#include "cfgopt.h"
+#include "tinyfps.h"
int fb_width = 320;
int fb_height = 240;
return -1;
}
+ initFpsFonts();
+
if(g3d_init() == -1) {
return -1;
}
/* TODO implement page flipping */
if(pixels) {
/*wait_vsync();*/
+ drawFps(pixels);
memcpy(vmem_front, pixels, fbsize);
+ } else {
+ drawFps(vmem_back);
}
}
static void destroy(void);
static void draw(void);
static int julia(long x, long y, long cx, long cy, int max_iter);
-static int calc_walk(struct vec2x *path, long x, long y, int max_steps);
static struct screen scr = {
"fract",
static void draw(void)
{
- int i, j, len, x, y;
- unsigned short *pixels = fb_pixels;
- struct vec2x walkpos[WALK_SIZE];
+ int i, j;
+ unsigned short *pixels = vmem_back;
cx = mouse_x;
cy = mouse_y;
}
}
- pixels = fb_pixels;
-
- if((len = calc_walk(walkpos, mouse_x, mouse_y, WALK_SIZE))) {
- x = walkpos[0].x >> 16;
- y = walkpos[0].y >> 16;
-
- for(i=1; i<len; i++) {
- int x0 = x;
- int y0 = y;
- int x1 = walkpos[i].x >> 16;
- int y1 = walkpos[i].y >> 16;
-
- if(clip_line(&x0, &y0, &x1, &y1, 0, 0, fb_width - 1, fb_height - 1)) {
- draw_line(x0, y0, x1, y1, PACK_RGB16(32, 128, 255));
- }
- x = x1;
- y = y1;
- }
- }
-
+ pixels = vmem_back;
pixels[mouse_y * fb_width + mouse_x] = 0xffe;
-
- swap_buffers(fb_pixels);
+ swap_buffers(vmem_back);
}
static long normalize_coord(long x, long range)
return (x << 17) / range - 65536;
}
-static long device_coord(long x, long range)
-{
- /* (x + 1) / 2 * (range - 1) */
- return ((x + 65536) >> 1) * (range - 1);
-}
-
static int julia(long x, long y, long cx, long cy, int max_iter)
{
int i;
return i < max_iter ? (256 * i / max_iter) : 0;
}
-
-static int calc_walk(struct vec2x *path, long x, long y, int max_steps)
-{
- int i;
- long cx, cy;
-
- /* convert to fixed point roughly [-1, 1] */
- x = cx = (normalize_coord(x, fb_width) >> 8) * xscale_24x8;
- y = cy = (normalize_coord(y, fb_height) >> 8) * yscale_24x8;
-
- for(i=0; i<max_steps; i++) {
- /* z_n = z_{n-1}**2 + c */
- long px = x >> 8;
- long py = y >> 8;
-
- path[i].x = device_coord((x << 8) / xscale_24x8, fb_width);
- path[i].y = device_coord((y << 8) / yscale_24x8, fb_height);
-
- if(px * px + py * py > (4 << 16)) {
- break;
- }
- x = px * px - py * py + cx;
- y = (px * py << 1) + cy;
- }
-
- return i;
-}
static RLEBitmap *rleCreate(unsigned int w, unsigned int h);
static void rleDestroy(RLEBitmap *b);
-static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride,
+static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride,
RLEBitmap *bitmap, int blitX, int blitY);
static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride,
RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY);
static void updatePropeller(float t);
-extern void drawFps(unsigned short *vram);
-
#define BG_FILENAME "data/grise.png"
#define GROBJ_01_FILENAME "data/grobj_01.png"
static unsigned short *background = 0;
-static unsigned int backgroundW = 0;
-static unsigned int backgroundH = 0;
+static int backgroundW = 0;
+static int backgroundH = 0;
static unsigned int lastFrameTime = 0;
static float lastFrameDuration = 0.0f;
static int scrollModTable[REFLECTION_HEIGHT];
static float nearScrollAmount = 0.0f;
-static char miniFXBuffer[1024];
+static unsigned char miniFXBuffer[1024];
static RLEBitmap *grobj = 0;
static RLEBitmap *rlePropeller = 0;
init,
destroy,
start,
- stop,
+ 0,
draw
};
processNormal();
-#ifdef MIKE_PC
- return 0xCAFE;
-#else
return 0;
-#endif
}
static void destroy(void)
lastFrameTime = time_msec;
}
-static void stop(long trans_time)
-{
-}
-
-
-
static void draw(void)
-{
+{
int scroll = MIN_SCROLL + (MAX_SCROLL - MIN_SCROLL) * mouse_x / fb_width;
unsigned short *dst = backBuffer + PIXEL_PADDING;
unsigned short *src = background + scroll;
src += backgroundW;
dst += BB_SIZE;
}
-
+
/* Create scroll offsets for all scanlines of the normalmap */
updateScrollTables(lastFrameDuration);
- /* Render the baked reflection one scanline below its place, so that
+ /* Render the baked reflection one scanline below its place, so that
* the displacement that follows will be done in a cache-friendly way
*/
src -= PIXEL_PADDING; /* We want to also fill the PADDING pixels here */
/* Then after displacement, blit the objects */
for (i = 0; i < 5; i++) rleBlit(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 100);
-
+
/* Blit effect to framebuffer */
src = backBuffer + PIXEL_PADDING;
dst = vmem_back;
for (scanline = 0; scanline < fb_height; scanline++) {
memcpy(dst, src, fb_width * 2);
- src += BB_SIZE;
+ src += BB_SIZE;
dst += fb_width;
}
- drawFps(vmem_back);
-
swap_buffers(0);
}
static void updateScrollTables(float dt) {
int i = 0;
-
+
nearScrollAmount += dt * NEAR_SCROLL_SPEED;
nearScrollAmount = (float) fmod(nearScrollAmount, 512.0f);
}
/* -------------------------------------------------------------------------------------------------
- * RLE STUFF
+ * RLE STUFF
* -------------------------------------------------------------------------------------------------
*/
/* Limit streak count per scanline so we can directly jump to specific scanline */
static void rleDistributeStreaks(RLEBitmap *bitmap) {
int scanline, halfW = bitmap->w >> 1;
unsigned char *ptr, tmp;
-
+
ptr = bitmap->scans;
for (scanline = 0; scanline < bitmap->h; scanline++) {
if (ptr[0] >= halfW) {
}
static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride,
- RLEBitmap *bitmap, int blitX, int blitY)
+ RLEBitmap *bitmap, int blitX, int blitY)
{
int scanline = 0;
int streakPos = 0;
t += 1.0f;
ti = (*((unsigned int*)&t)) & 0x7FFFFF;
-
+
for (i = 0; i < RLE_BYTES_PER_SCANLINE; i++) {
if (*a == 0) {
*output++ = *b++;
int scaleXFixed;
static unsigned char scan[512];
- int blitW = (int)(bitmap->w * scaleX + 0.5f);
+ /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/
int blitH = (int)(bitmap->h * scaleY + 0.5f);
/* From this point on, scaleY will be inverted */
int scaleXFixed;
static unsigned char scan[512];
- int blitW = (int)(bitmap->w * scaleX + 0.5f);
+ /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/
int blitH = (int)(bitmap->h * scaleY + 0.5f);
/* From this point on, scaleY will be inverted */
static void updatePropeller(float t) {
int i, j;
int cx, cy, count = 0;
- char *dst;
+ unsigned char *dst;
float x = 0.0f;
float y = 18.0f;
float nx, ny;
#include "demo.h"
#include "screen.h"
-#include "tinyfps.h"
static int init(void);
static void destroy(void);
{
int i;
- initFpsFonts();
-
psin1 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE);
psin2 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE);
psin3 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE);
plasmaPal[i] = (r<<11) | (g<<5) | b;
}
- //return 0xCAFE;
return 0;
}
}
}
- drawFps((unsigned short*)vmem_back);
-
swap_buffers(0);
}
--- /dev/null
+#include <math.h>
+#include <assert.h>
+#include "polyclip.h"
+
+struct ray {
+ float origin[3];
+ float dir[3];
+};
+
+static int clip_edge(struct g3d_vertex *poly, int *vnumptr,
+ const struct g3d_vertex *v0, const struct g3d_vertex *v1,
+ const struct cplane *plane);
+static float distance_signed(float *pos, const struct cplane *plane);
+static int intersect(const struct ray *ray, const struct cplane *plane, float *t);
+
+
+int clip_poly(struct g3d_vertex *vout, int *voutnum,
+ const struct g3d_vertex *vin, int vnum, struct cplane *plane)
+{
+ int i;
+ int edges_clipped = 0;
+ int out_vnum = 0;
+
+ for(i=0; i<vnum; i++) {
+ int res = clip_edge(vout, &out_vnum, vin + i, vin + (i + 1) % vnum, plane);
+ if(res == 0) {
+ edges_clipped++;
+ }
+ }
+
+ if(out_vnum <= 0) {
+ assert(edges_clipped == 0);
+ return -1;
+ }
+
+ *voutnum = out_vnum;
+ return edges_clipped > 0 ? 0 : 1;
+}
+
+#define LERP_VATTR(res, v0, v1, t) \
+ do { \
+ (res)->nx = (v0)->nx + ((v1)->nx - (v0)->nx) * (t); \
+ (res)->ny = (v0)->ny + ((v1)->ny - (v0)->ny) * (t); \
+ (res)->nz = (v0)->nz + ((v1)->nz - (v0)->nz) * (t); \
+ (res)->u = (v0)->u + ((v1)->u - (v0)->u) * (t); \
+ (res)->v = (v0)->v + ((v1)->v - (v0)->v) * (t); \
+ (res)->r = (v0)->r + ((v1)->r - (v0)->r) * (t); \
+ (res)->g = (v0)->g + ((v1)->g - (v0)->g) * (t); \
+ (res)->b = (v0)->b + ((v1)->b - (v0)->b) * (t); \
+ } while(0)
+
+
+/* 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 g3d_vertex *poly, int *vnumptr,
+ const struct g3d_vertex *v0, const struct g3d_vertex *v1,
+ const struct cplane *plane)
+{
+ float pos0[3], pos1[3];
+ float d0, d1, t;
+ struct ray ray;
+ int i, vnum = *vnumptr;
+
+ pos0[0] = v0->x; pos0[1] = v0->y; pos0[2] = v0->z;
+ pos1[0] = v1->x; pos1[1] = v1->y; pos1[2] = v1->z;
+
+ d0 = distance_signed(pos0, plane);
+ d1 = distance_signed(pos1, plane);
+
+ for(i=0; i<3; i++) {
+ ray.origin[i] = pos0[i];
+ ray.dir[i] = pos1[i] - pos0[i];
+ }
+
+ if(d0 >= 0.0) {
+ /* start inside */
+ if(d1 >= 0.0) {
+ /* all inside */
+ poly[vnum++] = *v1; /* append v1 */
+ *vnumptr = vnum;
+ return 1;
+ } else {
+ /* going out */
+ struct g3d_vertex *vptr = poly + vnum;
+
+ intersect(&ray, plane, &t);
+
+ vptr->x = ray.origin[0] + ray.dir[0] * t;
+ vptr->y = ray.origin[1] + ray.dir[1] * t;
+ vptr->z = ray.origin[2] + ray.dir[2] * t;
+ vptr->w = 1.0f;
+
+ LERP_VATTR(vptr, v0, v1, t);
+ vnum++; /* append new vertex on the intersection point */
+ }
+ } else {
+ /* start outside */
+ if(d1 >= 0) {
+ /* going in */
+ struct g3d_vertex *vptr = poly + vnum;
+
+ intersect(&ray, plane, &t);
+
+ vptr->x = ray.origin[0] + ray.dir[0] + t;
+ vptr->y = ray.origin[1] + ray.dir[1] + t;
+ vptr->z = ray.origin[2] + ray.dir[2] + t;
+ vptr->w = 1.0f;
+
+ LERP_VATTR(vptr, v0, v1, t);
+ vnum++; /* append new vertex on the intersection point */
+
+ /* then append v1 ... */
+ poly[vnum++] = *v1;
+ } else {
+ /* all outside */
+ return -1;
+ }
+ }
+
+ *vnumptr = vnum;
+ return 0;
+}
+
+
+static float distance_signed(float *pos, const struct cplane *plane)
+{
+ float dx = pos[0] - plane->x;
+ float dy = pos[1] - plane->y;
+ float dz = pos[2] - plane->z;
+ return dx * plane->nx + dy * plane->ny + dz * plane->nz;
+}
+
+static int intersect(const struct ray *ray, const struct cplane *plane, float *t)
+{
+ float orig_pt_dir[3];
+
+ float ndotdir = plane->nx * ray->dir[0] + plane->ny * ray->dir[1] + plane->nz * ray->dir[2];
+ if(fabs(ndotdir) < 1e-4) {
+ *t = 0.0f;
+ return 0;
+ }
+
+ orig_pt_dir[0] = plane->x - ray->origin[0];
+ orig_pt_dir[1] = plane->y - ray->origin[1];
+ orig_pt_dir[2] = plane->z - ray->origin[2];
+
+ *t = (plane->nx * orig_pt_dir[0] + plane->ny * orig_pt_dir[1] + plane->nz * orig_pt_dir[2]) / ndotdir;
+ return 1;
+}
--- /dev/null
+#ifndef POLYCLIP_H_
+#define POLYCLIP_H_
+
+#include "3dgfx.h"
+
+struct cplane {
+ float x, y, z;
+ float nx, ny, nz;
+};
+
+/* Polygon clipper
+ * returns:
+ * 1 -> fully inside, not clipped
+ * 0 -> straddling the plane and clipped
+ * -1 -> fully outside, not clipped
+ * in all cases, vertices are copied to vout, and the vertex count is written
+ * to wherever voutnum is pointing
+ */
+int clip_poly(struct g3d_vertex *vout, int *voutnum,
+ const struct g3d_vertex *vin, int vnum, struct cplane *plane);
+
+#endif /* POLYCLIP_H_ */
#include <limits.h>
#include <SDL/SDL.h>
#include "demo.h"
+#include "tinyfps.h"
static void handle_event(SDL_Event *ev);
static void toggle_fullscreen(void);
time_msec = SDL_GetTicks() - start_time;
demo_draw();
+ drawFps(fb_pixels);
if(SDL_MUSTLOCK(fbsurf)) {
SDL_LockSurface(fbsurf);