英文:
When trying to render a cube, all the triangles get rendered into a line
问题
以下是您提供的代码的翻译部分:
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);
<details>
<summary>英文:</summary>
I have been doing [javidx9'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
Code
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];
if (w != 0.0f)
{
o.x /= w; o.y /= w; o.z /= w;
}
}
};
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() {};
void init(const char* title, int width, int height, bool fullscreen) {
SDL_Init(SDL_INIT_EVERYTHING);
int flags = SDL_WINDOW_SHOWN;
if (fullscreen) {
int flags = SDL_WINDOW_FULLSCREEN;
}
window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags);
renderer = SDL_CreateRenderer(window, -1, 0);
isRunning = true;
camera.init(1280, 720, 90.0f, 0.1f, 1000.0f);
};
void update() {
};
void render() {
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[0]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[1]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[2]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[3]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[4]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[5]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[6]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[7]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[8]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[9]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[10]);
camera.renderTriangle(1280, 720, renderer, camera.cube.Triangles[11]);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderPresent(renderer);
};
void handleEvents() {
SDL_Event event;
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
isRunning = false;
break;
}
};
void clean() {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
};
bool running() { return isRunning; };
private:
bool isRunning{};
SDL_Window* window{};
SDL_Renderer* renderer{};
Camera camera;
};
I have debugged a bit and eliminated the MultiplyMatrixVector, so I think its not that at the least
</details>
# 答案1
**得分**: 2
在 `Camera::init` 中,你有这一行:
```cpp
projectionMatrix.m[0][0] = (float)(height/width)*fovRad;
不幸的是,(float)(height/width)
并不会产生你想要的结果。它首先执行整数除法,然后将结果转换为 float
。只需用以下其中一种方式替换该行:
// C++ 风格的类型转换
projectionMatrix.m[0][0] = static_cast<float>(height) / width * fovRad;
// 隐式类型转换
projectionMatrix.m[0][0] = fovRad * height / width;
// C 风格的类型转换(表达式不需要加括号)
projectionMatrix.m[0][0] = (float)height / width * fovRad;
或者,由于你只需要 height
和 width
的比例,你可以将这个比例作为参数传入:
void init(float aspectRatio, float FOV, float nearPlane, float farPlane) {
// ...
projectionMatrix.m[0][0] = aspectRatio * fovRad;
// ...
}
// ...
float aspectRatio = static_cast<float>(height) / width;
camera.init(aspectRatio, 90.0f, 0.1f, 1000.0f);
英文:
In Camera::init
, you have this line:
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:
// C++ style cast
projectionMatrix.m[0][0] = static_cast<float>(height) / width * fovRad;
// Implicit cast
projectionMatrix.m[0][0] = fovRad * height / width;
// C style cast (no need to parenthesize the expression)
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:
void init(float aspectRatio, float FOV, float nearPlane, float farPlane) {
// ...
projectionMatrix.m[0][0] = aspectRatio * fovRad;
// ...
}
// ...
float aspectRatio = static_cast<float>(height) / width;
camera.init(aspectRatio, 90.0f, 0.1f, 1000.0f);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论