00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdlib.h>
00041 #include <math.h>
00042 #include "line.h"
00043 #include "3d.h"
00044
00045 int *tcos, *tsin;
00046
00047 void create_lookup_tables() {
00048 double M_PI = 8.0 * atan(1.0);
00049
00050 int c;
00051 double a;
00052
00053 tcos = newa(int, 256);
00054 tsin = newa(int, 256);
00055
00056 for (c = 0; c < 256; c++) {
00057 a = M_PI * c / 128;
00058 tcos[c] = (int)(cos(a) * 64);
00059 tsin[c] = (int)(sin(a) * 64);
00060 }
00061 }
00062
00063 void destroy_lookup_tables() {
00064 free(tcos);
00065 free(tsin);
00066 }
00067
00068 mesh_t* mesh_new(int pcount, int tcount) {
00069 mesh_t* r = new(mesh_t);
00070 r->pcount = pcount;
00071 r->tcount = tcount;
00072 r->points = newa(vector_t, pcount);
00073 r->triangles = newa(triangle_t, tcount);
00074 return r;
00075 }
00076
00077 void mesh_delete(mesh_t* mesh) {
00078 free(mesh->points);
00079 free(mesh->triangles);
00080 free(mesh);
00081 }
00082
00083 void vector_cross_product (vector_t* v1, vector_t* v2, vector_t* r) {
00084 int x, y, z;
00085 x = mulfx(v1->y, v2->z) - mulfx(v1->z, v2->y);
00086 y = mulfx(v1->z, v2->x) - mulfx(v1->x, v2->z);
00087 z = mulfx(v1->x, v2->y) - mulfx(v1->y, v2->x);
00088 r->x = x; r->y = y; r->z = z;
00089 }
00090
00091 int vector_cross_product_z (vector_t* v1, vector_t* v2) {
00092 return mulfx(v1->x, v2->y) - mulfx(v1->y, v2->x);
00093 }
00094
00095 int vector_dot_product (vector_t* v1, vector_t* v2) {
00096 return mulfx(v1->x, v2->x) + mulfx(v1->y, v2->y) + mulfx(v1->z, v2->z);
00097 }
00098
00099 int vector_length_squared (vector_t *v) {
00100 return sqrfx(v->x) + sqrfx(v->y) + sqrfx(v->z);
00101 }
00102
00103 int vector_length(vector_t *v) {
00104 return sqrtfx(vector_length_squared(v));
00105 }
00106
00107 void vector_normalize(vector_t *p, vector_t *r) {
00108 int d = vector_length(p);
00109 if (d != 0) {
00110 r->x = divfx(p->x, d);
00111 r->y = divfx(p->y, d);
00112 r->z = divfx(p->z, d);
00113 }
00114 }
00115
00116 void vector_scalar(vector_t *v, int s, vector_t* r) {
00117 r->x = mulfx(v->x, s);
00118 r->y = mulfx(v->y, s);
00119 r->z = mulfx(v->z, s);
00120 }
00121
00122 void vector_add(vector_t *v1, vector_t *v2, vector_t *r) {
00123 r->x = v1->x + v2->x;
00124 r->y = v1->y + v2->y;
00125 r->z = v1->z + v2->z;
00126 }
00127
00128 void vector_subtract (vector_t *v1, vector_t *v2, vector_t *r) {
00129 r->x = v1->x - v2->x;
00130 r->y = v1->y - v2->y;
00131 r->z = v1->z - v2->z;
00132 }
00133
00134 int vector_distance (vector_t *v1, vector_t *v2) {
00135 vector_t r;
00136 vector_subtract(v1, v2, &r);
00137 return vector_length(&r);
00138 }
00139
00140 void vector_rotate(vector_t* p, u_char angle_x, u_char angle_y, u_char angle_z, vector_t* r) {
00141 int x, y, z;
00142 int ca, sa;
00143
00144
00145 ca = tcos[angle_z]; sa = tsin[angle_z];
00146 x = p->x; y = p->y; z = p->z;
00147 r->x = (mulfx(ca, x) - mulfx(sa, y));
00148 r->y = (mulfx(sa, x) + mulfx(ca, y));
00149 r->z = z;
00150
00151
00152 ca = tcos[angle_y]; sa = tsin[angle_y];
00153 x = r->x; y = r->y; z = r->z;
00154 r->x = (mulfx(ca, x) - mulfx(sa, z));
00155 r->z = (mulfx(sa, x) + mulfx(ca, z));
00156
00157
00158 ca = tcos[angle_x]; sa = tsin[angle_x];
00159 x = r->x; y = r->y; z = r->z;
00160 r->y = (mulfx(ca, y) - mulfx(sa, z));
00161 r->z = (mulfx(sa, y) + mulfx(ca, z));
00162 }
00163
00164 void object_apply_transformations(object_t* obj, vector_t* pbuffer, int x, int y) {
00165 mesh_t* mesh = obj->mesh;
00166 vector_t* m = mesh->points;
00167 int c = mesh->pcount;
00168 while (c--) {
00169 vector_rotate(m, obj->rot_x, obj->rot_y, obj->rot_z, pbuffer);
00170 pbuffer->z += obj->trans_z;
00171 pbuffer->z /= 128;
00172 pbuffer->x = ((pbuffer->x + obj->trans_x) / pbuffer->z) + x;
00173 pbuffer->y = ((pbuffer->y + obj->trans_y) / pbuffer->z) + y;
00174 ++pbuffer;
00175 ++m;
00176 }
00177 }
00178
00179 void object_render_wireframe(surface_t* s, object_t* obj, vector_t* pbuffer) {
00180 int c, diff;
00181 vector_t *i, *j, *k, q1, q2;
00182 mesh_t* mesh = obj->mesh;
00183 vector_t* m = mesh->points;
00184 triangle_t* t = mesh->triangles;
00185
00186 object_apply_transformations(obj, pbuffer, 128, 96);
00187
00188 m = mesh->points;
00189 diff = (char*)pbuffer - (char*)m;
00190 for (c = 0; c < mesh->tcount; c++) {
00191 i = (vector_t*)((char*)t->vertexes[0] + diff);
00192 j = (vector_t*)((char*)t->vertexes[1] + diff);
00193 k = (vector_t*)((char*)t->vertexes[2] + diff);
00194
00195 vector_subtract(j, i, &q1);
00196 vector_subtract(k, i, &q2);
00197 if (vector_cross_product_z(&q1, &q2) > 0) {
00198 surface_line(s, i->x, i->y, j->x, j->y);
00199 surface_line(s, j->x, j->y, k->x, k->y);
00200 surface_line(s, k->x, k->y, i->x, i->y);
00201 }
00202 t++;
00203 }
00204 }
00205
00206 void object_render_flatshading(surface_t* s, object_t* obj, vector_t* pbuffer, int* low, int* high, vector_t* light) {
00207 int c, diff;
00208 int l, top, bottom;
00209 vector_t *i, *j, *k, q1, q2, N;
00210 mesh_t* mesh = obj->mesh;
00211 vector_t* m = mesh->points;
00212 triangle_t* t = mesh->triangles;
00213 int li;
00214
00215 object_apply_transformations(obj, pbuffer, 128, 96);
00216
00217 m = mesh->points;
00218 diff = (char*)pbuffer - (char*)m;
00219 for (c = 0; c < mesh->tcount; c++) {
00220 i = (vector_t*)((char*)t->vertexes[0] + diff);
00221 j = (vector_t*)((char*)t->vertexes[1] + diff);
00222 k = (vector_t*)((char*)t->vertexes[2] + diff);
00223
00224 vector_subtract(j, i, &q1);
00225 vector_subtract(k, i, &q2);
00226 vector_cross_product(&q1, &q2, &N);
00227
00228 if (N.z > 0) {
00229 vector_normalize(&N, &N);
00230 li = vector_dot_product(&N, light) * 5;
00231 li = f2i(li);
00232 li = (li < 0) ? 0 : ((li > 4) ? 4 : li);
00233
00234
00235
00236
00237 memset(low, MODE2_HEIGHT << 1, 64);
00238 memset(high, MODE2_HEIGHT << 1, 0);
00239
00240
00241 calculate_side(i->x, i->y, j->x, j->y, low, high);
00242 calculate_side(j->x, j->y, k->x, k->y, low, high);
00243 calculate_side(k->x, k->y, i->x, i->y, low, high);
00244
00245 top = (i->y < j->y) ? ((i->y < k->y) ? i->y : k->y) : ((j->y < k->y) ? j->y : k->y);
00246 bottom = (i->y > j->y) ? ((i->y > k->y) ? i->y : k->y) : ((j->y > k->y) ? j->y : k->y);
00247
00248 for (l = top; l <= bottom; l++) {
00249 surface_hline(s, low[l], l, high[l], DITHER(li, l));
00250 }
00251 }
00252 t++;
00253 }
00254 }