Skip to content

Instantly share code, notes, and snippets.

@takeutch-kemeco
Last active September 22, 2020 03:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takeutch-kemeco/94c0acf3ee78bce6543240f120c61176 to your computer and use it in GitHub Desktop.
Save takeutch-kemeco/94c0acf3ee78bce6543240f120c61176 to your computer and use it in GitHub Desktop.
aclのkcube.cの12ビット固定小数点数版

kcube_int.c

これは何?

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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment