701 lines
16 KiB
C
701 lines
16 KiB
C
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <dos.h>
|
|
#include <i86.h>
|
|
#include <conio.h>
|
|
#include <string.h>
|
|
|
|
struct Context
|
|
{
|
|
int width, height;
|
|
int tex_w, tex_h;
|
|
uint8_t *backbuffer;
|
|
uint8_t *colorbuffer;
|
|
float *depthbuffer;
|
|
uint8_t *texture;
|
|
float lightdir[3];
|
|
};
|
|
|
|
static uint8_t *vga = (uint8_t *)0xA0000;
|
|
|
|
static const uint8_t bayer8x8[] = {
|
|
0, 32, 8, 40, 2, 34, 10, 42,
|
|
48, 16, 56, 24, 50, 18, 58, 26,
|
|
12, 44, 4, 36, 14, 46, 6, 38,
|
|
60, 28, 52, 20, 62, 30, 54, 22,
|
|
3, 35, 11, 43, 1, 33, 9, 41,
|
|
51, 19, 59, 27, 49, 17, 57, 25,
|
|
15, 47, 7, 39, 13, 45, 5, 37,
|
|
63, 31, 55, 23, 61, 29, 53, 21
|
|
};
|
|
|
|
static void SetMode(unsigned char mode) {
|
|
union REGS regs;
|
|
regs.w.ax = mode;
|
|
int386(0x10, ®s, ®s);
|
|
}
|
|
|
|
static void SetPalette(int i, unsigned char r, unsigned char g, unsigned char b) {
|
|
outp(0x3C8, i);
|
|
outp(0x3C9, r);
|
|
outp(0x3C9, g);
|
|
outp(0x3C9, b);
|
|
}
|
|
|
|
static void InitPalette(void)
|
|
{
|
|
int i, r, g, b;
|
|
|
|
for (i = 0; i < 256; ++i)
|
|
{
|
|
r = (i >> 6) & 3;
|
|
r = (r << 4) | (r << 2) | r;
|
|
|
|
g = (i >> 3) & 7;
|
|
g = (g << 3) | g;
|
|
|
|
b = i & 7;
|
|
b = (b << 3) | b;
|
|
|
|
/* RRGGGBBB */
|
|
// SetPalette(i, (((i >> 6) & 3) << 4) | 15, (((i >> 3) & 7) << 3) | 7, ((i & 7) << 3) | 7);
|
|
SetPalette(i, r, g, b);
|
|
}
|
|
}
|
|
|
|
static void SetPixel(struct Context *ctx, int x, int y, float c[])
|
|
{
|
|
int r, g, b;
|
|
uint8_t color;
|
|
uint8_t bayerval;
|
|
|
|
r = c[0] * (4 * 64);
|
|
g = c[1] * (8 * 64);
|
|
b = c[2] * (8 * 64);
|
|
|
|
bayerval = bayer8x8[(x & 7) + (y & 7) * 8];
|
|
r += bayerval;
|
|
g += bayerval;
|
|
b += bayerval;
|
|
|
|
r >>= 6;
|
|
g >>= 6;
|
|
b >>= 6;
|
|
|
|
if (r > 3) r = 3;
|
|
if (g > 7) g = 7;
|
|
if (b > 7) b = 7;
|
|
|
|
color = (r << 6) | (g << 3) | b;
|
|
ctx->colorbuffer[x + y * 320] = color;
|
|
}
|
|
|
|
static void ClearDepth(struct Context *ctx, float depth)
|
|
{
|
|
int i;
|
|
int pixels = ctx->width * ctx->height;
|
|
|
|
for (i = 0; i < pixels; ++i)
|
|
{
|
|
ctx->depthbuffer[i] = depth;
|
|
}
|
|
}
|
|
|
|
static float DegToRad(float deg)
|
|
{
|
|
return deg * 0.0174532925f;
|
|
}
|
|
|
|
static float Min(float a, float b)
|
|
{
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
static float Min3(float a, float b, float c)
|
|
{
|
|
return Min(Min(a, b), c);
|
|
}
|
|
|
|
static float Max(float a, float b)
|
|
{
|
|
return a > b ? a : b;
|
|
}
|
|
|
|
static float Max3(float a, float b, float c)
|
|
{
|
|
return Max(Max(a, b), c);
|
|
}
|
|
|
|
static int IsOnRight(float a[], float b[], float c[])
|
|
{
|
|
return ((b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]) <= 0.0f);
|
|
}
|
|
|
|
static float Distance2(float a[], float b[])
|
|
{
|
|
float x, y, d;
|
|
x = b[0] - a[0];
|
|
y = b[1] - a[1];
|
|
return sqrt(x * x + y * y);
|
|
}
|
|
|
|
static void Normalize(float a[])
|
|
{
|
|
float l = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
|
a[0] = a[0] / l;
|
|
a[1] = a[1] / l;
|
|
a[2] = a[2] / l;
|
|
}
|
|
|
|
static void MapToRes(struct Context *ctx, float a[])
|
|
{
|
|
a[0] = a[0] / a[3];
|
|
a[1] = a[1] / a[3];
|
|
a[2] = a[2] / a[3];
|
|
|
|
a[0] = (a[0] + 1.0f) * 0.5f * (ctx->width - 1);
|
|
a[1] = (1.0f - a[1]) * 0.5f * (ctx->height - 1);
|
|
}
|
|
|
|
static void Cross(float result[], float a[], float b[])
|
|
{
|
|
result[0] = a[1] * b[2] - a[2] * b[1];
|
|
result[1] = a[2] * b[0] - a[0] * b[2];
|
|
result[2] = a[0] * b[1] - a[1] * b[0];
|
|
}
|
|
|
|
static float Dot(float a[], float b[])
|
|
{
|
|
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
}
|
|
|
|
static float Dot2(float a[], float b[])
|
|
{
|
|
return a[0] * b[0] + a[1] * b[1];
|
|
}
|
|
|
|
static void VecCopy3(float result[], float a[])
|
|
{
|
|
result[0] = a[0];
|
|
result[1] = a[1];
|
|
result[2] = a[2];
|
|
}
|
|
|
|
static void VecSubVec3(float result[], float a[], float b[])
|
|
{
|
|
result[0] = a[0] - b[0];
|
|
result[1] = a[1] - b[1];
|
|
result[2] = a[2] - b[2];
|
|
};
|
|
|
|
static void MatMultMat(float result[], float a[], float b[])
|
|
{
|
|
result[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12];
|
|
result[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13];
|
|
result[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14];
|
|
result[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15];
|
|
result[4] = a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12];
|
|
result[5] = a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13];
|
|
result[6] = a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14];
|
|
result[7] = a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15];
|
|
result[8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12];
|
|
result[9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13];
|
|
result[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14];
|
|
result[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15];
|
|
result[12] = a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12];
|
|
result[13] = a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13];
|
|
result[14] = a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14];
|
|
result[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15];
|
|
}
|
|
|
|
static void MatMultVec(float result[], float a[], float v[])
|
|
{
|
|
result[0] = a[0] * v[0] + a[1] * v[1] + a[2] * v[2] + a[3] * v[3];
|
|
result[1] = a[4] * v[0] + a[5] * v[1] + a[6] * v[2] + a[7] * v[3];
|
|
result[2] = a[8] * v[0] + a[9] * v[1] + a[10] * v[2] + a[11] * v[3];
|
|
result[3] = a[12] * v[0] + a[13] * v[1] + a[14] * v[2] + a[15] * v[3];
|
|
}
|
|
|
|
static void MatMultVec3(float result[], float a[], float v[])
|
|
{
|
|
result[0] = a[0] * v[0] + a[1] * v[1] + a[2] * v[2] + a[3];
|
|
result[1] = a[4] * v[0] + a[5] * v[1] + a[6] * v[2] + a[7];
|
|
result[2] = a[8] * v[0] + a[9] * v[1] + a[10] * v[2] + a[11];
|
|
result[3] = a[12] * v[0] + a[13] * v[1] + a[14] * v[2] + a[15];
|
|
}
|
|
|
|
static void LookAt(float mat[], float campos[], float targetpos[], float upvec[])
|
|
{
|
|
float forward[3];
|
|
float right[3];
|
|
float up[3];
|
|
|
|
VecSubVec3(forward, targetpos, campos);
|
|
Normalize(forward);
|
|
|
|
Cross(right, forward, upvec);
|
|
Normalize(right);
|
|
|
|
Cross(up, right, forward);
|
|
|
|
mat[0] = right[0];
|
|
mat[1] = right[1];
|
|
mat[2] = right[2];
|
|
mat[3] = -Dot(right, campos);
|
|
mat[4] = up[0];
|
|
mat[5] = up[1];
|
|
mat[6] = up[2];
|
|
mat[7] = -Dot(up, campos);
|
|
mat[8] = -forward[0];
|
|
mat[9] = -forward[1];
|
|
mat[10] = -forward[2];
|
|
mat[11] = Dot(forward, campos);
|
|
mat[12] = 0.0f;
|
|
mat[13] = 0.0f;
|
|
mat[14] = 0.0f;
|
|
mat[15] = 1.0f;
|
|
}
|
|
|
|
static void Perspective(float mat[], float fov, float aspectratio, float nearp, float farp)
|
|
{
|
|
float tanhalffovy = tan(fov * 0.5f);
|
|
|
|
mat[0] = 1.0f / (aspectratio * tanhalffovy);
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 0.0f;
|
|
mat[4] = 0.0f;
|
|
mat[5] = 1.0f / tanhalffovy;
|
|
mat[6] = 0.0f;
|
|
mat[7] = 0.0f;
|
|
mat[8] = 0.0f;
|
|
mat[9] = 0.0f;
|
|
mat[10] = -(farp + nearp) / (farp - nearp);
|
|
mat[11] = -(2 * farp * nearp) / (farp - nearp) ;
|
|
mat[12] = 0.0f;
|
|
mat[13] = 0.0f;
|
|
mat[14] = -1.0f;
|
|
mat[15] = 0.0f;
|
|
}
|
|
|
|
struct ScrVertex
|
|
{
|
|
float x, y;
|
|
float t[2];
|
|
float n[3];
|
|
float depth;
|
|
};
|
|
|
|
static void FillScanLine(struct Context *ctx, const struct ScrVertex *v0, const struct ScrVertex *v1)
|
|
{
|
|
int x, y, start, end, t0x, t0y, t1x, t1y, tx, ty;
|
|
float c[3], n[3], depth, *depthbuf, xdiff, depthdiff, tdiff[2], ndiff[3], diffuse;
|
|
uint8_t *texel;
|
|
|
|
|
|
start = v0->x;
|
|
if (start < 0)
|
|
start = 0;
|
|
|
|
end = v1->x;
|
|
if (end > ctx->width)
|
|
end = ctx->width;
|
|
|
|
y = v0->y;
|
|
|
|
xdiff = v1->x - v0->x;
|
|
depthdiff = v1->depth - v0->depth;
|
|
tdiff[0] = v1->t[0] - v0->t[0];
|
|
tdiff[1] = v1->t[1] - v0->t[1];
|
|
|
|
ndiff[0] = v1->n[0] - v0->n[0];
|
|
ndiff[1] = v1->n[1] - v0->n[1];
|
|
ndiff[2] = v1->n[2] - v0->n[2];
|
|
|
|
|
|
for (x = start; x < end; ++x)
|
|
{
|
|
float t = ((float)x - v0->x) / xdiff;
|
|
depth = v0->depth + t * depthdiff;
|
|
|
|
depthbuf = &ctx->depthbuffer[x + y * ctx->width];
|
|
if (*depthbuf < depth)
|
|
continue;
|
|
|
|
*depthbuf = depth;
|
|
|
|
tx = (v0->t[0] + t * tdiff[0]) * ctx->tex_w;
|
|
ty = (1.0f - (v0->t[1] + t * tdiff[1])) * ctx->tex_h;
|
|
|
|
if (tx < 0)
|
|
tx = 0;
|
|
else if (tx >= ctx->width)
|
|
tx = ctx->width - 1;
|
|
|
|
if (ty < 0)
|
|
ty = 0;
|
|
else if (ty >= ctx->height)
|
|
ty = ctx->height - 1;
|
|
|
|
n[0] = v0->n[0] + t * ndiff[0];
|
|
n[1] = v0->n[1] + t * ndiff[1];
|
|
n[2] = v0->n[2] + t * ndiff[2];
|
|
|
|
Normalize(n);
|
|
diffuse = Max(0.5, Dot(n, ctx->lightdir));
|
|
|
|
texel = &ctx->texture[(tx + ty * ctx->tex_w) * 3];
|
|
c[0] = texel[0] / 255.0f * diffuse;
|
|
c[1] = texel[1] / 255.0f * diffuse;
|
|
c[2] = texel[2] / 255.0f * diffuse;
|
|
|
|
SetPixel(ctx, x, y, c);
|
|
}
|
|
}
|
|
|
|
static void SortByY(struct ScrVertex** s)
|
|
{
|
|
struct ScrVertex* temp;
|
|
|
|
if (s[0]->y > s[1]->y)
|
|
{
|
|
temp = s[0];
|
|
s[0] = s[1];
|
|
s[1] = temp;
|
|
}
|
|
|
|
if (s[1]->y > s[2]->y)
|
|
{
|
|
temp = s[1];
|
|
s[1] = s[2];
|
|
s[2] = temp;
|
|
}
|
|
|
|
if (s[0]->y > s[1]->y)
|
|
{
|
|
temp = s[0];
|
|
s[0] = s[1];
|
|
s[1] = temp;
|
|
}
|
|
}
|
|
|
|
static void DebugDrawPoint(struct Context *ctx, int x, int y)
|
|
{
|
|
float c[] = { 1.0f, 0.0f, 0.0f };
|
|
|
|
if (x < 0 || x >= ctx->width || y < 0 || y >= ctx->height)
|
|
return;
|
|
|
|
SetPixel(ctx, x, y, c);
|
|
}
|
|
|
|
static void LerpScrVertex(const struct ScrVertex *a, const struct ScrVertex *b, struct ScrVertex *res, float t)
|
|
{
|
|
res->x = a->x + (b->x - a->x) * t;
|
|
res->y = a->y + (b->y - a->y) * t;
|
|
res->t[0] = a->t[0] + (b->t[0] - a->t[0]) * t;
|
|
res->t[1] = a->t[1] + (b->t[1] - a->t[1]) * t;
|
|
res->n[0] = a->n[0] + (b->n[0] - a->n[0]) * t;
|
|
res->n[1] = a->n[1] + (b->n[1] - a->n[1]) * t;
|
|
res->n[2] = a->n[2] + (b->n[2] - a->n[2]) * t;
|
|
res->depth = a->depth + (b->depth - a->depth) * t;
|
|
}
|
|
|
|
static void DrawTriangle(struct Context *ctx, float wp0[], float wp1[], float wp2[], float c0[], float c1[], float c2[], float mvp[], float n0[], float n1[], float n2[])
|
|
{
|
|
float p[3][4];
|
|
struct ScrVertex v[3], nv, *s[4], *tempv;
|
|
int i;
|
|
float nf;
|
|
|
|
MatMultVec3(p[0], mvp, wp0);
|
|
MatMultVec3(p[1], mvp, wp1);
|
|
MatMultVec3(p[2], mvp, wp2);
|
|
|
|
for (i = 0; i < 3; ++i)
|
|
{
|
|
if (p[i][3] == 0.0f)
|
|
return;
|
|
|
|
MapToRes(ctx, p[i]);
|
|
|
|
v[i].x = p[i][0];
|
|
v[i].y = p[i][1];
|
|
v[i].depth = p[i][2];
|
|
}
|
|
|
|
v[0].t[0] = c0[0];
|
|
v[0].t[1] = c0[1];
|
|
|
|
v[1].t[0] = c1[0];
|
|
v[1].t[1] = c1[1];
|
|
|
|
v[2].t[0] = c2[0];
|
|
v[2].t[1] = c2[1];
|
|
|
|
v[0].n[0] = n0[0];
|
|
v[0].n[1] = n0[1];
|
|
v[0].n[2] = n0[2];
|
|
|
|
v[1].n[0] = n1[0];
|
|
v[1].n[1] = n1[1];
|
|
v[1].n[2] = n1[2];
|
|
|
|
v[2].n[0] = n2[0];
|
|
v[2].n[1] = n2[1];
|
|
v[2].n[2] = n2[2];
|
|
|
|
if (IsOnRight(p[0], p[2], p[1]))
|
|
return; /* backface cull */
|
|
|
|
s[0] = &v[0];
|
|
s[1] = &v[1];
|
|
s[2] = &v[2];
|
|
s[3] = &nv;
|
|
SortByY(s);
|
|
|
|
nf = (s[1]->y - s[0]->y) / (s[2]->y - s[0]->y);
|
|
LerpScrVertex(s[0], s[2], &nv, nf);
|
|
nv.y = s[1]->y;
|
|
|
|
if (s[3]->x < s[1]->x)
|
|
{
|
|
tempv = s[1];
|
|
s[1] = s[3];
|
|
s[3] = tempv;
|
|
}
|
|
|
|
// for (i = 0; i < 4; ++i)
|
|
// {
|
|
// DebugDrawPoint(ctx, s[i]->x, s[i]->y);
|
|
// }
|
|
|
|
if (s[0]->y != s[1]->y)
|
|
{
|
|
int start, end, sc_y;
|
|
|
|
start = s[0]->y;
|
|
if (start < 0)
|
|
start = 0;
|
|
|
|
end = s[1]->y + 1;
|
|
if (end > ctx->height)
|
|
end = ctx->height;
|
|
|
|
for (sc_y = start; sc_y < end; sc_y++)
|
|
{
|
|
struct ScrVertex scv[2];
|
|
float t = ((float)sc_y - s[0]->y) / (s[1]->y - s[0]->y);
|
|
|
|
LerpScrVertex(s[0], s[1], &scv[0], t);
|
|
LerpScrVertex(s[0], s[3], &scv[1], t);
|
|
|
|
scv[0].y = sc_y;
|
|
FillScanLine(ctx, &scv[0], &scv[1]);
|
|
}
|
|
}
|
|
|
|
if (s[1]->y != s[2]->y)
|
|
{
|
|
int start, end, sc_y;
|
|
|
|
start = s[3]->y + 1;
|
|
if (start < 0)
|
|
start = 0;
|
|
|
|
end = s[2]->y + 1;
|
|
if (end > ctx->height)
|
|
end = ctx->height;
|
|
|
|
for (sc_y = start; sc_y < end; sc_y++)
|
|
{
|
|
struct ScrVertex scv[2];
|
|
float t = ((float)sc_y - s[3]->y) / (s[2]->y - s[3]->y);
|
|
|
|
LerpScrVertex(s[1], s[2], &scv[0], t);
|
|
LerpScrVertex(s[3], s[2], &scv[1], t);
|
|
|
|
scv[0].y = sc_y;
|
|
FillScanLine(ctx, &scv[0], &scv[1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void OutputVGA(const struct Context *ctx)
|
|
{
|
|
if (ctx->colorbuffer != vga)
|
|
memcpy(vga, ctx->colorbuffer, 320 * 200);
|
|
}
|
|
|
|
static void *MyMalloc(size_t n)
|
|
{
|
|
void *mem = malloc(n);
|
|
if (!mem)
|
|
{
|
|
fprintf(stderr, "cannot alloc %d bytes!\n", (int)n);
|
|
exit(1);
|
|
}
|
|
|
|
return mem;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct Context ctx;
|
|
|
|
float view[16];
|
|
float proj[16];
|
|
float mvp[16];
|
|
|
|
float campos[3];
|
|
float targetpos[] = { 0.0f, 0.0f, 0.0f };
|
|
float upvector[] = { 0.0f, 1.0f, 0.0f };
|
|
|
|
float aspectratio = 1.3f;
|
|
|
|
float p0[3], p1[3], p2[3];
|
|
float c0[3], c1[3], c2[3];
|
|
float n0[3], n1[3], n2[3];
|
|
|
|
int datasize, i, vertices, tp;
|
|
float *data;
|
|
|
|
int temp, i0, i1, i2;
|
|
float camangle;
|
|
|
|
FILE *in = stdin;
|
|
FILE *out = stdout;
|
|
|
|
if (argc > 1)
|
|
{
|
|
in = fopen(argv[1], "r");
|
|
if (!in)
|
|
{
|
|
fprintf(stderr, "cannot open for reading: %s\n", argv[1]);
|
|
exit(2);
|
|
}
|
|
}
|
|
|
|
if (argc > 2)
|
|
{
|
|
out = fopen(argv[2], "w");
|
|
if (!out)
|
|
{
|
|
fprintf(stderr, "cannot open for writing: %s\n", argv[2]);
|
|
exit(2);
|
|
}
|
|
}
|
|
|
|
ctx.width = 320;
|
|
ctx.height = 200;
|
|
|
|
ctx.backbuffer = MyMalloc(320 * 240);
|
|
ctx.depthbuffer = MyMalloc(sizeof(float) * ctx.width * ctx.height);
|
|
|
|
ctx.colorbuffer = ctx.backbuffer;
|
|
|
|
ctx.lightdir[0] = 0.3f;
|
|
ctx.lightdir[1] = 1.0f;
|
|
ctx.lightdir[2] = 0.4f;
|
|
Normalize(ctx.lightdir);
|
|
|
|
Perspective(proj, DegToRad(90.0f) / aspectratio, aspectratio, 0.1f, 50.0f);
|
|
|
|
fscanf(in, "%d\n%d\n", &datasize, &vertices);
|
|
data = MyMalloc(sizeof(float) * datasize);
|
|
|
|
for (i = 0; i < datasize; ++i)
|
|
{
|
|
fscanf(in, "%f\n", &data[i]);
|
|
}
|
|
|
|
fprintf(stderr, "model rdy\n");
|
|
|
|
fscanf(in, "%d\n%d\n", &ctx.tex_w, &ctx.tex_h);
|
|
tp = ctx.tex_w * ctx.tex_h * 3;
|
|
|
|
ctx.texture = MyMalloc(tp);
|
|
|
|
for (i = 0; i < tp; ++i)
|
|
{
|
|
int v;
|
|
fscanf(in, "%d\n", &v);
|
|
ctx.texture[i] = v;
|
|
}
|
|
|
|
fprintf(stderr, "textura rdy\n");
|
|
|
|
camangle = 0.0f;
|
|
|
|
SetMode(0x13);
|
|
InitPalette();
|
|
|
|
for (;;)
|
|
{
|
|
const float camdis = 7.0f;
|
|
|
|
ClearDepth(&ctx, 100.0);
|
|
memset(ctx.colorbuffer, 82, 320*200);
|
|
|
|
campos[0] = sin(camangle) * camdis;
|
|
campos[1] = 0.8f * camdis;
|
|
campos[2] = cos(camangle) * camdis;
|
|
|
|
camangle = camangle + 3.14f * 0.005f;
|
|
|
|
LookAt(view, campos, targetpos, upvector);
|
|
MatMultMat(mvp, proj, view);
|
|
|
|
|
|
for (i = 0; i < vertices; i += 3)
|
|
{
|
|
i0 = i * 8;
|
|
i1 = (i + 1) * 8;
|
|
i2 = (i + 2) * 8;
|
|
|
|
p0[0] = data[i0];
|
|
p0[1] = data[i0 + 1];
|
|
p0[2] = data[i0 + 2];
|
|
|
|
p1[0] = data[i1];
|
|
p1[1] = data[i1 + 1];
|
|
p1[2] = data[i1 + 2];
|
|
|
|
p2[0] = data[i2];
|
|
p2[1] = data[i2 + 1];
|
|
p2[2] = data[i2 + 2];
|
|
|
|
c0[0] = data[i0 + 3];
|
|
c0[1] = data[i0 + 4];
|
|
|
|
c1[0] = data[i1 + 3];
|
|
c1[1] = data[i1 + 4];
|
|
|
|
c2[0] = data[i2 + 3];
|
|
c2[1] = data[i2 + 4];
|
|
|
|
n0[0] = data[i0 + 5];
|
|
n0[1] = data[i0 + 6];
|
|
n0[2] = data[i0 + 7];
|
|
|
|
n1[0] = data[i1 + 5];
|
|
n1[1] = data[i1 + 6];
|
|
n1[2] = data[i1 + 7];
|
|
|
|
n2[0] = data[i2 + 5];
|
|
n2[1] = data[i2 + 6];
|
|
n2[2] = data[i2 + 7];
|
|
|
|
DrawTriangle(&ctx, p0, p1, p2, c0, c1, c2, mvp, n0, n1, n2);
|
|
}
|
|
|
|
OutputVGA(&ctx);
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|