Function ClearBuffers(Integer Array meta, Real Array colorbuffer, Real Array depthbuffer, Real Array color, Real depth) Declare Integer i For i = 0 to meta[2] - 1 Assign colorbuffer[i * 3] = color[0] Assign colorbuffer[i * 3 + 1] = color[1] Assign colorbuffer[i * 3 + 2] = color[2] Assign depthbuffer[i] = depth End End Function DegToRad(Real deg) Declare Real rad Assign rad = deg * 0.0174532925 Return Real rad Function Min(Real a, Real b) Declare Real r If a < b Assign r = a False: Assign r = b End Return Real r Function Min3(Real a, Real b, Real c) Declare Real r Assign r = Min(Min(a, b), c) Return Real r Function Max(Real a, Real b) Declare Real r If a > b Assign r = a False: Assign r = b End Return Real r Function Max3(Real a, Real b, Real c) Declare Real r Assign r = Max(Max(a, b), c) Return Real r Function IsOnRight(Real Array a, Real Array b, Real Array c) Declare Boolean r If (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]) <= 0 Assign r = true False: Assign r= false End Return Boolean r Function Distance2(Real Array a, Real Array b) Declare Real x, y, d Assign x = b[0] - a[0] Assign y = b[1] - a[1] Assign d = sqrt(x * x + y * y) Return Real d Function Normalize(Real Array a) Declare Real l Assign l = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]) Assign a[0] = a[0] / l Assign a[1] = a[1] / l Assign a[2] = a[2] / l End Function MapToRes(Integer Array meta, Real Array a) Assign a[0] = a[0] / a[3] Assign a[1] = a[1] / a[3] Assign a[2] = a[2] / a[3] Assign a[0] = (a[0] + 1.0) * 0.5 * (meta[0] - 1) Assign a[1] = (1.0 - a[1]) * 0.5 * (meta[1] - 1) End Function Cross(Real Array result, Real Array a, Real Array b) Assign result[0] = a[1] * b[2] - a[2] * b[1] Assign result[1] = a[2] * b[0] - a[0] * b[2] Assign result[2] = a[0] * b[1] - a[1] * b[0] End Function Dot(Real Array a, Real Array b) Declare Real result Assign result = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] Return Real result Function Dot2(Real Array a, Real Array b) Declare Real result Assign result = a[0] * b[0] + a[1] * b[1] Return Real result Function VecCopy3(Real Array result, Real Array a) Assign result[0] = a[0] Assign result[1] = a[1] Assign result[2] = a[2] End Function VecSubVec3(Real Array result, Real Array a, Real Array b) Assign result[0] = a[0] - b[0] Assign result[1] = a[1] - b[1] Assign result[2] = a[2] - b[2] End Function MatMultMat(Real Array result, Real Array a, Real Array b) Assign result[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12] Assign result[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13] Assign result[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14] Assign result[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15] Assign result[4] = a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12] Assign result[5] = a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13] Assign result[6] = a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14] Assign result[7] = a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15] Assign result[8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12] Assign result[9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13] Assign result[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14] Assign result[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15] Assign result[12] = a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12] Assign result[13] = a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13] Assign result[14] = a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14] Assign result[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15] End Function MatMultVec(Real Array result, Real Array a, Real Array v) Assign result[0] = a[0] * v[0] + a[1] * v[1] + a[2] * v[2] + a[3] * v[3] Assign result[1] = a[4] * v[0] + a[5] * v[1] + a[6] * v[2] + a[7] * v[3] Assign result[2] = a[8] * v[0] + a[9] * v[1] + a[10] * v[2] + a[11] * v[3] Assign result[3] = a[12] * v[0] + a[13] * v[1] + a[14] * v[2] + a[15] * v[3] End Function MatMultVec3(Real Array result, Real Array a, Real Array v) Assign result[0] = a[0] * v[0] + a[1] * v[1] + a[2] * v[2] + a[3] Assign result[1] = a[4] * v[0] + a[5] * v[1] + a[6] * v[2] + a[7] Assign result[2] = a[8] * v[0] + a[9] * v[1] + a[10] * v[2] + a[11] Assign result[3] = a[12] * v[0] + a[13] * v[1] + a[14] * v[2] + a[15] End Function LookAt(Real Array mat, Real Array campos, Real Array targetpos, Real Array upvec) Declare Real Array forward[3] Declare Real Array right[3] Declare Real Array up[3] Call VecSubVec3(forward, targetpos, campos) Call Normalize(forward) Call Cross(right, forward, upvec) Call Normalize(right) Call Cross(up, right, forward) Assign mat[0] = right[0] Assign mat[1] = right[1] Assign mat[2] = right[2] Assign mat[3] = -Dot(right, campos) Assign mat[4] = up[0] Assign mat[5] = up[1] Assign mat[6] = up[2] Assign mat[7] = -Dot(up, campos) Assign mat[8] = -forward[0] Assign mat[9] = -forward[1] Assign mat[10] = -forward[2] Assign mat[11] = Dot(forward, campos) Assign mat[12] = 0.0 Assign mat[13] = 0.0 Assign mat[14] = 0.0 Assign mat[15] = 1.0 End Function Perspective(Real Array mat, Real fov, Real aspectratio, Real near, Real far) Declare Real tanhalffovy Assign tanhalffovy = tan(fov * 0.5) Assign mat[0] = 1 / (aspectratio * tanhalffovy) Assign mat[1] = 0.0 Assign mat[2] = 0.0 Assign mat[3] = 0.0 Assign mat[4] = 0.0 Assign mat[5] = 1 / tanhalffovy Assign mat[6] = 0.0 Assign mat[7] = 0.0 Assign mat[8] = 0.0 Assign mat[9] = 0.0 Assign mat[10] = -(far + near) / (far - near) Assign mat[11] = -(2 * far * near) / (far - near) Assign mat[12] = 0.0 Assign mat[13] = 0.0 Assign mat[14] = -1.0 Assign mat[15] = 0.0 End Function DrawTriangle(Integer Array meta, Real Array colorbuffer, Real Array depthbuffer, Real Array wp0, Real Array wp1, Real Array wp2, Integer Array texture, Real Array c0, Real Array c1, Real Array c2, Real Array mvp, Real Array lightdir, Real Array n0, Real Array n1, Real Array n2) Declare Real Array p0[4] Declare Real Array p1[4] Declare Real Array p2[4] Call MatMultVec3(p0, mvp, wp0) Call MatMultVec3(p1, mvp, wp1) Call MatMultVec3(p2, mvp, wp2) If p0[3] != 0.0 && p1[3] != 0.0 && p2[3] != 0.0 Call MapToRes(meta, p0) Call MapToRes(meta, p1) Call MapToRes(meta, p2) Declare Real Array aabbmin[2] Declare Real Array aabbmax[2] Assign aabbmin[0] = Max(Min3(p0[0], p1[0], p2[0]), 0) Assign aabbmin[1] = Max(Min3(p0[1], p1[1], p2[1]), 0) Assign aabbmax[0] = Min(Max3(p0[0], p1[0], p2[0]), meta[0] - 1) Assign aabbmax[1] = Min(Max3(p0[1], p1[1], p2[1]), meta[1] - 1) Declare Integer x, y, idx, tx, ty, ti Declare Real Array p[2] Declare Real depth Declare Real w0, w1, w2, dot00, dot01, dot11, dot20, dot21, denom, d0, d1, d2 Declare Real Array v0[2] Declare Real Array v1[2] Declare Real Array v2[2] Declare Real Array texcoord[2] ... Output p0[2] ... Output p1[2] ... Output p2[2] Declare Real Array normal[3] Declare Real diff For x = aabbmin[0] to aabbmax[0] For y = aabbmin[1] to aabbmax[1] Assign p[0] = x Assign p[1] = y ... x >= 0 && x < meta[0] && y >= 0 && y < meta[1] && If IsOnRight(p0, p1, p) && IsOnRight(p1, p2, p) && IsOnRight(p2, p0, p) Assign v0[0] = p1[0] - p0[0] Assign v0[1] = p1[1] - p0[1] Assign v1[0] = p2[0] - p0[0] Assign v1[1] = p2[1] - p0[1] Assign v2[0] = p[0] - p0[0] Assign v2[1] = p[1] - p0[1] Assign dot00 = Dot2(v0, v0) Assign dot01 = Dot2(v0, v1) Assign dot11 = Dot2(v1, v1) Assign dot20 = Dot2(v2, v0) Assign dot21 = Dot2(v2, v1) Assign denom = dot00 * dot11 - dot01 * dot01 Assign w1 = (dot11 * dot20 - dot01 * dot21) / denom Assign w2 = (dot00 * dot21 - dot01 * dot20) / denom Assign w0 = 1.0 - w1 - w2 Assign depth = p0[2] * w0 + p1[2] * w1 + p2[2] * w2 Assign idx = x + meta[0] * y If depth > 0.0 && depthbuffer[idx] > depth Assign depthbuffer[idx] = depth Assign idx = idx * 3 Assign texcoord[0] = w0 * c0[0] + w1 * c1[0] + w2 * c2[0] Assign texcoord[1] = w0 * c0[1] + w1 * c1[1] + w2 * c2[1] Assign normal[0] = w0 * n0[0] + w1 * n1[0] + w2 * n2[0] Assign normal[1] = w0 * n0[1] + w1 * n1[1] + w2 * n2[1] Assign normal[2] = w0 * n0[2] + w1 * n1[2] + w2 * n2[2] Call Normalize(normal) Assign diff = Max(0.5, Dot(normal, lightdir)) Assign tx = texcoord[0] * meta[3] Assign ty = (1 - texcoord[1]) * meta[4] Assign ti = (tx + ty * meta[3]) * 3 Assign colorbuffer[idx] = texture[ti] / 255 * diff Assign colorbuffer[idx + 1] = texture[ti + 1] / 255 * diff Assign colorbuffer[idx + 2] = texture[ti + 2] / 255 * diff End End End End End End Function OutputPPM(Integer Array meta, Real Array colorbuffer) Output "P3" Output meta[0] & " " & meta[1] Output 255 Declare Integer i, numpixels Assign numpixels = meta[2] For i = 0 to (numpixels - 1) * 3 step 3 Output Int(colorbuffer[i] * 255) & " " ... Output Int(colorbuffer[i + 1] * 255) & " " ... Output Int(colorbuffer[i + 2] * 255) & " " ... End End Function OutputVT100(Integer Array meta, Real Array colorbuffer) Output ToChar(27)&"[1;1H" Declare Integer r1, g1, b1, r2, b2, g2, x, y, width, height, idx, rowoffset ... Assign iterations = (meta[2] / 2 - 1) * 3 Assign width = meta[0] Assign height = meta[1] For y = 0 to height - 2 step 2 Output "" For x = 0 to width - 1 Assign idx = (x + y * width) * 3 Assign rowoffset = width * 3 Assign r1 = colorbuffer[idx] * 255 Assign g1 = colorbuffer[idx + 1] * 255 Assign b1 = colorbuffer[idx + 2] * 255 Assign r2 = colorbuffer[idx + rowoffset] * 255 Assign g2 = colorbuffer[idx + 1 + rowoffset] * 255 Assign b2 = colorbuffer[idx + 2 + rowoffset] * 255 Output ToChar(27) & "[38;2;" & r1 & ";" & g1 & ";" & b1 & "m" & ToChar(27) & "[48;2;" & r2 &";" & g2 & ";" & b2 & "m" & "▀" ... End End End Function DumpMat(Real Array mat) Declare Integer i For i = 0 to 15 Output mat[i] & " " If i % 4 == 3 Output "" End End End Function Main Declare Integer Array meta[5] Assign meta[0] = 175 Assign meta[1] = 120 ... Assign meta[0] = 1280 ... Assign meta[1] = 720 Assign meta[2] = meta[0] * meta[1] Declare Real Array depthbuffer[meta[2]] Declare Real Array colorbuffer[meta[2] * 3] Declare Real Array background[3] Assign background[0] = 0.3 Assign background[1] = 0.3 Assign background[2] = 0.3 Call ClearBuffers(meta, colorbuffer, depthbuffer, background, 100.0) Declare Real Array lightdir[3] Assign lightdir[0] = .3 Assign lightdir[1] = 1 Assign lightdir[2] = .4 Call Normalize(lightdir) Declare Real Array view[16] Declare Real Array proj[16] Declare Real Array mvp[16] Declare Real Array campos[3] Declare Real Array targetpos[3] Declare Real Array upvector[3] Assign targetpos[0] = 0 Assign targetpos[1] = 0 Assign targetpos[2] = 0 Assign upvector[0] = 0 Assign upvector[1] = 1 Assign upvector[2] = 0 ... Call DumpMat(view) Declare Real aspectratio Assign aspectratio = 1.46 ... meta[0] / meta[1] Call Perspective(proj, DegToRad(90.0) / aspectratio, aspectratio, 0.1, 50.0) Declare Real Array p0[3] Declare Real Array p1[3] Declare Real Array p2[3] Declare Real Array c0[2] Declare Real Array c1[2] Declare Real Array c2[2] Declare Real Array n0[3] Declare Real Array n1[3] Declare Real Array n2[3] Declare Integer datasize, i, vertices Input datasize Input vertices Declare Real Array data[datasize] For i = 0 to datasize - 1 Input data[i] End Output "model rdy" Input meta[3] Input meta[4] Declare Integer tp Assign tp = meta[3] * meta[4] * 3 Declare Integer Array texture[tp] For i = 0 to tp - 1 Input texture[i] End Output "textura rdy" Declare Integer temp Declare Integer i0, i1, i2 Declare Real camangle Assign camangle = 0 While true Call ClearBuffers(meta, colorbuffer, depthbuffer, background, 100.0) Declare Real camdis Assign camdis = 7.0 Assign campos[0] = sin(camangle) * camdis Assign campos[1] = 0.8 * camdis ... 10 * camdis Assign campos[2] = cos(camangle) * camdis Assign camangle = camangle + pi / 5 Call LookAt(view, campos, targetpos, upvector) Call MatMultMat(mvp, proj, view) For i = 0 to vertices - 3 step 3 ... For temp = 0 to vertices - 3 step 3 ... Assign i = vertices - 3 - temp Assign i0 = i * 8 Assign i1 = (i + 1) * 8 Assign i2 = (i + 2) * 8 Assign p0[0] = data[i0] Assign p0[1] = data[i0 + 1] Assign p0[2] = data[i0 + 2] Assign p1[0] = data[i1] Assign p1[1] = data[i1 + 1] Assign p1[2] = data[i1 + 2] Assign p2[0] = data[i2] Assign p2[1] = data[i2 + 1] Assign p2[2] = data[i2 + 2] ... Assign c0[0] = data[i * 8 + 5] * 0.5 + 0.5 ... Assign c0[1] = data[i * 8 + 6] * 0.5 + 0.5 ... Assign c0[2] = data[i * 8 + 7] * 0.5 + 0.5 Assign c0[0] = data[i0 + 3] Assign c0[1] = data[i0 + 4] Assign c1[0] = data[i1 + 3] Assign c1[1] = data[i1 + 4] Assign c2[0] = data[i2 + 3] Assign c2[1] = data[i2 + 4] Assign n0[0] = data[i0 + 5] Assign n0[1] = data[i0 + 6] Assign n0[2] = data[i0 + 7] Assign n1[0] = data[i1 + 5] Assign n1[1] = data[i1 + 6] Assign n1[2] = data[i1 + 7] Assign n2[0] = data[i2 + 5] Assign n2[1] = data[i2 + 6] Assign n2[2] = data[i2 + 7] Call DrawTriangle(meta, colorbuffer, depthbuffer, p0, p1, p2, texture, c0, c1, c2, mvp, lightdir, n0, n1, n2) ... Output i End ... Call OutputPPM(meta, colorbuffer) Call OutputVT100(meta, colorbuffer) End End