acl00d_sdl2.zip の sample の kcube.c の固定小数点数版です。 AInt32による小数部12bitの固定小数点数です。 三角関数も12bit固定小数点数のものにしてあるので、コンパイル時に外部ライブラリ(libmath.so)へのリンクは不要です。
int型のみなので、float型を使えない環境でも動くはずです。
四則演算もAInt32ですが、一部、数値範囲に余裕をもたせる為にAInt64への型変換を使用しています。
#include <acl.c> | |
void drawObj(); | |
void drawPoly(int j); | |
AInt32 sin_AInt32_12bit(const AInt32 x_12bit); | |
AInt32 cos_AInt32_12bit(const AInt32 x_12bit); | |
AInt32 vx[8], vy[8], vz[8], centerz4[6]; | |
AInt32 scx[8], scy[8]; | |
AInt8 squar[24] = { 0,4,6,2, 1,3,7,5, 0,2,3,1, 0,1,5,4, 4,5,7,6, 6,7,3,2 }; | |
AInt32 col[6] = { 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff, 0x00ffff }; | |
AWindow *win; | |
inline AInt32 mul_AInt32_12bit(const AInt32 x0_12bit, const AInt32 x1_12bit) | |
{ | |
return (AInt64)x0_12bit * (AInt64)x1_12bit >> 12; | |
} | |
inline AInt32 div_AInt32_12bit(const AInt32 x0_12bit, const AInt32 x1_12bit) | |
{ | |
return ((AInt64)x0_12bit << 12) / (AInt64)x1_12bit; | |
} | |
void aMain() | |
{ | |
win = aOpenWin(256, 160, "kcube_AInt64", 1); | |
const AInt32 one = 1 << 12; | |
static AInt32 vertx[8] = { 50*one, 50*one, 50*one, 50*one, -50*one, -50*one, -50*one, -50*one }; | |
static AInt32 verty[8] = { 50*one, 50*one, -50*one, -50*one, 50*one, 50*one, -50*one, -50*one }; | |
static AInt32 vertz[8] = { 50*one, -50*one, 50*one, -50*one, 50*one, -50*one, 50*one, -50*one }; | |
AInt32 thx = 0, thy = 0, thz = 0, i, l; | |
const AInt32 pi = 12868; | |
const AInt32 toRad = (pi << 12) / 0x8000; | |
for (;;) { | |
thx = (thx + 182) & 0xffff; | |
thy = (thy + 273) & 0xffff; | |
thz = (thz + 364) & 0xffff; | |
const AInt32 r_thx = mul_AInt32_12bit(thx, toRad); | |
const AInt32 r_thy = mul_AInt32_12bit(thy, toRad); | |
const AInt32 r_thz = mul_AInt32_12bit(thz, toRad); | |
const AInt32 xp = cos_AInt32_12bit(r_thx), xa = sin_AInt32_12bit(r_thx); | |
const AInt32 yp = cos_AInt32_12bit(r_thy), ya = sin_AInt32_12bit(r_thy); | |
const AInt32 zp = cos_AInt32_12bit(r_thz), za = sin_AInt32_12bit(r_thz); | |
for (i = 0; i < 8; i++) { | |
const AInt32 zt = mul_AInt32_12bit(vertz[i], xp) + mul_AInt32_12bit(verty[i], xa); | |
const AInt32 yt = mul_AInt32_12bit(verty[i], xp) - mul_AInt32_12bit(vertz[i], xa); | |
const AInt32 xt = mul_AInt32_12bit(vertx[i], yp) + mul_AInt32_12bit(zt, ya); | |
vz[i] = mul_AInt32_12bit(zt, yp) - mul_AInt32_12bit(vertx[i], ya); | |
vx[i] = mul_AInt32_12bit(xt, zp) - mul_AInt32_12bit(yt, za); | |
vy[i] = mul_AInt32_12bit(yt, zp) + mul_AInt32_12bit(xt, za); | |
} | |
l = 0; for (i = 0; i < 6; i++) { | |
centerz4[i] = vz[squar[l + 0]] + vz[squar[l + 1]] + vz[squar[l + 2]] + vz[squar[l + 3]] + (1024*one); | |
l += 4; | |
} | |
aFillRect0(win, 160, 160, 40, 0, 0x000000); | |
drawObj(); | |
aWait(50); | |
} | |
} | |
void drawObj() | |
{ | |
const AInt32 one = 1 << 12; | |
AInt8 i; | |
for (i = 0; i < 8; i++) { | |
AInt32 t = div_AInt32_12bit((300*one), (vz[i] + (400*one))); | |
scx[i] = mul_AInt32_12bit(vx[i], t) + (128*one); | |
scy[i] = mul_AInt32_12bit(vy[i], t) + (80*one); | |
} | |
for (;;) { | |
AInt32 max = 0.0; | |
int j = -1, k; | |
for (k = 0; k < 6; k++) { | |
if (max < centerz4[k]) { | |
max = centerz4[k]; | |
j = k; | |
} | |
} | |
if (j < 0) | |
break; | |
i = j * 4; | |
centerz4[j] = 0.0; | |
AInt32 e0x = vx[squar[i + 1]] - vx[squar[i + 0]]; | |
AInt32 e0y = vy[squar[i + 1]] - vy[squar[i + 0]]; | |
AInt32 e1x = vx[squar[i + 2]] - vx[squar[i + 1]]; | |
AInt32 e1y = vy[squar[i + 2]] - vy[squar[i + 1]]; | |
if (mul_AInt32_12bit(e0x, e1y) <= mul_AInt32_12bit(e0y, e1x)) | |
drawPoly(j); | |
} | |
} | |
void drawPoly(int j) | |
{ | |
int i = j * 4, i1 = i + 3; | |
int p0x = scx[squar[i1]] >> 12, p0y = scy[squar[i1]] >> 12, p1x, p1y; | |
int y, ymin = 0x7fffffff, ymax = 0, x, dx, y0, y1; | |
int *buf, buf0[160], buf1[160]; | |
int c = col[j]; | |
for (i = i; i <= i1; i++) { | |
p1x = scx[squar[i]] >> 12; | |
p1y = scy[squar[i]] >> 12; | |
if (ymin > p1y) | |
ymin = p1y; | |
if (ymax < p1y) | |
ymax = p1y; | |
if (p0y != p1y) { | |
if (p0y < p1y) { | |
buf = buf0; y0 = p0y; y1 = p1y; dx = p1x - p0x; x = p0x; | |
} else { | |
buf = buf1; y0 = p1y; y1 = p0y; dx = p0x - p1x; x = p1x; | |
} | |
x <<= 16; | |
dx = (dx << 16) / (y1 - y0); | |
if (dx >= 0) | |
x += 0x8000; | |
else | |
x -= 0x8000; | |
for (y = y0; y <= y1; y++) { | |
buf[y] = x >> 16; | |
x += dx; | |
} | |
} | |
p0x = p1x; | |
p0y = p1y; | |
} | |
for (y = ymin; y <= ymax; y++) { | |
p0x = buf0[y]; | |
p1x = buf1[y]; | |
if (p0x <= p1x) | |
aFillRect0(win, p1x - p0x + 1, 1, p0x, y, c); | |
else | |
aFillRect0(win, p0x - p1x + 1, 1, p1x, y, c); | |
} | |
} | |
static | |
AInt32 sin_AInt32_work_1(const AInt32 x_12bit) | |
{ | |
const AInt32 b = 12; | |
const AInt32 x1 = x_12bit; | |
const AInt32 x3 = (x1 * x1 >> b) * x1 >> b; | |
const AInt32 x5 = (x3 * x1 >> b) * x1 >> b; | |
const AInt32 x7 = (x5 * x1 >> b) * x1 >> b; | |
return x1 - x3 / 6 + x5 / 120 - x7 / 5040; | |
} | |
AInt32 sin_AInt32_12bit(const AInt32 x_12bit) | |
{ | |
const AInt32 pi = 12868; | |
const AInt32 pih = pi / 2; | |
const AInt32 pi2 = pi * 2; | |
const AInt32 x = (x_12bit >= 0) ? x_12bit % pi2 : pi2 - (-x_12bit % pi2); | |
if (x < pih) | |
return sin_AInt32_work_1(x); | |
else if (x < pi) | |
return sin_AInt32_work_1(pi - x); | |
else if (x < pi + pih) | |
return -sin_AInt32_work_1(x - pi); | |
else if (x < pi2) | |
return -sin_AInt32_work_1(pi2 - x); | |
// printf("error: sin_AInt32()\n"); | |
} | |
AInt32 cos_AInt32_12bit(const AInt32 x_12bit) | |
{ | |
const AInt32 pih = 6434; | |
return sin_AInt32_12bit(x_12bit + pih); | |
} |