model3d.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include "vc.c"
  2. #define WIDTH 960
  3. #define HEIGHT 720
  4. #define BACKGROUND_COLOR 0xFF181818
  5. #define PI 3.14159265359
  6. float sqrtf(float x);
  7. float atan2f(float y, float x);
  8. float sinf(float x);
  9. float cosf(float x);
  10. static uint32_t pixels[WIDTH*HEIGHT];
  11. static float zbuffer[WIDTH*HEIGHT] = {0};
  12. static float angle = 0;
  13. typedef struct {
  14. float x, y;
  15. } Vector2;
  16. static Vector2 make_vector2(float x, float y)
  17. {
  18. Vector2 v2;
  19. v2.x = x;
  20. v2.y = y;
  21. return v2;
  22. }
  23. typedef struct {
  24. float x, y, z;
  25. } Vector3;
  26. static Vector3 make_vector3(float x, float y, float z)
  27. {
  28. Vector3 v3;
  29. v3.x = x;
  30. v3.y = y;
  31. v3.z = z;
  32. return v3;
  33. }
  34. static Vector2 project_3d_2d(Vector3 v3)
  35. {
  36. return make_vector2(v3.x/v3.z, v3.y/v3.z);
  37. }
  38. static Vector2 project_2d_scr(Vector2 v2)
  39. {
  40. return make_vector2((v2.x + 1)/2*WIDTH, (1 - (v2.y + 1)/2)*HEIGHT);
  41. }
  42. static Vector3 rotate_y(Vector3 p, float delta_angle)
  43. {
  44. float angle = atan2f(p.z, p.x) + delta_angle;
  45. float mag = sqrtf(p.x*p.x + p.z*p.z);
  46. return make_vector3(cosf(angle)*mag, p.y, sinf(angle)*mag);
  47. }
  48. Olivec_Canvas vc_render(float dt)
  49. {
  50. angle += 0.25*PI*dt;
  51. Olivec_Canvas oc = olivec_canvas(pixels, WIDTH, HEIGHT, WIDTH);
  52. olivec_fill(oc, BACKGROUND_COLOR);
  53. for (size_t i = 0; i < WIDTH*HEIGHT; ++i) zbuffer[i] = 0;
  54. for (size_t i = 0; i < faces_count; ++i) {
  55. int a = faces[i][0];
  56. int b = faces[i][1];
  57. int c = faces[i][2];
  58. Vector3 v1 = rotate_y(make_vector3(vertices[a][0], vertices[a][1], vertices[a][2]), angle);
  59. Vector3 v2 = rotate_y(make_vector3(vertices[b][0], vertices[b][1], vertices[b][2]), angle);
  60. Vector3 v3 = rotate_y(make_vector3(vertices[c][0], vertices[c][1], vertices[c][2]), angle);
  61. v1.z += 1.5; v2.z += 1.5; v3.z += 1.5;
  62. Vector2 p1 = project_2d_scr(project_3d_2d(v1));
  63. Vector2 p2 = project_2d_scr(project_3d_2d(v2));
  64. Vector2 p3 = project_2d_scr(project_3d_2d(v3));
  65. int x1 = p1.x;
  66. int x2 = p2.x;
  67. int x3 = p3.x;
  68. int y1 = p1.y;
  69. int y2 = p2.y;
  70. int y3 = p3.y;
  71. int lx, hx, ly, hy;
  72. if (olivec_normalize_triangle(oc.width, oc.height, x1, y1, x2, y2, x3, y3, &lx, &hx, &ly, &hy)) {
  73. for (int y = ly; y <= hy; ++y) {
  74. for (int x = lx; x <= hx; ++x) {
  75. int u1, u2, det;
  76. olivec_barycentric(x1, y1, x2, y2, x3, y3, x, y, &u1, &u2, &det);
  77. int u3 = det - u1 - u2;
  78. if ((OLIVEC_SIGN(int, u1) == OLIVEC_SIGN(int, det) || u1 == 0) && (OLIVEC_SIGN(int, u2) == OLIVEC_SIGN(int, det) || u2 == 0) && (OLIVEC_SIGN(int, u3) == OLIVEC_SIGN(int, det) || u3 == 0)) {
  79. float z = 1/v1.z*u1/det + 1/v2.z*u2/det + 1/v3.z*u3/det;
  80. // TODO: implement near/far clipping planes
  81. if (z > zbuffer[y*WIDTH + x]) {
  82. zbuffer[y*WIDTH + x] = z;
  83. OLIVEC_PIXEL(oc, x, y) = mix_colors3(0xFF1818FF, 0xFF18FF18, 0xFFFF1818, u1, u2, det);
  84. z = 1.0f/z;
  85. if (z >= 1.0) {
  86. z -= 1.0;
  87. uint32_t v = z*255;
  88. if (v > 255) v = 255;
  89. olivec_blend_color(&OLIVEC_PIXEL(oc, x, y), (v<<(3*8)));
  90. }
  91. }
  92. }
  93. }
  94. }
  95. }
  96. }
  97. return oc;
  98. }