RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-541064

Dimka4369's questions

Martin Hope
Dimka4369
Asked: 2023-12-11 01:43:52 +0000 UTC

为什么立方体绘制不正确?

  • 9

我正在尝试用 C++ 绘制一个立方体,但它看起来不太像我想要的那样。我正在使用公式将球坐标转换为笛卡尔(直角)坐标。这个想法是找到光线从窗口的每个像素照射到的位置。如果光线击中物体,则绘制该像素。

以下是代码的主要部分:

int Screen[320 * 180 * 3] = { 0 };
int World[160][90][90] = { 0 };
int X1 = 0;
int Y1 = 0;
int BasicAngle = 0;

    World[10][10][0] = 1;
    World[10][10][10] = 1;
    World[20][20][20] = 1;
    World[40][40][40] = 1;
    World[40][20][10] = 1;

    createWindow(0, 0, 320, 180);

        for (int y = 0; y < 90; y++)
        {
            double B = (90.0 / 90.0) * y;
            for (int x = 0; x < 160; x++)
            {
                double A = (90.0 / 160.0) * x + BasicAngle;
                for (int R = 0; R < 100; R++)
                {
                    int X = X1 + R * sin(B * M_PI / 180) * cos(A * M_PI / 180);
                    int Y = Y1 + R * sin(B * M_PI / 180) * sin(A * M_PI / 180);
                    int Z = R * cos(B * M_PI / 180);

                    if (X < 160 && Y < 90 && X > -1 && Y > -1 && Z > -1 && Z < 90)
                    {
                        if (World[X][Y][Z] == 1)
                        {
                            R = 100;

                            Screen[y * 320 * 3 + (x + 160) * 3 + 0] = 255; // red правый
                            Screen[y * 320 * 3 + (x + 160) * 3 + 1] = 0; // green правый
                            Screen[y * 320 * 3 + (x + 160) * 3 + 2] = 0; // blue правый



                            Screen[Y * 320 * 3 + X * 3 + 0] = 255; // red левый
                            Screen[Y * 320 * 3 + X * 3 + 1] = 0; // green левый
                            Screen[Y * 320 * 3 + X * 3 + 2] = 0; // blue левый
                        }
                        else
                        {
                            Screen[Y * 320 * 3 + X * 3 + 0] = 0; // red левый
                            Screen[Y * 320 * 3 + X * 3 + 1] = 255; // green левый
                            Screen[Y * 320 * 3 + X * 3 + 2] = 0; // blue левый
                        }
                    }
                }
            }
        }

是什么导致了这种扭曲?如果有其他方法来发射光束,我可能会考虑这种可能性。也许问题在于确定射线和物体的交点?我想以体素的形式存储对象,然后从立方体中组装一些有趣的东西,而不是多边形。

添加。

按空格键时将截取屏幕截图。

#include <Windows.h>
#include <iostream>
#include <fstream>
#include <cmath>
double M_PI = 3.1415926535;

void save1dArrayToBMP(const char* path, int* buffer, int width, int height)
{
    std::ofstream file;
    file.open(path, std::ios::out | std::ios::binary);

    unsigned char bmpPadding[3] = { 0, 0, 0 };
    const int paddingAmount = (4 - (width * 3) % 4) % 4;

    const int fileHeaderSize = 14;
    const int informationHeaderSize = 40;
    const int fileSize = fileHeaderSize + informationHeaderSize + width * height * 4;

    unsigned char fileHeader[fileHeaderSize];

    //File type
    fileHeader[0] = 'B';
    fileHeader[1] = 'M';
    // File size
    fileHeader[2] = fileSize;
    fileHeader[3] = fileSize >> 8;
    fileHeader[4] = fileSize >> 16;
    fileHeader[5] = fileSize >> 24;
    //Reserved 1 (not used)
    fileHeader[6] = 0;
    fileHeader[7] = 0;
    //Reserved 2 (not used)
    fileHeader[8] = 0;
    fileHeader[9] = 0;
    //Pixel data offset
    fileHeader[10] = fileHeaderSize + informationHeaderSize;
    fileHeader[11] = 0;
    fileHeader[12] = 0;
    fileHeader[13] = 0;

    unsigned char informationHeader[informationHeaderSize];

    //Header size
    informationHeader[0] = informationHeaderSize;
    informationHeader[1] = 0;
    informationHeader[2] = 0;
    informationHeader[3] = 0;
    //Image width
    informationHeader[4] = width;
    informationHeader[5] = width >> 8;
    informationHeader[6] = width >> 16;
    informationHeader[7] = width >> 24;
    //Image height
    informationHeader[8] = height;
    informationHeader[9] = height >> 8;
    informationHeader[10] = height >> 16;
    informationHeader[11] = height >> 24;
    //Planes
    informationHeader[12] = 1;
    informationHeader[13] = 0;
    //Bits per pixels (RGB)
    informationHeader[14] = 24;
    informationHeader[15] = 0;
    //Compression (no compression)
    informationHeader[16] = 0;
    informationHeader[17] = 0;
    informationHeader[18] = 0;
    informationHeader[19] = 0;
    //Image size (no compression)
    informationHeader[20] = 0;
    informationHeader[21] = 0;
    informationHeader[22] = 0;
    informationHeader[23] = 0;
    //X pixels per meter (not specified)
    informationHeader[24] = 0;
    informationHeader[25] = 0;
    informationHeader[26] = 0;
    informationHeader[27] = 0;
    //Y pixels per meter (not specified)
    informationHeader[28] = 0;
    informationHeader[29] = 0;
    informationHeader[30] = 0;
    informationHeader[31] = 0;
    //Total colors (colors palette not used)
    informationHeader[32] = 0;
    informationHeader[33] = 0;
    informationHeader[34] = 0;
    informationHeader[35] = 0;
    //Important colors (Generally ignored)
    informationHeader[36] = 0;
    informationHeader[37] = 0;
    informationHeader[38] = 0;
    informationHeader[39] = 0;

    file.write(reinterpret_cast<char*>(fileHeader), fileHeaderSize);
    file.write(reinterpret_cast<char*>(informationHeader), informationHeaderSize);
    //file.write(reinterpret_cast<char*>(buffer), width * height * 4);

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            unsigned char r = static_cast<unsigned char>(buffer[(height - y - 1) * width * 3 + x * 3 + 0]);
            unsigned char g = static_cast<unsigned char>(buffer[(height - y - 1) * width * 3 + x * 3 + 1]);
            unsigned char b = static_cast<unsigned char>(buffer[(height - y - 1) * width * 3 + x * 3 + 2]);

            unsigned char color[] = { b, g, r };


            file.write(reinterpret_cast<char*>(color), 3);
        }
        file.write(reinterpret_cast<char*>(bmpPadding), paddingAmount);
    }

    file.close();

    std::cout << "File created\n";
}

int World[160][90][90] = { 0 };
int X1 = 0;
int Y1 = 0;
int BasicAngle = 0;
int Screen[320 * 180 * 3] = { 0 };

void drawLine(int x1, int y1, int z1, int x2, int y2, int z2, int ScreenX, int ScreenY) {
    int dx = x2 - x1;
    int dy = y2 - y1;
    int dz = z2 - z1;

    int steps = max(max(abs(dx), abs(dy)), abs(dz));  // Выбираем максимальное изменение по координатам как количество шагов

    int xInc = dx / steps;
    int yInc = dy / steps;
    int zInc = dz / steps;

    int x = x1;
    int y = y1;
    int z = z1;

    for (int i = 0; i <= steps; i++) {

        if (x < 160 && y < 90 && x > -1 && y > -1 && z > -1 && z < 90)
        {
            if (World[x][y][z] == 1)
            {
                i = steps;

                Screen[ScreenY * 320 * 3 + (ScreenX + 160) * 3 + 0] = 255; // red
                Screen[ScreenY * 320 * 3 + (ScreenX + 160) * 3 + 1] = 0; // green
                Screen[ScreenY * 320 * 3 + (ScreenX + 160) * 3 + 2] = 0; // blue

                Screen[y * 320 * 3 + x * 3 + 0] = 255; // red
                Screen[y * 320 * 3 + x * 3 + 1] = 0; // green
                Screen[y * 320 * 3 + x * 3 + 2] = 0; // blue
            }
            else
            {
                Screen[y * 320 * 3 + x * 3 + 0] = 0; // red
                Screen[y * 320 * 3 + x * 3 + 1] = 255; // green
                Screen[y * 320 * 3 + x * 3 + 2] = 0; // blue
            }
        }
        x += xInc;
        y += yInc;
        z += zInc;
    }
}

int main()
{
    World[10][10][0] = 1;
    World[10][10][10] = 1;
    World[20][20][20] = 1;
    World[40][40][40] = 1;
    World[40][20][10] = 1;
    while (true)
    {
        for (int i = 0; i < 320 * 180 * 3; i++)
        {
            Screen[i] = 0;
        }
        for (int x = 0; x < 320; x++)
        {
            Screen[90 * 320 * 3 + x * 3 + 0] = 255; // red
            Screen[90 * 320 * 3 + x * 3 + 1] = 255; // green
            Screen[90 * 320 * 3 + x * 3 + 2] = 255; // blue
        }
        for (int y = 0; y < 180; y++)
        {
            Screen[y * 320 * 3 + 160 * 3 + 0] = 255; // red
            Screen[y * 320 * 3 + 160 * 3 + 1] = 255; // green
            Screen[y * 320 * 3 + 160 * 3 + 2] = 255; // blue
        }
        for (int y = 0; y < 90; y++)
        {
            double B = (90.0 / 90.0) * y;
            for (int x = 0; x < 160; x++)
            {
                double A = (90.0 / 160.0) * x + BasicAngle;

                int R = 100;
                int X = X1 + R * sin(B * M_PI / 180) * cos(A * M_PI / 180);
                int Y = Y1 + R * sin(B * M_PI / 180) * sin(A * M_PI / 180);
                int Z = R * cos(B * M_PI / 180);

                drawLine(X1, Y1, 0, X, Y, Z, x, y);
            }
        }
        if (GetAsyncKeyState(VK_SPACE))
        {
            save1dArrayToBMP("Frame.bmp", Screen, 320, 180);
            Sleep(100);
        }
    }
}

12/23/2023:我们通过三角形的相似性取得了一些结果。到目前为止我只在 2D 中尝试过。它看起来像这样:

添加了 Bresenham 算法:

使用该算法的面积仅减少。视角会影响中心光线的分组,但我不能无限地减小角度(增加焦距、腿)。你能为这个做什么?(没有算法的代码)

int Focus = 32;
for (int x = -15; x < 16; x++)
{
    double L = sqrt(Focus * Focus + x * x);
    for (double Lenght = 0; Lenght < 100; Lenght += 0.1)
    {
        double coeff = Lenght / L;
        int X = x * coeff;
        int Y = Focus * coeff;

        Screen[Y * 320 * 3 + (X + 160) * 3 + 1] = 255;
    }
}

这里的代码中有从-15到16,因此有空,但是从-159到160是必要的。我弄清楚了并切换到3D

只需 1 行即可转换为 3D:

double L = sqrt(Focus * Focus + x * x + y * y);

一个非常好的结果,我不喜欢的是立方体的波纹度,不均匀的边缘。

我无法在 3D 中添加 Bresenham 算法,我不明白为什么。但该步骤提高了清晰度,但性能却显着下降。现在步长是0.01,但我想要0.5

我无法理解以下内容:

  1. 为什么布雷森纳姆算法不起作用?
  2. 如果我需要获得坐标而不是矩阵,如何将坐标乘以矩阵(以旋转相机)?
  3. Как можно обойти искажение без шага? Очень сильно упала производительность.

30.12.23 Последние результаты такие, для разрешения 640х480 дальность прорисовки от 130 до примерно 150 единиц, слева направо:

  1. 8.323 с. (метод на подобии треугольников, шаг: 0.01)
  2. 9.648 с. (метод по уравнению прямой, шаг на умножении: 0.00001)
  3. 6.824 с. (метод по уравнению прямой, шаг на сложении: 0.00001)
  4. 0.479 с. (код Станислава, принцип я пока что не понял)

Нужно что-то такое:

во втором варианте я использую следующий способ:

в циклах for меняю endX и endY:

int aX = endX - startX;
int aY = endY - startY;
int aZ = endZ - startZ;

и после в цикле for меняю множитель (шаг):

int aX1 = aX * multiplier;
int aY1 = aY * multiplier;
int aZ1 = aZ * multiplier;

Шаг приходится уменьшать, чтобы избежать ошибок отрисовки. Чтобы отказаться от шага - нужно ориентироваться по сетке. Но тогда требуется для этого некоторая формула, которую я не знаю.

При этом сетка проходит по 0, по 1, по 2 и т.д., а куб находится между 0 и 1. В идеале сетка должна проходить по 0.5, по 1.5, 2.5 и т.д. - это уже задел на будущее

31.12: Попробовал я демонстрационный пример. Попробовал пример - не изучил, очень постараюсь с ним разобраться, т.к. хотелось бы менять размер сетки, для оптимизации по типу "Voxel Octrees". С примером работает в 20 раз быстрее, чем просто с шагом. При разрешении 640х480 всё хорошо, потому что соотношение сторон почти одинаковое, а вот при FHD и соотношении 16:9 уже начинаются проблемы:

Жёлтым это призма (угол обзора), красным сам куб. Пытался домножать aX (чуть выше) на какой-то коэффициент, однако не преуспел. Меняется пропорция по высоте или ширине (цифры, где я указал количество пикселей), однако левый-нижний угол и диагональ правого-верхнего угла продолжают различаться, что плохо. Пока что я не понимаю, что и на что требуется умножить?

c++
  • 2 个回答
  • 208 Views
Martin Hope
Dimka4369
Asked: 2023-11-24 17:32:49 +0000 UTC

旋转图像(矩阵)时如何去除点(空格)?

  • 6

我从这里获取了公式: https: //ru.wikipedia.org/wiki/Rotation_matrix 我正在尝试旋转图片,但我得到了白点,我玩了符号,但它没有帮助。这里:https: //ru.stackoverflow.com/questions/1063702/Recalculation-of-coordinates-when-rotating-an-image我读到了关于坐标计数的内容,我没有考虑到计数是从顶部开始的- 左角。这可能是一个四舍五入的问题,但对其进行操作并没有产生结果。需要改变什么?

int* Plane1 = new int[256 * 100 * 3];
int Angle = 20;

int main()
{
    readBMPTo1dArray("Helicopter.bmp", Plane1, 256, 100);

    int red = 0;
    int green = 0;
    int blue = 0;

    while (true)
    {
        HWND hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED, L"STATIC", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
        SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);
        HDC hdc = GetDC(hwnd);
        UpdateWindow(hwnd);
        Angle = Angle + 1;
        if (Angle >= 360)
        {
            Angle = 0;
        }
        UpdateWindow(hwnd);
        for (int y = 0; y < 100; y++)
        {
            for (int x = 0; x < 256; x++)
            {
                red = (Plane1[y * 256 * 3 + x * 3 + 0] + 256) % 256;
                green = (Plane1[y * 256 * 3 + x * 3 + 1] + 256) % 256;
                blue = (Plane1[y * 256 * 3 + x * 3 + 2] + 256) % 256;

                COLORREF color = RGB(red, green, blue);

                int x1 = x * cos(Angle * M_PI / 180) - y * sin(Angle * M_PI / 180);
                int y1 = x * sin(Angle * M_PI / 180) + y * cos(Angle * M_PI / 180);

                SetPixel(hdc, x1 + 500, y1 + 500, color);
            }
        }
        Sleep(1000);
        UpdateWindow(hwnd);
    }
} 

在此输入图像描述

在此输入图像描述

在此输入图像描述

c++
  • 1 个回答
  • 32 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5