尝试渲染一个立方体时,所有的三角形都被渲染成一条线。

huangapple go评论111阅读模式
英文:

When trying to render a cube, all the triangles get rendered into a line

问题

以下是您提供的代码的翻译部分:

3D.h:

  1. #pragma once
  2. #include <vector>
  3. #include <cmath>
  4. #include "stdio.h"
  5. #include "SDL.h"
  6. struct Vector3
  7. {
  8. float x, y, z;
  9. };
  10. struct Triangle
  11. {
  12. Vector3 points[3];
  13. };
  14. struct Mesh
  15. {
  16. std::vector<Triangle> Triangles;
  17. };
  18. struct Matrix4x4
  19. {
  20. float m[4][4] = {0};
  21. };
  22. class Camera
  23. {
  24. public:
  25. Mesh cube;
  26. Matrix4x4 projectionMatrix;
  27. void init(int width, int height, float FOV, float nearPlane, float farPlane) {
  28. cube.Triangles = {
  29. { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f },
  30. { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f },
  31. { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
  32. { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
  33. { 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
  34. { 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
  35. { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f },
  36. { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f },
  37. { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
  38. { 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
  39. { 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f },
  40. { 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },
  41. };
  42. float fovRad = 1.0f / tanf(FOV * 0.5f / 180.0f * 3.14159f);
  43. projectionMatrix.m[0][0] = (float)(height/width)*fovRad;
  44. projectionMatrix.m[1][1] = fovRad;
  45. projectionMatrix.m[2][2] = farPlane / (farPlane - nearPlane);
  46. projectionMatrix.m[3][2] = (-farPlane * nearPlane) / (farPlane - nearPlane);
  47. projectionMatrix.m[2][3] = 1.0f;
  48. projectionMatrix.m[3][3] = 0.0f;
  49. }
  50. //vector<Triangle2D> render(int width, int height) {
  51. void renderTriangle(int width, int height, SDL_Renderer* renderer, Triangle tri) {
  52. Triangle triProjected, triTranslated;
  53. triTranslated = tri;
  54. triTranslated.points[0].z = tri.points[0].z + 3.0f;
  55. triTranslated.points[1].z = tri.points[1].z + 3.0f;
  56. triTranslated.points[2].z = tri.points[2].z + 3.0f;
  57. MultiplyMatrixVector(triTranslated.points[0], triProjected.points[0], projectionMatrix);
  58. MultiplyMatrixVector(triTranslated.points[1], triProjected.points[1], projectionMatrix);
  59. MultiplyMatrixVector(triTranslated.points[2], triProjected.points[2], projectionMatrix);
  60. triProjected.points[0].x += 1.0f;
  61. triProjected.points[0].y += 1.0f;
  62. triProjected.points[1].x += 1.0f;
  63. triProjected.points[1].y += 1.0f;
  64. triProjected.points[2].x += 1.0f;
  65. triProjected.points[2].y += 1.0f;
  66. triProjected.points[0].x *= 0.5f * (float)width;
  67. triProjected.points[0].y *= 0.5f * (float)height;
  68. triProjected.points[1].x *= 0.5f * (float)width;
  69. triProjected.points[1].y *= 0.5f * (float)height;
  70. triProjected.points[2].x *= 0.5f * (float)width;
  71. triProjected.points[2].y *= 0.5f * (float)height;
  72. SDL_RenderDrawLine(renderer, (int)triProjected.points[0].x, (int)triProjected.points[0].y, (int)triProjected.points[1].x, (int)triProjected.points[1].y);
  73. SDL_RenderDrawLine(renderer, (int)triProjected.points[1].x, (int)triProjected.points[1].y, (int)triProjected.points[2].x, (int)triProjected.points[2].y);
  74. SDL_RenderDrawLine(renderer, (int)triProjected.points[2].x, (int)triProjected.points[2].y, (int)triProjected.points[0].x, (int)triProjected.points[0].y);
  75. <details>
  76. <summary>英文:</summary>
  77. I have been doing [javidx9&#39;s 3D Graphics series](https://youtu.be/ih20l3pJoeU) except with SDL2 instead of the olcConsleGameEngine and I have gotten to the part before rotation. and all the triangles when rendered just turn into a line in the middle-ish of the screen
  78. Code
  79. 3D.h:

#pragma once
#include <vector>
#include <cmath>
#include "stdio.h"
#include "SDL.h"

struct Vector3
{
float x, y, z;
};

struct Triangle
{
Vector3 points[3];
};

struct Mesh
{
std::vector<Triangle> Triangles;
};

struct Matrix4x4
{
float m[4][4] = {0};
};

class Camera
{
public:
Mesh cube;
Matrix4x4 projectionMatrix;
void init(int width, int height, float FOV, float nearPlane, float farPlane) {
cube.Triangles = {
{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
{ 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
{ 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },
};
float fovRad = 1.0f / tanf(FOV * 0.5f / 180.0f * 3.14159f);
projectionMatrix.m[0][0] = (float)(height/width)fovRad;
projectionMatrix.m[1][1] = fovRad;
projectionMatrix.m[2][2] = farPlane / (farPlane - nearPlane);
projectionMatrix.m[3][2] = (-farPlane * nearPlane) / (farPlane - nearPlane);
projectionMatrix.m[2][3] = 1.0f;
projectionMatrix.m[3][3] = 0.0f;
}
//vector<Triangle2D> render(int width, int height) {
void renderTriangle(int width, int height, SDL_Renderer
renderer, Triangle tri) {
Triangle triProjected, triTranslated;
triTranslated = tri;
triTranslated.points[0].z = tri.points[0].z + 3.0f;
triTranslated.points[1].z = tri.points[1].z + 3.0f;
triTranslated.points[2].z = tri.points[2].z + 3.0f;
MultiplyMatrixVector(triTranslated.points[0], triProjected.points[0], projectionMatrix);
MultiplyMatrixVector(triTranslated.points[1], triProjected.points[1], projectionMatrix);
MultiplyMatrixVector(triTranslated.points[2], triProjected.points[2], projectionMatrix);
triProjected.points[0].x += 1.0f;
triProjected.points[0].y += 1.0f;
triProjected.points[1].x += 1.0f;
triProjected.points[1].y += 1.0f;
triProjected.points[2].x += 1.0f;
triProjected.points[2].y += 1.0f;
triProjected.points[0].x *= 0.5f * (float)width;
triProjected.points[0].y *= 0.5f * (float)height;
triProjected.points[1].x *= 0.5f * (float)width;
triProjected.points[1].y *= 0.5f * (float)height;
triProjected.points[2].x *= 0.5f * (float)width;
triProjected.points[2].y *= 0.5f * (float)height;
SDL_RenderDrawLine(renderer, (int)triProjected.points[0].x, (int)triProjected.points[0].y, (int)triProjected.points[1].x, (int)triProjected.points[1].y);
SDL_RenderDrawLine(renderer, (int)triProjected.points[1].x, (int)triProjected.points[1].y, (int)triProjected.points[2].x, (int)triProjected.points[2].y);
SDL_RenderDrawLine(renderer, (int)triProjected.points[2].x, (int)triProjected.points[2].y, (int)triProjected.points[0].x, (int)triProjected.points[0].y);
//exit(1);
}
void MultiplyMatrixVector(Vector3 &i, Vector3 &o, Matrix4x4 &m) {
o.x = i.x * m.m[0][0] + i.y * m.m[1][0] + i.z * m.m[2][0] + m.m[3][0];
o.y = i.x * m.m[0][1] + i.y * m.m[1][1] + i.z * m.m[2][1] + m.m[3][1];
o.z = i.x * m.m[0][2] + i.y * m.m[1][2] + i.z * m.m[2][2] + m.m[3][2];
float w = i.x * m.m[0][3] + i.y * m.m[1][3] + i.z * m.m[2][3] + m.m[3][3];

  1. if (w != 0.0f)
  2. {
  3. o.x /= w; o.y /= w; o.z /= w;
  4. }
  5. }

};

  1. Game.h:

#pragma once
#include "SDL.h"
#include "3D.h"

void draw2DTriangle(SDL_Renderer* renderer, int ax, int ay, int bx, int by, int cx, int cy)
{
SDL_RenderDrawLine(renderer, ax, ay, bx, by);
SDL_RenderDrawLine(renderer, bx, by, cx, cy);
SDL_RenderDrawLine(renderer, cx, cy, ax, ay);
}

class Game {
public:
Game() {};
~Game() {};

  1. void init(const char* title, int width, int height, bool fullscreen) {
  2. SDL_Init(SDL_INIT_EVERYTHING);
  3. int flags = SDL_WINDOW_SHOWN;
  4. if (fullscreen) {
  5. int flags = SDL_WINDOW_FULLSCREEN;
  6. }
  7. window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags);
  8. renderer = SDL_CreateRenderer(window, -1, 0);
  9. isRunning = true;
  10. camera.init(1280, 720, 90.0f, 0.1f, 1000.0f);
  11. };
  12. void update() {
  13. };
  14. void render() {
  15. SDL_RenderClear(renderer);
  16. SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
  17. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[0]);
  18. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[1]);
  19. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[2]);
  20. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[3]);
  21. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[4]);
  22. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[5]);
  23. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[6]);
  24. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[7]);
  25. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[8]);
  26. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[9]);
  27. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[10]);
  28. camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[11]);
  29. SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
  30. SDL_RenderPresent(renderer);
  31. };
  32. void handleEvents() {
  33. SDL_Event event;
  34. SDL_PollEvent(&amp;event);
  35. switch (event.type) {
  36. case SDL_QUIT:
  37. isRunning = false;
  38. break;
  39. }
  40. };
  41. void clean() {
  42. SDL_DestroyWindow(window);
  43. SDL_DestroyRenderer(renderer);
  44. SDL_Quit();
  45. };
  46. bool running() { return isRunning; };

private:
bool isRunning{};
SDL_Window* window{};
SDL_Renderer* renderer{};
Camera camera;
};

  1. I have debugged a bit and eliminated the MultiplyMatrixVector, so I think its not that at the least
  2. </details>
  3. # 答案1
  4. **得分**: 2
  5. `Camera::init` 中,你有这一行:
  6. ```cpp
  7. projectionMatrix.m[0][0] = (float)(height/width)*fovRad;

不幸的是,(float)(height/width) 并不会产生你想要的结果。它首先执行整数除法,然后将结果转换为 float。只需用以下其中一种方式替换该行:

  1. // C++ 风格的类型转换
  2. projectionMatrix.m[0][0] = static_cast<float>(height) / width * fovRad;
  3. // 隐式类型转换
  4. projectionMatrix.m[0][0] = fovRad * height / width;
  5. // C 风格的类型转换(表达式不需要加括号)
  6. projectionMatrix.m[0][0] = (float)height / width * fovRad;

或者,由于你只需要 heightwidth 的比例,你可以将这个比例作为参数传入:

  1. void init(float aspectRatio, float FOV, float nearPlane, float farPlane) {
  2. // ...
  3. projectionMatrix.m[0][0] = aspectRatio * fovRad;
  4. // ...
  5. }
  6. // ...
  7. float aspectRatio = static_cast<float>(height) / width;
  8. camera.init(aspectRatio, 90.0f, 0.1f, 1000.0f);
英文:

In Camera::init, you have this line:

  1. projectionMatrix.m[0][0] = (float)(height/width)*fovRad;

Unfortunately, (float)(height/width) does not do what you want. It does an integer division first and then casts the result to float. Just replace the line with either one of these:

  1. // C++ style cast
  2. projectionMatrix.m[0][0] = static_cast&lt;float&gt;(height) / width * fovRad;
  3. // Implicit cast
  4. projectionMatrix.m[0][0] = fovRad * height / width;
  5. // C style cast (no need to parenthesize the expression)
  6. projectionMatrix.m[0][0] = (float)height / width * fovRad;

Alternatively, since you don't need height and width for anything other than their ratio, you could just take that ratio as a parameter:

  1. void init(float aspectRatio, float FOV, float nearPlane, float farPlane) {
  2. // ...
  3. projectionMatrix.m[0][0] = aspectRatio * fovRad;
  4. // ...
  5. }
  6. // ...
  7. float aspectRatio = static_cast&lt;float&gt;(height) / width;
  8. camera.init(aspectRatio, 90.0f, 0.1f, 1000.0f);

huangapple
  • 本文由 发表于 2023年6月30日 02:10:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76583618.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定