Advertisement
here2share

c3D.Engine.4.Python_3 ZZZ

Mar 30th, 2021
677
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 29.07 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <assert.h>
  5.  
  6. #include <windows.h>
  7. #include <tchar.h>
  8.  
  9. typedef unsigned int IUINT32;
  10.  
  11. //=====================================================================
  12. // Math library: This part should not be explained in detail, just be familiar with D3D matrix transformation
  13. //=====================================================================
  14. typedef struct { float m[4][4]; } matrix_t;
  15. typedef struct { float x, y, z, w; } vector_t;
  16. typedef vector_t point_t;
  17.  
  18. int CMID(int x, int min, int max) { return (x < min)? min : ((x > max)? max : x); }
  19.  
  20.  // Calculate interpolation: t is the value between [0, 1]
  21. float interp(float x1, float x2, float t) { return x1 + (x2 - x1) * t; }
  22.  
  23. // | v |
  24. float vector_length(const vector_t *v) {
  25.     float sq = v->x * v->x + v->y * v->y + v->z * v->z;
  26.     return (float)sqrt(sq);
  27. }
  28.  
  29. // z = x + y
  30. void vector_add(vector_t *z, const vector_t *x, const vector_t *y) {
  31.     z->x = x->x + y->x;
  32.     z->y = x->y + y->y;
  33.     z->z = x->z + y->z;
  34.     z->w = 1.0;
  35. }
  36.  
  37. // z = x - y
  38. void vector_sub(vector_t *z, const vector_t *x, const vector_t *y) {
  39.     z->x = x->x - y->x;
  40.     z->y = x->y - y->y;
  41.     z->z = x->z - y->z;
  42.     z->w = 1.0;
  43. }
  44.  
  45.  // Vector dot product
  46. float vector_dotproduct(const vector_t *x, const vector_t *y) {
  47.     return x->x * y->x + x->y * y->y + x->z * y->z;
  48. }
  49.  
  50.  // vector cross product
  51. void vector_crossproduct(vector_t *z, const vector_t *x, const vector_t *y) {
  52.     float m1, m2, m3;
  53.     m1 = x->y * y->z - x->z * y->y;
  54.     m2 = x->z * y->x - x->x * y->z;
  55.     m3 = x->x * y->y - x->y * y->x;
  56.     z->x = m1;
  57.     z->y = m2;
  58.     z->z = m3;
  59.     z->w = 1.0f;
  60. }
  61.  
  62.  // Vector interpolation, the value of t is [0, 1]
  63. void vector_interp(vector_t *z, const vector_t *x1, const vector_t *x2, float t) {
  64.     z->x = interp(x1->x, x2->x, t);
  65.     z->y = interp(x1->y, x2->y, t);
  66.     z->z = interp(x1->z, x2->z, t);
  67.     z->w = 1.0f;
  68. }
  69.  
  70.  // vector normalization
  71. void vector_normalize(vector_t *v) {
  72.     float length = vector_length(v);
  73.     if (length != 0.0f) {
  74.         float inv = 1.0f / length;
  75.         v->x *= inv;
  76.         v->y *= inv;
  77.         v->z *= inv;
  78.     }
  79. }
  80.  
  81. // c = a + b
  82. void matrix_add(matrix_t *c, const matrix_t *a, const matrix_t *b) {
  83.     int i, j;
  84.     for (i = 0; i < 4; i++) {
  85.         for (j = 0; j < 4; j++)
  86.             c->m[i][j] = a->m[i][j] + b->m[i][j];
  87.     }
  88. }
  89.  
  90. // c = a - b
  91. void matrix_sub(matrix_t *c, const matrix_t *a, const matrix_t *b) {
  92.     int i, j;
  93.     for (i = 0; i < 4; i++) {
  94.         for (j = 0; j < 4; j++)
  95.             c->m[i][j] = a->m[i][j] - b->m[i][j];
  96.     }
  97. }
  98.  
  99. // c = a * b
  100. void matrix_mul(matrix_t *c, const matrix_t *a, const matrix_t *b) {
  101.     matrix_t z;
  102.     int i, j;
  103.     for (i = 0; i < 4; i++) {
  104.         for (j = 0; j < 4; j++) {
  105.             z.m[j][i] = (a->m[j][0] * b->m[0][i]) +
  106.                         (a->m[j][1] * b->m[1][i]) +
  107.                         (a->m[j][2] * b->m[2][i]) +
  108.                         (a->m[j][3] * b->m[3][i]);
  109.         }
  110.     }
  111.     c[0] = z;
  112. }
  113.  
  114. // c = a * f
  115. void matrix_scale(matrix_t *c, const matrix_t *a, float f) {
  116.     int i, j;
  117.     for (i = 0; i < 4; i++) {
  118.         for (j = 0; j < 4; j++)
  119.             c->m[i][j] = a->m[i][j] * f;
  120.     }
  121. }
  122.  
  123. // y = x * m
  124. void matrix_apply(vector_t *y, const vector_t *x, const matrix_t *m) {
  125.     float X = x->x, Y = x->y, Z = x->z, W = x->w;
  126.     y->x = X * m->m[0][0] + Y * m->m[1][0] + Z * m->m[2][0] + W * m->m[3][0];
  127.     y->y = X * m->m[0][1] + Y * m->m[1][1] + Z * m->m[2][1] + W * m->m[3][1];
  128.     y->z = X * m->m[0][2] + Y * m->m[1][2] + Z * m->m[2][2] + W * m->m[3][2];
  129.     y->w = X * m->m[0][3] + Y * m->m[1][3] + Z * m->m[2][3] + W * m->m[3][3];
  130. }
  131.  
  132. void matrix_set_identity(matrix_t *m) {
  133.     m->m[0][0] = m->m[1][1] = m->m[2][2] = m->m[3][3] = 1.0f;
  134.     m->m[0][1] = m->m[0][2] = m->m[0][3] = 0.0f;
  135.     m->m[1][0] = m->m[1][2] = m->m[1][3] = 0.0f;
  136.     m->m[2][0] = m->m[2][1] = m->m[2][3] = 0.0f;
  137.     m->m[3][0] = m->m[3][1] = m->m[3][2] = 0.0f;
  138. }
  139.  
  140. void matrix_set_zero(matrix_t *m) {
  141.     m->m[0][0] = m->m[0][1] = m->m[0][2] = m->m[0][3] = 0.0f;
  142.     m->m[1][0] = m->m[1][1] = m->m[1][2] = m->m[1][3] = 0.0f;
  143.     m->m[2][0] = m->m[2][1] = m->m[2][2] = m->m[2][3] = 0.0f;
  144.     m->m[3][0] = m->m[3][1] = m->m[3][2] = m->m[3][3] = 0.0f;
  145. }
  146.  
  147.  // translation transformation
  148. void matrix_set_translate(matrix_t *m, float x, float y, float z) {
  149.     matrix_set_identity(m);
  150.     m->m[3][0] = x;
  151.     m->m[3][1] = y;
  152.     m->m[3][2] = z;
  153. }
  154.  
  155.  // zoom transformation
  156. void matrix_set_scale(matrix_t *m, float x, float y, float z) {
  157.     matrix_set_identity(m);
  158.     m->m[0][0] = x;
  159.     m->m[1][1] = y;
  160.     m->m[2][2] = z;
  161. }
  162.  
  163.  // Rotation matrix
  164. void matrix_set_rotate(matrix_t *m, float x, float y, float z, float theta) {
  165.     float qsin = (float)sin(theta * 0.5f);
  166.     float qcos = (float)cos(theta * 0.5f);
  167.     vector_t vec = { x, y, z, 1.0f };
  168.     float w = qcos;
  169.     vector_normalize(&vec);
  170.     x = vec.x * qsin;
  171.     y = vec.y * qsin;
  172.     z = vec.z * qsin;
  173.     m->m[0][0] = 1 - 2 * y * y - 2 * z * z;
  174.     m->m[1][0] = 2 * x * y - 2 * w * z;
  175.     m->m[2][0] = 2 * x * z + 2 * w * y;
  176.     m->m[0][1] = 2 * x * y + 2 * w * z;
  177.     m->m[1][1] = 1 - 2 * x * x - 2 * z * z;
  178.     m->m[2][1] = 2 * y * z - 2 * w * x;
  179.     m->m[0][2] = 2 * x * z - 2 * w * y;
  180.     m->m[1][2] = 2 * y * z + 2 * w * x;
  181.     m->m[2][2] = 1 - 2 * x * x - 2 * y * y;
  182.     m->m[0][3] = m->m[1][3] = m->m[2][3] = 0.0f;
  183.     m->m[3][0] = m->m[3][1] = m->m[3][2] = 0.0f;   
  184.     m->m[3][3] = 1.0f;
  185. }
  186.  
  187.  // Set up the camera
  188. void matrix_set_lookat(matrix_t *m, const vector_t *eye, const vector_t *at, const vector_t *up) {
  189.     vector_t xaxis, yaxis, zaxis;
  190.  
  191.     vector_sub(&zaxis, at, eye);
  192.     vector_normalize(&zaxis);
  193.     vector_crossproduct(&xaxis, up, &zaxis);
  194.     vector_normalize(&xaxis);
  195.     vector_crossproduct(&yaxis, &zaxis, &xaxis);
  196.  
  197.     m->m[0][0] = xaxis.x;
  198.     m->m[1][0] = xaxis.y;
  199.     m->m[2][0] = xaxis.z;
  200.     m->m[3][0] = -vector_dotproduct(&xaxis, eye);
  201.  
  202.     m->m[0][1] = yaxis.x;
  203.     m->m[1][1] = yaxis.y;
  204.     m->m[2][1] = yaxis.z;
  205.     m->m[3][1] = -vector_dotproduct(&yaxis, eye);
  206.  
  207.     m->m[0][2] = zaxis.x;
  208.     m->m[1][2] = zaxis.y;
  209.     m->m[2][2] = zaxis.z;
  210.     m->m[3][2] = -vector_dotproduct(&zaxis, eye);
  211.    
  212.     m->m[0][3] = m->m[1][3] = m->m[2][3] = 0.0f;
  213.     m->m[3][3] = 1.0f;
  214. }
  215.  
  216. // D3DXMatrixPerspectiveFovLH
  217. void matrix_set_perspective(matrix_t *m, float fovy, float aspect, float zn, float zf) {
  218.     float fax = 1.0f / (float)tan(fovy * 0.5f);
  219.     matrix_set_zero(m);
  220.     m->m[0][0] = (float)(fax / aspect);
  221.     m->m[1][1] = (float)(fax);
  222.     m->m[2][2] = zf / (zf - zn);
  223.     m->m[3][2] = - zn * zf / (zf - zn);
  224.     m->m[2][3] = 1;
  225. }
  226.  
  227.  
  228. //=====================================================================
  229.  // coordinate transformation
  230. //=====================================================================
  231. typedef struct {
  232.      matrix_t world; // world coordinate transformation
  233.      matrix_t view; // Camera coordinate transformation
  234.      matrix_t projection; // Projection transformation
  235.     matrix_t transform;     // transform = world * view * projection
  236.      float w, h; // screen size
  237. }   transform_t;
  238.  
  239.  
  240.  // Matrix update, calculation transform = world * view * projection
  241. void transform_update(transform_t *ts) {
  242.     matrix_t m;
  243.     matrix_mul(&m, &ts->world, &ts->view);
  244.     matrix_mul(&ts->transform, &m, &ts->projection);
  245. }
  246.  
  247.  // Initialize, set the screen length and width
  248. void transform_init(transform_t *ts, int width, int height) {
  249.     float aspect = (float)width / ((float)height);
  250.     matrix_set_identity(&ts->world);
  251.     matrix_set_identity(&ts->view);
  252.     matrix_set_perspective(&ts->projection, 3.1415926f * 0.5f, aspect, 1.0f, 500.0f);
  253.     ts->w = (float)width;
  254.     ts->h = (float)height;
  255.     transform_update(ts);
  256. }
  257.  
  258.  // project vector x
  259. void transform_apply(const transform_t *ts, vector_t *y, const vector_t *x) {
  260.     matrix_apply(y, x, &ts->transform);
  261. }
  262.  
  263.  // Check the boundary between homogeneous coordinates and cvv for frustum clipping
  264. int transform_check_cvv(const vector_t *v) {
  265.     float w = v->w;
  266.     int check = 0;
  267.     if (v->z < 0.0f) check |= 1;
  268.     if (v->z >  w) check |= 2;
  269.     if (v->x < -w) check |= 4;
  270.     if (v->x >  w) check |= 8;
  271.     if (v->y < -w) check |= 16;
  272.     if (v->y >  w) check |= 32;
  273.     return check;
  274. }
  275.  
  276.  // Normalize to get screen coordinates
  277. void transform_homogenize(const transform_t *ts, vector_t *y, const vector_t *x) {
  278.     float rhw = 1.0f / x->w;
  279.     y->x = (x->x * rhw + 1.0f) * ts->w * 0.5f;
  280.     y->y = (1.0f - x->y * rhw) * ts->h * 0.5f;
  281.     y->z = x->z * rhw;
  282.     y->w = 1.0f;
  283. }
  284.  
  285.  
  286. //=====================================================================
  287.  // Geometric calculation: vertex, scan line, edge, rectangle, step length calculation
  288. //=====================================================================
  289. typedef struct { float r, g, b; } color_t;
  290. typedef struct { float u, v; } texcoord_t;
  291. typedef struct { point_t pos; texcoord_t tc; color_t color; float rhw; } vertex_t;
  292.  
  293. typedef struct { vertex_t v, v1, v2; } edge_t;
  294. typedef struct { float top, bottom; edge_t left, right; } trapezoid_t;
  295. typedef struct { vertex_t v, step; int x, y, w; } scanline_t;
  296.  
  297.  
  298. void vertex_rhw_init(vertex_t *v) {
  299.     float rhw = 1.0f / v->pos.w;
  300.     v->rhw = rhw;
  301.     v->tc.u *= rhw;
  302.     v->tc.v *= rhw;
  303.     v->color.r *= rhw;
  304.     v->color.g *= rhw;
  305.     v->color.b *= rhw;
  306. }
  307.  
  308. void vertex_interp(vertex_t *y, const vertex_t *x1, const vertex_t *x2, float t) {
  309.     vector_interp(&y->pos, &x1->pos, &x2->pos, t);
  310.     y->tc.u = interp(x1->tc.u, x2->tc.u, t);
  311.     y->tc.v = interp(x1->tc.v, x2->tc.v, t);
  312.     y->color.r = interp(x1->color.r, x2->color.r, t);
  313.     y->color.g = interp(x1->color.g, x2->color.g, t);
  314.     y->color.b = interp(x1->color.b, x2->color.b, t);
  315.     y->rhw = interp(x1->rhw, x2->rhw, t);
  316. }
  317.  
  318. void vertex_division(vertex_t *y, const vertex_t *x1, const vertex_t *x2, float w) {
  319.     float inv = 1.0f / w;
  320.     y->pos.x = (x2->pos.x - x1->pos.x) * inv;
  321.     y->pos.y = (x2->pos.y - x1->pos.y) * inv;
  322.     y->pos.z = (x2->pos.z - x1->pos.z) * inv;
  323.     y->pos.w = (x2->pos.w - x1->pos.w) * inv;
  324.     y->tc.u = (x2->tc.u - x1->tc.u) * inv;
  325.     y->tc.v = (x2->tc.v - x1->tc.v) * inv;
  326.     y->color.r = (x2->color.r - x1->color.r) * inv;
  327.     y->color.g = (x2->color.g - x1->color.g) * inv;
  328.     y->color.b = (x2->color.b - x1->color.b) * inv;
  329.     y->rhw = (x2->rhw - x1->rhw) * inv;
  330. }
  331.  
  332. void vertex_add(vertex_t *y, const vertex_t *x) {
  333.     y->pos.x += x->pos.x;
  334.     y->pos.y += x->pos.y;
  335.     y->pos.z += x->pos.z;
  336.     y->pos.w += x->pos.w;
  337.     y->rhw += x->rhw;
  338.     y->tc.u += x->tc.u;
  339.     y->tc.v += x->tc.v;
  340.     y->color.r += x->color.r;
  341.     y->color.g += x->color.g;
  342.     y->color.b += x->color.b;
  343. }
  344.  
  345.  // Generate 0-2 trapezoids based on the triangle, and return the number of legal trapezoids
  346. int trapezoid_init_triangle(trapezoid_t *trap, const vertex_t *p1,
  347.     const vertex_t *p2, const vertex_t *p3) {
  348.     const vertex_t *p;
  349.     float k, x;
  350.  
  351.     if (p1->pos.y > p2->pos.y) p = p1, p1 = p2, p2 = p;
  352.     if (p1->pos.y > p3->pos.y) p = p1, p1 = p3, p3 = p;
  353.     if (p2->pos.y > p3->pos.y) p = p2, p2 = p3, p3 = p;
  354.     if (p1->pos.y == p2->pos.y && p1->pos.y == p3->pos.y) return 0;
  355.     if (p1->pos.x == p2->pos.x && p1->pos.x == p3->pos.x) return 0;
  356.  
  357.     if (p1->pos.y == p2->pos.y) {   // triangle down
  358.         if (p1->pos.x > p2->pos.x) p = p1, p1 = p2, p2 = p;
  359.         trap[0].top = p1->pos.y;
  360.         trap[0].bottom = p3->pos.y;
  361.         trap[0].left.v1 = *p1;
  362.         trap[0].left.v2 = *p3;
  363.         trap[0].right.v1 = *p2;
  364.         trap[0].right.v2 = *p3;
  365.         return (trap[0].top < trap[0].bottom)? 1 : 0;
  366.     }
  367.  
  368.     if (p2->pos.y == p3->pos.y) {   // triangle up
  369.         if (p2->pos.x > p3->pos.x) p = p2, p2 = p3, p3 = p;
  370.         trap[0].top = p1->pos.y;
  371.         trap[0].bottom = p3->pos.y;
  372.         trap[0].left.v1 = *p1;
  373.         trap[0].left.v2 = *p2;
  374.         trap[0].right.v1 = *p1;
  375.         trap[0].right.v2 = *p3;
  376.         return (trap[0].top < trap[0].bottom)? 1 : 0;
  377.     }
  378.  
  379.     trap[0].top = p1->pos.y;
  380.     trap[0].bottom = p2->pos.y;
  381.     trap[1].top = p2->pos.y;
  382.     trap[1].bottom = p3->pos.y;
  383.  
  384.     k = (p3->pos.y - p1->pos.y) / (p2->pos.y - p1->pos.y);
  385.     x = p1->pos.x + (p2->pos.x - p1->pos.x) * k;
  386.  
  387.     if (x <= p3->pos.x) {       // triangle left
  388.         trap[0].left.v1 = *p1;
  389.         trap[0].left.v2 = *p2;
  390.         trap[0].right.v1 = *p1;
  391.         trap[0].right.v2 = *p3;
  392.         trap[1].left.v1 = *p2;
  393.         trap[1].left.v2 = *p3;
  394.         trap[1].right.v1 = *p1;
  395.         trap[1].right.v2 = *p3;
  396.     }   else {                  // triangle right
  397.         trap[0].left.v1 = *p1;
  398.         trap[0].left.v2 = *p3;
  399.         trap[0].right.v1 = *p1;
  400.         trap[0].right.v2 = *p2;
  401.         trap[1].left.v1 = *p1;
  402.         trap[1].left.v2 = *p3;
  403.         trap[1].right.v1 = *p2;
  404.         trap[1].right.v2 = *p3;
  405.     }
  406.  
  407.     return 2;
  408. }
  409.  
  410.  // Calculate the vertices whose ordinates on the left and right sides are equal to Y according to the Y coordinates
  411. void trapezoid_edge_interp(trapezoid_t *trap, float y) {
  412.     float s1 = trap->left.v2.pos.y - trap->left.v1.pos.y;
  413.     float s2 = trap->right.v2.pos.y - trap->right.v1.pos.y;
  414.     float t1 = (y - trap->left.v1.pos.y) / s1;
  415.     float t2 = (y - trap->right.v1.pos.y) / s2;
  416.     vertex_interp(&trap->left.v, &trap->left.v1, &trap->left.v2, t1);
  417.     vertex_interp(&trap->right.v, &trap->right.v1, &trap->right.v2, t2);
  418. }
  419.  
  420.  // Initially calculate the starting point and step length of the scan line according to the endpoints on the left and right sides
  421. void trapezoid_init_scan_line(const trapezoid_t *trap, scanline_t *scanline, int y) {
  422.     float width = trap->right.v.pos.x - trap->left.v.pos.x;
  423.     scanline->x = (int)(trap->left.v.pos.x + 0.5f);
  424.     scanline->w = (int)(trap->right.v.pos.x + 0.5f) - scanline->x;
  425.     scanline->y = y;
  426.     scanline->v = trap->left.v;
  427.     if (trap->left.v.pos.x >= trap->right.v.pos.x) scanline->w = 0;
  428.     vertex_division(&scanline->step, &trap->left.v, &trap->right.v, width);
  429. }
  430.  
  431.  
  432. //=====================================================================
  433.  // rendering equipment
  434. //=====================================================================
  435. typedef struct {
  436.      transform_t transform; // coordinate converter
  437.      int width; // window width
  438.      int height; // window height
  439.      IUINT32 **framebuffer; // Pixel buffer: framebuffer[y] represents the yth line
  440.      float **zbuffer; // Depth buffer: zbuffer[y] is the y-th line pointer
  441.      IUINT32 **texture; // Texture: also the index of each row
  442.      int tex_width; // texture width
  443.      int tex_height; // texture height
  444.      float max_u; // Maximum texture width: tex_width-1
  445.      float max_v; // Maximum texture height: tex_height-1
  446.      int render_state; // rendering state
  447.      IUINT32 background; // background color
  448.      IUINT32 foreground; // wireframe color
  449. }   device_t;
  450.  
  451.  #define RENDER_STATE_WIREFRAME 1 // Render wireframe
  452.  #define RENDER_STATE_TEXTURE 2 // Render texture
  453.  #define RENDER_STATE_COLOR 4 // Render color
  454.  
  455.  // The device is initialized, fb is the external frame buffer, non-NULL will refer to the external frame buffer (4-byte alignment per line)
  456. void device_init(device_t *device, int width, int height, void *fb) {
  457.     int need = sizeof(void*) * (height * 2 + 1024) + width * height * 8;
  458.     char *ptr = (char*)malloc(need + 64);
  459.     char *framebuf, *zbuf;
  460.     int j;
  461.     assert(ptr);
  462.     device->framebuffer = (IUINT32**)ptr;
  463.     device->zbuffer = (float**)(ptr + sizeof(void*) * height);
  464.     ptr += sizeof(void*) * height * 2;
  465.     device->texture = (IUINT32**)ptr;
  466.     ptr += sizeof(void*) * 1024;
  467.     framebuf = (char*)ptr;
  468.     zbuf = (char*)ptr + width * height * 4;
  469.     ptr += width * height * 8;
  470.     if (fb != NULL) framebuf = (char*)fb;
  471.     for (j = 0; j < height; j++) {
  472.         device->framebuffer[j] = (IUINT32*)(framebuf + width * 4 * j);
  473.         device->zbuffer[j] = (float*)(zbuf + width * 4 * j);
  474.     }
  475.     device->texture[0] = (IUINT32*)ptr;
  476.     device->texture[1] = (IUINT32*)(ptr + 16);
  477.     memset(device->texture[0], 0, 64);
  478.     device->tex_width = 2;
  479.     device->tex_height = 2;
  480.     device->max_u = 1.0f;
  481.     device->max_v = 1.0f;
  482.     device->width = width;
  483.     device->height = height;
  484.     device->background = 0xc0c0c0;
  485.     device->foreground = 0;
  486.     transform_init(&device->transform, width, height);
  487.     device->render_state = RENDER_STATE_WIREFRAME;
  488. }
  489.  
  490.  // Delete device
  491. void device_destroy(device_t *device) {
  492.     if (device->framebuffer)
  493.         free(device->framebuffer);
  494.     device->framebuffer = NULL;
  495.     device->zbuffer = NULL;
  496.     device->texture = NULL;
  497. }
  498.  
  499.  // Set the current texture
  500. void device_set_texture(device_t *device, void *bits, long pitch, int w, int h) {
  501.     char *ptr = (char*)bits;
  502.     int j;
  503.     assert(w <= 1024 && h <= 1024);
  504.      for (j = 0; j <h; ptr += pitch, j++) // recalculate the pointer of each line of texture
  505.         device->texture[j] = (IUINT32*)ptr;
  506.     device->tex_width = w;
  507.     device->tex_height = h;
  508.     device->max_u = (float)(w - 1);
  509.     device->max_v = (float)(h - 1);
  510. }
  511.  
  512.  // Clear framebuffer and zbuffer
  513. void device_clear(device_t *device, int mode) {
  514.     int y, x, height = device->height;
  515.     for (y = 0; y < device->height; y++) {
  516.         IUINT32 *dst = device->framebuffer[y];
  517.         IUINT32 cc = (height - 1 - y) * 230 / (height - 1);
  518.         cc = (cc << 16) | (cc << 8) | cc;
  519.         if (mode == 0) cc = device->background;
  520.         for (x = device->width; x > 0; dst++, x--) dst[0] = cc;
  521.     }
  522.     for (y = 0; y < device->height; y++) {
  523.         float *dst = device->zbuffer[y];
  524.         for (x = device->width; x > 0; dst++, x--) dst[0] = 0.0f;
  525.     }
  526. }
  527.  
  528.  // draw points
  529. void device_pixel(device_t *device, int x, int y, IUINT32 color) {
  530.     if (((IUINT32)x) < (IUINT32)device->width && ((IUINT32)y) < (IUINT32)device->height) {
  531.         device->framebuffer[y][x] = color;
  532.     }
  533. }
  534.  
  535.  // draw line segment
  536. void device_draw_line(device_t *device, int x1, int y1, int x2, int y2, IUINT32 c) {
  537.     int x, y, rem = 0;
  538.     if (x1 == x2 && y1 == y2) {
  539.         device_pixel(device, x1, y1, c);
  540.     }   else if (x1 == x2) {
  541.         int inc = (y1 <= y2)? 1 : -1;
  542.         for (y = y1; y != y2; y += inc) device_pixel(device, x1, y, c);
  543.         device_pixel(device, x2, y2, c);
  544.     }   else if (y1 == y2) {
  545.         int inc = (x1 <= x2)? 1 : -1;
  546.         for (x = x1; x != x2; x += inc) device_pixel(device, x, y1, c);
  547.         device_pixel(device, x2, y2, c);
  548.     }   else {
  549.         int dx = (x1 < x2)? x2 - x1 : x1 - x2;
  550.         int dy = (y1 < y2)? y2 - y1 : y1 - y2;
  551.         if (dx >= dy) {
  552.             if (x2 < x1) x = x1, y = y1, x1 = x2, y1 = y2, x2 = x, y2 = y;
  553.             for (x = x1, y = y1; x <= x2; x++) {
  554.                 device_pixel(device, x, y, c);
  555.                 rem += dy;
  556.                 if (rem >= dx) {
  557.                     rem -= dx;
  558.                     y += (y2 >= y1)? 1 : -1;
  559.                     device_pixel(device, x, y, c);
  560.                 }
  561.             }
  562.             device_pixel(device, x2, y2, c);
  563.         }   else {
  564.             if (y2 < y1) x = x1, y = y1, x1 = x2, y1 = y2, x2 = x, y2 = y;
  565.             for (x = x1, y = y1; y <= y2; y++) {
  566.                 device_pixel(device, x, y, c);
  567.                 rem += dx;
  568.                 if (rem >= dy) {
  569.                     rem -= dy;
  570.                     x += (x2 >= x1)? 1 : -1;
  571.                     device_pixel(device, x, y, c);
  572.                 }
  573.             }
  574.             device_pixel(device, x2, y2, c);
  575.         }
  576.     }
  577. }
  578.  
  579.  // read the texture according to the coordinates
  580. IUINT32 device_texture_read(const device_t *device, float u, float v) {
  581.     int x, y;
  582.     u = u * device->max_u;
  583.     v = v * device->max_v;
  584.     x = (int)(u + 0.5f);
  585.     y = (int)(v + 0.5f);
  586.     x = CMID(x, 0, device->tex_width - 1);
  587.     y = CMID(y, 0, device->tex_height - 1);
  588.     return device->texture[y][x];
  589. }
  590.  
  591.  
  592. //=====================================================================
  593.  // Rendering implementation
  594. //=====================================================================
  595.  
  596.  // Draw scan line
  597. void device_draw_scanline(device_t *device, scanline_t *scanline) {
  598.     IUINT32 *framebuffer = device->framebuffer[scanline->y];
  599.     float *zbuffer = device->zbuffer[scanline->y];
  600.     int x = scanline->x;
  601.     int w = scanline->w;
  602.     int width = device->width;
  603.     int render_state = device->render_state;
  604.     for (; w > 0; x++, w--) {
  605.         if (x >= 0 && x < width) {
  606.             float rhw = scanline->v.rhw;
  607.             if (rhw >= zbuffer[x]) {   
  608.                 float w = 1.0f / rhw;
  609.                 zbuffer[x] = rhw;
  610.                 if (render_state & RENDER_STATE_COLOR) {
  611.                     float r = scanline->v.color.r * w;
  612.                     float g = scanline->v.color.g * w;
  613.                     float b = scanline->v.color.b * w;
  614.                     int R = (int)(r * 255.0f);
  615.                     int G = (int)(g * 255.0f);
  616.                     int B = (int)(b * 255.0f);
  617.                     R = CMID(R, 0, 255);
  618.                     G = CMID(G, 0, 255);
  619.                     B = CMID(B, 0, 255);
  620.                     framebuffer[x] = (R << 16) | (G << 8) | (B);
  621.                 }
  622.                 if (render_state & RENDER_STATE_TEXTURE) {
  623.                     float u = scanline->v.tc.u * w;
  624.                     float v = scanline->v.tc.v * w;
  625.                     IUINT32 cc = device_texture_read(device, u, v);
  626.                     framebuffer[x] = cc;
  627.                 }
  628.             }
  629.         }
  630.         vertex_add(&scanline->v, &scanline->step);
  631.         if (x >= width) break;
  632.     }
  633. }
  634.  
  635.  // Main rendering function
  636. void device_render_trap(device_t *device, trapezoid_t *trap) {
  637.     scanline_t scanline;
  638.     int j, top, bottom;
  639.     top = (int)(trap->top + 0.5f);
  640.     bottom = (int)(trap->bottom + 0.5f);
  641.     for (j = top; j < bottom; j++) {
  642.         if (j >= 0 && j < device->height) {
  643.             trapezoid_edge_interp(trap, (float)j + 0.5f);
  644.             trapezoid_init_scan_line(trap, &scanline, j);
  645.             device_draw_scanline(device, &scanline);
  646.         }
  647.         if (j >= device->height) break;
  648.     }
  649. }
  650.  
  651.  // Draw the original triangle according to render_state
  652. void device_draw_primitive(device_t *device, const vertex_t *v1,
  653.     const vertex_t *v2, const vertex_t *v3) {
  654.     point_t p1, p2, p3, c1, c2, c3;
  655.     int render_state = device->render_state;
  656.  
  657.      // Change according to Transform
  658.     transform_apply(&device->transform, &c1, &v1->pos);
  659.     transform_apply(&device->transform, &c2, &v2->pos);
  660.     transform_apply(&device->transform, &c3, &v3->pos);
  661.  
  662.      // Crop, note that this can be perfected to specifically determine the coordinate ratio of several points in cvv and the plane intersecting with cvv
  663.      // Perform further fine-graining and decompose a triangle into several triangles completely in cvv
  664.     if (transform_check_cvv(&c1) != 0) return;
  665.     if (transform_check_cvv(&c2) != 0) return;
  666.     if (transform_check_cvv(&c3) != 0) return;
  667.  
  668.         // Normalized
  669.     transform_homogenize(&device->transform, &p1, &c1);
  670.     transform_homogenize(&device->transform, &p2, &c2);
  671.     transform_homogenize(&device->transform, &p3, &c3);
  672.  
  673.      // texture or color drawing
  674.     if (render_state & (RENDER_STATE_TEXTURE | RENDER_STATE_COLOR)) {
  675.         vertex_t t1 = *v1, t2 = *v2, t3 = *v3;
  676.         trapezoid_t traps[2];
  677.         int n;
  678.  
  679.         t1.pos = p1;
  680.         t2.pos = p2;
  681.         t3.pos = p3;
  682.         t1.pos.w = c1.w;
  683.         t2.pos.w = c2.w;
  684.         t3.pos.w = c3.w;
  685.        
  686.          vertex_rhw_init(&t1); // initialize w
  687.          vertex_rhw_init(&t2); // initialize w
  688.          vertex_rhw_init(&t3); // initialize w
  689.        
  690.          // Split the triangle into 0-2 trapezoids, and return the number of available trapezoids
  691.         n = trapezoid_init_triangle(traps, &t1, &t2, &t3);
  692.  
  693.         if (n >= 1) device_render_trap(device, &traps[0]);
  694.         if (n >= 2) device_render_trap(device, &traps[1]);
  695.     }
  696.  
  697.      if (render_state & RENDER_STATE_WIREFRAME) {// wireframe drawing
  698.         device_draw_line(device, (int)p1.x, (int)p1.y, (int)p2.x, (int)p2.y, device->foreground);
  699.         device_draw_line(device, (int)p1.x, (int)p1.y, (int)p3.x, (int)p3.y, device->foreground);
  700.         device_draw_line(device, (int)p3.x, (int)p3.y, (int)p2.x, (int)p2.y, device->foreground);
  701.     }
  702. }
  703.  
  704.  
  705. //=====================================================================
  706.  // Win32 window and graphics drawing: provide a DibSection FB for device
  707. //=====================================================================
  708. int screen_w, screen_h, screen_exit = 0;
  709. int screen_mx = 0, screen_my = 0, screen_mb = 0;
  710.  int screen_keys[512]; // current keyboard press state
  711. static HWND screen_handle = NULL; // Main window HWND
  712.  static HDC screen_dc = NULL; // matching HDC
  713. static HBITMAP screen_hb = NULL;        // DIB
  714.  static HBITMAP screen_ob = NULL; // old BITMAP
  715. unsigned char *screen_fb = NULL;        // frame buffer
  716. long screen_pitch = 0;
  717.  
  718.  int screen_init(int w, int h, const TCHAR *title); // screen initialization
  719.  int screen_close(void); // close the screen
  720.  void screen_dispatch(void); // process the message
  721.  void screen_update(void); // Display FrameBuffer
  722.  
  723. // win32 event handler
  724. static LRESULT screen_events(HWND, UINT, WPARAM, LPARAM);  
  725.  
  726. #ifdef _MSC_VER
  727. #pragma comment(lib, "gdi32.lib")
  728. #pragma comment(lib, "user32.lib")
  729. #endif
  730.  
  731.  // Initialize the window and set the title
  732. int screen_init(int w, int h, const TCHAR *title) {
  733.     WNDCLASS wc = { CS_BYTEALIGNCLIENT, (WNDPROC)screen_events, 0, 0, 0,
  734.         NULL, NULL, NULL, NULL, _T("SCREEN3.1415926") };
  735.     BITMAPINFO bi = { { sizeof(BITMAPINFOHEADER), w, -h, 1, 32, BI_RGB,
  736.         w * h * 4, 0, 0, 0, 0 }  };
  737.     RECT rect = { 0, 0, w, h };
  738.     int wx, wy, sx, sy;
  739.     LPVOID ptr;
  740.     HDC hDC;
  741.  
  742.     screen_close();
  743.  
  744.     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  745.     wc.hInstance = GetModuleHandle(NULL);
  746.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  747.     if (!RegisterClass(&wc)) return -1;
  748.  
  749.     screen_handle = CreateWindow(_T("SCREEN3.1415926"), title,
  750.         WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
  751.         0, 0, 0, 0, NULL, NULL, wc.hInstance, NULL);
  752.     if (screen_handle == NULL) return -2;
  753.  
  754.     screen_exit = 0;
  755.     hDC = GetDC(screen_handle);
  756.     screen_dc = CreateCompatibleDC(hDC);
  757.     ReleaseDC(screen_handle, hDC);
  758.  
  759.     screen_hb = CreateDIBSection(screen_dc, &bi, DIB_RGB_COLORS, &ptr, 0, 0);
  760.     if (screen_hb == NULL) return -3;
  761.  
  762.     screen_ob = (HBITMAP)SelectObject(screen_dc, screen_hb);
  763.     screen_fb = (unsigned char*)ptr;
  764.     screen_w = w;
  765.     screen_h = h;
  766.     screen_pitch = w * 4;
  767.    
  768.     AdjustWindowRect(&rect, GetWindowLong(screen_handle, GWL_STYLE), 0);
  769.     wx = rect.right - rect.left;
  770.     wy = rect.bottom - rect.top;
  771.     sx = (GetSystemMetrics(SM_CXSCREEN) - wx) / 2;
  772.     sy = (GetSystemMetrics(SM_CYSCREEN) - wy) / 2;
  773.     if (sy < 0) sy = 0;
  774.     SetWindowPos(screen_handle, NULL, sx, sy, wx, wy, (SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW));
  775.     SetForegroundWindow(screen_handle);
  776.  
  777.     ShowWindow(screen_handle, SW_NORMAL);
  778.     screen_dispatch();
  779.  
  780.     memset(screen_keys, 0, sizeof(int) * 512);
  781.     memset(screen_fb, 0, w * h * 4);
  782.  
  783.     return 0;
  784. }
  785.  
  786. int screen_close(void) {
  787.     if (screen_dc) {
  788.         if (screen_ob) {
  789.             SelectObject(screen_dc, screen_ob);
  790.             screen_ob = NULL;
  791.         }
  792.         DeleteDC(screen_dc);
  793.         screen_dc = NULL;
  794.     }
  795.     if (screen_hb) {
  796.         DeleteObject(screen_hb);
  797.         screen_hb = NULL;
  798.     }
  799.     if (screen_handle) {
  800.         CloseWindow(screen_handle);
  801.         screen_handle = NULL;
  802.     }
  803.     return 0;
  804. }
  805.  
  806. static LRESULT screen_events(HWND hWnd, UINT msg,
  807.     WPARAM wParam, LPARAM lParam) {
  808.     switch (msg) {
  809.     case WM_CLOSE: screen_exit = 1; break;
  810.     case WM_KEYDOWN: screen_keys[wParam & 511] = 1; break;
  811.     case WM_KEYUP: screen_keys[wParam & 511] = 0; break;
  812.     default: return DefWindowProc(hWnd, msg, wParam, lParam);
  813.     }
  814.     return 0;
  815. }
  816.  
  817. void screen_dispatch(void) {
  818.     MSG msg;
  819.     while (1) {
  820.         if (!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) break;
  821.         if (!GetMessage(&msg, NULL, 0, 0)) break;
  822.         DispatchMessage(&msg);
  823.     }
  824. }
  825.  
  826. void screen_update(void) {
  827.     HDC hDC = GetDC(screen_handle);
  828.     BitBlt(hDC, 0, 0, screen_w, screen_h, screen_dc, 0, 0, SRCCOPY);
  829.     ReleaseDC(screen_handle, hDC);
  830.     screen_dispatch();
  831. }
  832.  
  833.  
  834. //=====================================================================
  835.  // main program
  836. //=====================================================================
  837. vertex_t mesh[8] = {
  838.     { {  1, -1,  1, 1 }, { 0, 0 }, { 1.0f, 0.2f, 0.2f }, 1 },
  839.     { { -1, -1,  1, 1 }, { 0, 1 }, { 0.2f, 1.0f, 0.2f }, 1 },
  840.     { { -1,  1,  1, 1 }, { 1, 1 }, { 0.2f, 0.2f, 1.0f }, 1 },
  841.     { {  1,  1,  1, 1 }, { 1, 0 }, { 1.0f, 0.2f, 1.0f }, 1 },
  842.     { {  1, -1, -1, 1 }, { 0, 0 }, { 1.0f, 1.0f, 0.2f }, 1 },
  843.     { { -1, -1, -1, 1 }, { 0, 1 }, { 0.2f, 1.0f, 1.0f }, 1 },
  844.     { { -1,  1, -1, 1 }, { 1, 1 }, { 1.0f, 0.3f, 0.3f }, 1 },
  845.     { {  1,  1, -1, 1 }, { 1, 0 }, { 0.2f, 1.0f, 0.3f }, 1 },
  846. };
  847.  
  848. void draw_plane(device_t *device, int a, int b, int c, int d) {
  849.     vertex_t p1 = mesh[a], p2 = mesh[b], p3 = mesh[c], p4 = mesh[d];
  850.     p1.tc.u = 0, p1.tc.v = 0, p2.tc.u = 0, p2.tc.v = 1;
  851.     p3.tc.u = 1, p3.tc.v = 1, p4.tc.u = 1, p4.tc.v = 0;
  852.     device_draw_primitive(device, &p1, &p2, &p3);
  853.     device_draw_primitive(device, &p3, &p4, &p1);
  854. }
  855.  
  856. void draw_box(device_t *device, float theta) {
  857.     matrix_t m;
  858.     matrix_set_rotate(&m, -1, -0.5, 1, theta);
  859.     device->transform.world = m;
  860.     transform_update(&device->transform);
  861.     draw_plane(device, 0, 1, 2, 3);
  862.     draw_plane(device, 4, 5, 6, 7);
  863.     draw_plane(device, 0, 4, 5, 1);
  864.     draw_plane(device, 1, 5, 6, 2);
  865.     draw_plane(device, 2, 6, 7, 3);
  866.     draw_plane(device, 3, 7, 4, 0);
  867. }
  868.  
  869. void camera_at_zero(device_t *device, float x, float y, float z) {
  870.     point_t eye = { x, y, z, 1 }, at = { 0, 0, 0, 1 }, up = { 0, 0, 1, 1 };
  871.     matrix_set_lookat(&device->transform.view, &eye, &at, &up);
  872.     transform_update(&device->transform);
  873. }
  874.  
  875. void init_texture(device_t *device) {
  876.     static IUINT32 texture[256][256];
  877.     int i, j;
  878.     for (j = 0; j < 256; j++) {
  879.         for (i = 0; i < 256; i++) {
  880.             int x = i / 32, y = j / 32;
  881.             texture[j][i] = ((x + y) & 1)? 0xffffff : 0x3fbcef;
  882.         }
  883.     }
  884.     device_set_texture(device, texture, 256 * 4, 256, 256);
  885. }
  886.  
  887. int main(void)
  888. {
  889.     device_t device;
  890.     int states[] = { RENDER_STATE_TEXTURE, RENDER_STATE_COLOR, RENDER_STATE_WIREFRAME };
  891.     int indicator = 0;
  892.     int kbhit = 0;
  893.     float alpha = 1;
  894.     float pos = 3.5;
  895.  
  896.     TCHAR *title = _T("Mini3d (software render tutorial) - ")
  897.         _T("Left/Right: rotation, Up/Down: forward/backward, Space: switch state");
  898.  
  899.     if (screen_init(800, 600, title))
  900.         return -1;
  901.  
  902.     device_init(&device, 800, 600, screen_fb);
  903.     camera_at_zero(&device, 3, 0, 0);
  904.  
  905.     init_texture(&device);
  906.     device.render_state = RENDER_STATE_TEXTURE;
  907.  
  908.     while (screen_exit == 0 && screen_keys[VK_ESCAPE] == 0) {
  909.         screen_dispatch();
  910.         device_clear(&device, 1);
  911.         camera_at_zero(&device, pos, 0, 0);
  912.        
  913.         if (screen_keys[VK_UP]) pos -= 0.01f;
  914.         if (screen_keys[VK_DOWN]) pos += 0.01f;
  915.         if (screen_keys[VK_LEFT]) alpha += 0.01f;
  916.         if (screen_keys[VK_RIGHT]) alpha -= 0.01f;
  917.  
  918.         if (screen_keys[VK_SPACE]) {
  919.             if (kbhit == 0) {
  920.                 kbhit = 1;
  921.                 if (++indicator >= 3) indicator = 0;
  922.                 device.render_state = states[indicator];
  923.             }
  924.         }   else {
  925.             kbhit = 0;
  926.         }
  927.  
  928.         draw_box(&device, alpha);
  929.         screen_update();
  930.         Sleep(1);
  931.     }
  932.     return 0;
  933. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement