* 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); | int, int); | ||||
__extern int caca_fill_triangle(caca_canvas_t *, int, int, int, int, int, | __extern int caca_fill_triangle(caca_canvas_t *, int, int, int, int, int, | ||||
int, uint32_t); | 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 | /** \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; | 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. | * 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}}" | MACOSX_SDK_CXXFLAGS="${MACOSX_SDK_CXXFLAGS:-${MACOSX_SDK_CFLAGS}}" | ||||
;; | ;; | ||||
x*86*darwin*) | 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}" | GCC_VERSION="${GCC_VERSION:-4.0}" | ||||
ARCH="${ARCH:--arch i386}" | ARCH="${ARCH:--arch i386}" | ||||
MACOSX_SDK_CFLAGS="${MACOSX_SDK_CFLAGS:--isysroot ${MACOSX_SDK}}" | 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 | 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 | if USE_CXX | ||||
conio_snake = conio-snake | conio_snake = conio-snake | ||||
endif | endif | ||||
trifiller_SOURCES = trifiller.c ../src/common-image.c | |||||
trifiller_LDADD = ../caca/libcaca.la | |||||
blit_SOURCES = blit.c | blit_SOURCES = blit.c | ||||
blit_LDADD = ../caca/libcaca.la | 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; | |||||
} |