* Made compilation under MacOSX 10.6 (Snow Leopard) possible, but breaks 10.4 (Tiger), to be fixedtags/v0.99.beta17
@@ -338,6 +338,14 @@ __extern int caca_draw_thin_triangle(caca_canvas_t *, int, int, int, int, | |||
int, int); | |||
__extern int caca_fill_triangle(caca_canvas_t *, int, int, int, int, int, | |||
int, uint32_t); | |||
__extern int caca_fill_triangle_textured(caca_canvas_t *, | |||
int , int , | |||
int , int , | |||
int , int , | |||
float , float , | |||
float , float , | |||
float , float , | |||
caca_canvas_t *); | |||
/* @} */ | |||
/** \defgroup caca_frame libcaca canvas frame handling | |||
@@ -155,6 +155,202 @@ int caca_fill_triangle(caca_canvas_t *cv, int x1, int y1, int x2, int y2, | |||
return 0; | |||
} | |||
/** \brief Fill a triangle on the canvas using an arbitrary-sized texture. | |||
* | |||
* This function fails if one or both the canvas are missing | |||
* | |||
* \param cv The handle to the libcaca canvas. | |||
* \param x1 X coordinate of the first point. | |||
* \param y1 Y coordinate of the first point. | |||
* \param x2 X coordinate of the second point. | |||
* \param y2 Y coordinate of the second point. | |||
* \param x3 X coordinate of the third point. | |||
* \param y3 Y coordinate of the third point. | |||
* \param u1 U texture coordinate of the first point. | |||
* \param v1 V texture coordinate of the first point. | |||
* \param u2 U texture coordinate of the second point. | |||
* \param v2 V texture coordinate of the second point. | |||
* \param u3 U texture coordinate of the third point. | |||
* \param v3 V texture coordinate of the third point. | |||
* \param tex The handle of the canvas texture. | |||
* \return This function return 0 if ok, -1 if canvas or texture are missing. | |||
*/ | |||
int caca_fill_triangle_textured(caca_canvas_t *cv, | |||
int x1, int y1, | |||
int x2, int y2, | |||
int x3, int y3, | |||
float u1, float v1, | |||
float u2, float v2, | |||
float u3, float v3, | |||
caca_canvas_t *tex) | |||
{ | |||
#define SWAP_F(a, b) {float c = a; a = b; b = c; } | |||
/* (very) Naive and | |||
* (very) float-based affine and | |||
* (very) non-clipped and | |||
* (very) non-corrected triangle mapper | |||
* | |||
* Accepts arbitrary texture sizes | |||
* Coordinates clamped to [0.0 - 1.0] (no repeat) | |||
*/ | |||
if(!cv || !tex) return -1; | |||
/* Bubble-sort y1 <= y2 <= y3 */ | |||
if(y1 > y2) | |||
return caca_fill_triangle_textured(cv, | |||
x2, y2, x1, y1, x3, y3, | |||
u2, v2, u1, v1, u3, v3, | |||
tex); | |||
if(y2 > y3) | |||
return caca_fill_triangle_textured(cv, | |||
x1, y1, x3, y3, x2, y2, | |||
u1, v1, u3, v3, u2, v2, | |||
tex); | |||
/* Clip texture coordinates */ | |||
if(u1<0.0f) u1 = 0.0f; if(v1<0.0f) v1 = 0.0f; | |||
if(u2<0.0f) u2 = 0.0f; if(v2<0.0f) v2 = 0.0f; | |||
if(u3<0.0f) u3 = 0.0f; if(v3<0.0f) v3 = 0.0f; | |||
if(u1>1.0f) u1 = 1.0f; if(v1>1.0f) v1 = 1.0f; | |||
if(u2>1.0f) u2 = 1.0f; if(v2>1.0f) v2 = 1.0f; | |||
if(u3>1.0f) u3 = 1.0f; if(v3>1.0f) v3 = 1.0f; | |||
/* Convert relative tex coordinates to absolute */ | |||
int tw = caca_get_canvas_width(tex); | |||
int th = caca_get_canvas_height(tex); | |||
u1*=(float)tw; u2*=(float)tw; u3*=(float)tw; | |||
v1*=(float)th; v2*=(float)th; v3*=(float)th; | |||
float x = (float) x1, y = (float) y1; | |||
float y2y1 = y2-y1; | |||
float y3y1 = y3-y1; | |||
float y3y2 = y3-y2; | |||
/* Compute slopes, making sure we don't divide by zero */ | |||
/* (in this case, we don't need the value anyway) */ | |||
/* FIXME : only compute needed slopes */ | |||
float sl12 = ((float)x2 - x1) / (y2y1==0?1:y2y1); | |||
float sl13 = ((float)x3 - x1) / (y3y1==0?1:y3y1); | |||
float sl23 = ((float)x3 - x2) / (y3y2==0?1:y3y2); | |||
float usl12 = (u2 - u1) / (y2y1==0?1:y2y1); | |||
float usl13 = (u3 - u1) / (y3y1==0?1:y3y1); | |||
float usl23 = (u3 - u2) / (y3y2==0?1:y3y2); | |||
float vsl12 = (v2 - v1) / (y2y1==0?1:y2y1); | |||
float vsl13 = (v3 - v1) / (y3y1==0?1:y3y1); | |||
float vsl23 = (v3 - v2) / (y3y2==0?1:y3y2); | |||
float xa = (float) x1, xb = (float) x1; | |||
float ua = u1, ub = u1; | |||
float va = v1, vb = v1; | |||
float u, v; | |||
int s = 0; | |||
/* Top */ | |||
for(y = y1 ; y < y2; y++) | |||
{ | |||
if(xb < xa) { | |||
SWAP_F(xb, xa); | |||
SWAP_F(sl13, sl12); | |||
SWAP_F(ua, ub); | |||
SWAP_F(va, vb); | |||
SWAP_F(usl13, usl12); | |||
SWAP_F(vsl13, vsl12); | |||
s=1; | |||
} | |||
float tus = (ub - ua) / (xb - xa); | |||
float tvs = (vb - va) / (xb - xa); | |||
v = va; u = ua; | |||
/* scanline */ | |||
for(x = xa ; x < xb; x++) | |||
{ | |||
u+=tus; | |||
v+=tvs; | |||
/* FIXME: use caca_get_canvas_attrs / caca_get_canvas_chars */ | |||
uint32_t attr = caca_get_attr(tex, u, v); | |||
uint32_t c = caca_get_char(tex, u, v); | |||
caca_set_attr(cv, attr); | |||
caca_put_char(cv, x, y, c); | |||
} | |||
xa+=sl13; | |||
xb+=sl12; | |||
ua+=usl13; va+=vsl13; | |||
ub+=usl12; vb+=vsl12; | |||
} | |||
if(s) | |||
{ | |||
SWAP_F(xb, xa); | |||
SWAP_F(sl13, sl12); | |||
SWAP_F(ua, ub); | |||
SWAP_F(va, vb); | |||
SWAP_F(usl13, usl12); | |||
SWAP_F(vsl13, vsl12); | |||
} | |||
/* Bottom */ | |||
xb = (float) x2; | |||
/* These variables are set by 'top' routine | |||
* and are in an incorrect state if we only draw the bottom part | |||
*/ | |||
if(y1 == y2) { | |||
ua = u1; | |||
ub = u2; | |||
va = v1; | |||
vb = v2; | |||
} | |||
for(y = y2 ; y < y3; y++) | |||
{ | |||
if(xb <= xa) | |||
{ | |||
SWAP_F(xb, xa); | |||
SWAP_F(sl13, sl23); | |||
SWAP_F(ua, ub); | |||
SWAP_F(va, vb); | |||
SWAP_F(usl13, usl23); | |||
SWAP_F(vsl13, vsl23); | |||
} | |||
float tus = (ub - ua) / ((float)xb - xa); | |||
float tvs = (vb - va) / ((float)xb - xa); | |||
u = ua; v = va; | |||
/* scanline */ | |||
for(x = xa ; x < xb; x++) | |||
{ | |||
u+=tus; | |||
v+=tvs; | |||
/* FIXME, can be heavily optimised */ | |||
uint32_t attr = caca_get_attr(tex, u, v); | |||
uint32_t c = caca_get_char(tex, u, v); | |||
caca_set_attr(cv, attr); | |||
caca_put_char(cv, x, y, c); | |||
} | |||
xa+=sl13; | |||
xb+=sl23; | |||
ua+=usl13; va+=vsl13; | |||
ub+=usl23; vb+=vsl23; | |||
} | |||
return 0; | |||
} | |||
/* | |||
* XXX: The following functions are aliases. | |||
*/ | |||
@@ -258,7 +258,7 @@ if test "${enable_cocoa}" != "no"; then | |||
MACOSX_SDK_CXXFLAGS="${MACOSX_SDK_CXXFLAGS:-${MACOSX_SDK_CFLAGS}}" | |||
;; | |||
x*86*darwin*) | |||
MACOSX_SDK="${MACOSX_SDK:-/Developer/SDKs/MacOSX10.4u.sdk}" | |||
MACOSX_SDK="${MACOSX_SDK:-/Developer/SDKs/MacOSX10.6.sdk}" | |||
GCC_VERSION="${GCC_VERSION:-4.0}" | |||
ARCH="${ARCH:--arch i386}" | |||
MACOSX_SDK_CFLAGS="${MACOSX_SDK_CFLAGS:--isysroot ${MACOSX_SDK}}" | |||
@@ -2,12 +2,15 @@ | |||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/caca -I$(top_builddir)/caca | |||
noinst_PROGRAMS = blit canvas colors conio $(conio_snake) demo demo0 dithering driver event export figfont font font2tga frames fullwidth gamma hsv input spritedit swallow text transform truecolor unicode import | |||
noinst_PROGRAMS = trifiller blit canvas colors conio $(conio_snake) demo demo0 dithering driver event export figfont font font2tga frames fullwidth gamma hsv input spritedit swallow text transform truecolor unicode import | |||
if USE_CXX | |||
conio_snake = conio-snake | |||
endif | |||
trifiller_SOURCES = trifiller.c ../src/common-image.c | |||
trifiller_LDADD = ../caca/libcaca.la | |||
blit_SOURCES = blit.c | |||
blit_LDADD = ../caca/libcaca.la | |||
@@ -0,0 +1,239 @@ | |||
/* | |||
* trifiller texture mapping features | |||
* Copyright (c) 2009 Jean-Yves Lamoureux <jylam@lnxscene.org> | |||
* All Rights Reserved | |||
* | |||
* $Id: trifiller.c 2821 2008-09-27 13:12:46Z sam $ | |||
* | |||
* This program is free software. It comes without any warranty, to | |||
* the extent permitted by applicable law. You can redistribute it | |||
* and/or modify it under the terms of the Do What The Fuck You Want | |||
* To Public License, Version 2, as published by Sam Hocevar. See | |||
* http://sam.zoy.org/wtfpl/COPYING for more details. | |||
*/ | |||
#include "config.h" | |||
#if !defined(__KERNEL__) | |||
# include <stdio.h> | |||
# include <string.h> | |||
#endif | |||
/* libcaca header */ | |||
#include "caca.h" | |||
/* Image loading functions */ | |||
#include "../src/common-image.h" | |||
/* M_PI / cos / sin */ | |||
#include <math.h> | |||
#define SQUARE_SIZE 20 | |||
int main(int argc, char *argv[]) | |||
{ | |||
/* libcaca/libcaca contexts */ | |||
caca_canvas_t *cv; caca_display_t *dp; | |||
caca_canvas_t *tex; | |||
/* cached canvas size */ | |||
int ww, wh, tw, th; | |||
/* logic */ | |||
int quit = 0; | |||
int update = 1; | |||
int px, py; | |||
float angle = 0; | |||
float square[4][2] = { | |||
{-SQUARE_SIZE, -SQUARE_SIZE}, | |||
{ SQUARE_SIZE, -SQUARE_SIZE}, | |||
{ SQUARE_SIZE, SQUARE_SIZE}, | |||
{-SQUARE_SIZE, SQUARE_SIZE}, | |||
}; | |||
float rotated[4][2]; | |||
/* Create displayed canvas */ | |||
cv = caca_create_canvas(0, 0); | |||
if(!cv) | |||
{ | |||
fprintf(stderr, "%s: unable to initialise libcaca\n", argv[0]); | |||
return 1; | |||
} | |||
/* Create texture holding canvas */ | |||
tex = caca_create_canvas(16, 16); | |||
if(!tex) | |||
{ | |||
fprintf(stderr, "%s: unable to initialise libcaca\n", argv[0]); | |||
return 1; | |||
} | |||
/* Open window */ | |||
dp = caca_create_display(cv); | |||
if(!dp) | |||
{ | |||
fprintf(stderr, "%s: unable to initialise libcaca\n", argv[0]); | |||
return 1; | |||
} | |||
/* Set the window title */ | |||
caca_set_display_title(dp, "trifiller"); | |||
/* Frame duration */ | |||
caca_set_display_time(dp, 10000); | |||
/* Get displayed canvas size */ | |||
ww = caca_get_canvas_width(cv); | |||
wh = caca_get_canvas_height(cv); | |||
/* Texture size */ | |||
tw = caca_get_canvas_width(tex); | |||
th = caca_get_canvas_height(tex); | |||
/* Load texture if any */ | |||
if(argc == 2) | |||
{ | |||
struct image *im = load_image(argv[1]); | |||
if(!im) | |||
{ | |||
fprintf(stderr, "%s: unable to load image '%s'\n", argv[0], argv[1]); | |||
return 1; | |||
} | |||
caca_set_dither_algorithm(im->dither, | |||
caca_get_dither_algorithm_list(NULL)[4]); | |||
caca_dither_bitmap(tex, | |||
0, 0, | |||
tw, th, | |||
im->dither, im->pixels); | |||
unload_image(im); | |||
} | |||
/* or generate one */ | |||
else | |||
{ | |||
int i; | |||
for(i = 0; i < 16; i ++) | |||
{ | |||
caca_set_color_ansi(tex, (i+1)%0xF, i); | |||
caca_put_str(tex, 0, i, "123456789ABCDEF"); | |||
} | |||
} | |||
px = 0; | |||
py = 0; | |||
while(!quit) | |||
{ | |||
caca_event_t ev; | |||
unsigned int const event_mask = CACA_EVENT_KEY_PRESS | |||
| CACA_EVENT_RESIZE | |||
| CACA_EVENT_QUIT; | |||
int event; | |||
if(update) | |||
event = caca_get_event(dp, event_mask, &ev, 0); | |||
else | |||
event = caca_get_event(dp, event_mask, &ev, -1); | |||
while(event) | |||
{ | |||
if(caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS) | |||
switch(caca_get_event_key_ch(&ev)) | |||
{ | |||
case 'q': | |||
case 'Q': | |||
case CACA_KEY_ESCAPE: | |||
quit = 1; | |||
break; | |||
case CACA_KEY_UP: | |||
py--; | |||
break; | |||
case CACA_KEY_DOWN: | |||
py++; | |||
break; | |||
case CACA_KEY_LEFT: | |||
px--; | |||
break; | |||
case CACA_KEY_RIGHT: | |||
px++; | |||
break; | |||
case 'a': | |||
angle+=1.0f; | |||
break; | |||
case 's': | |||
angle-=1.0f; | |||
break; | |||
} | |||
else if(caca_get_event_type(&ev) == CACA_EVENT_RESIZE) | |||
{ | |||
caca_refresh_display(dp); | |||
ww = caca_get_event_resize_width(&ev); | |||
wh = caca_get_event_resize_height(&ev); | |||
update = 1; | |||
} | |||
else if(caca_get_event_type(&ev) & CACA_EVENT_QUIT) | |||
quit = 1; | |||
event = caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0); | |||
} | |||
/* 2D Rotation around screen center */ | |||
int p; | |||
for(p=0; p<4; p++) | |||
{ | |||
rotated[p][0] = square[p][0] * cos(angle*M_PI/180.0f) - square[p][1] * sin(angle*M_PI/180.0f); | |||
rotated[p][1] = square[p][0] * sin(angle*M_PI/180.0f) + square[p][1] * cos(angle*M_PI/180.0f); | |||
rotated[p][0] += ww/2 + px; | |||
rotated[p][1] += wh/2 + py; | |||
} | |||
angle+=1.0f; | |||
/* Display two triangles */ | |||
caca_fill_triangle_textured(cv, | |||
/* triangle screen coordinates */ | |||
rotated[0][0], rotated[0][1], | |||
rotated[1][0], rotated[1][1], | |||
rotated[2][0], rotated[2][1], | |||
/* texture coordinates */ | |||
0, 0, | |||
1, 0, | |||
1, 1, | |||
tex); | |||
caca_fill_triangle_textured(cv, | |||
/* triangle screen coordinates */ | |||
rotated[0][0], rotated[0][1], | |||
rotated[2][0], rotated[2][1], | |||
rotated[3][0], rotated[3][1], | |||
/* texture coordinates */ | |||
0, 0, | |||
1, 1, | |||
0, 1, | |||
tex); | |||
/* Refresh display and clear for next frame */ | |||
caca_refresh_display(dp); | |||
caca_clear_canvas(cv); | |||
} | |||
caca_free_display(dp); | |||
caca_free_canvas(cv); | |||
caca_free_canvas(tex); | |||
return 0; | |||
} |