Quellcode durchsuchen

* Added texture mapped triangle routine, float based, arbitrary texture size, to be optimized

* Made compilation under MacOSX 10.6 (Snow Leopard) possible, but breaks 10.4 (Tiger), to be fixed
tags/v0.99.beta17
Jean-Yves Lamoureux jylam vor 15 Jahren
Ursprung
Commit
67679dc55d
5 geänderte Dateien mit 448 neuen und 2 gelöschten Zeilen
  1. +8
    -0
      caca/caca.h
  2. +196
    -0
      caca/triangle.c
  3. +1
    -1
      configure.ac
  4. +4
    -1
      examples/Makefile.am
  5. +239
    -0
      examples/trifiller.c

+ 8
- 0
caca/caca.h Datei anzeigen

@@ -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


+ 196
- 0
caca/triangle.c Datei anzeigen

@@ -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.
*/


+ 1
- 1
configure.ac Datei anzeigen

@@ -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}}"


+ 4
- 1
examples/Makefile.am Datei anzeigen

@@ -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



+ 239
- 0
examples/trifiller.c Datei anzeigen

@@ -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;
}

Laden…
Abbrechen
Speichern