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

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

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&#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

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(&amp;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;

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

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&lt;float&gt;(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&lt;float&gt;(height) / width;
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:

确定