You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SFML球体投影出现拉伸变形,求助问题原因及解决方法

问题分析与修复

你的球体出现左右凸起的核心原因是射线生成逻辑错误:代码中错误地将角度变量i、j直接加到了3D点的坐标上,导致每条射线的起点并非相机原点(0,0,0),而是偏移了一个与角度相关的数值,最终造成画面畸变。

关键错误点

  1. 射线坐标计算错误:
    原代码中生成射线点的代码:

    S_Point((-cos(i) * l) + i - (PI / 2), (cos(j) * l) - j + (PI / 2), sin(j) * l)
    

    这里的+ i - (PI/2)和- j + (PI/2)完全是多余的,属于将角度值错误地当作位置偏移量,破坏了射线从相机原点出发的逻辑。

  2. MUL宏未定义:代码中使用了s_l (6 * MUL)和s_h (6 * MUL),但未定义MUL,会导致编译错误。

修复后的完整代码

#include <stdio.h>
#include <math.h>
#include "SFML/Graphics.hpp"

using namespace sf;

#define MUL 100  // 补充定义缩放因子,可根据需求调整
#define s_l (6 * MUL)
#define s_h (6 * MUL)

// 3d Point in space
struct S_Point {
    double x, y, z;
};

// Distance from a point to another point
double p_dist(S_Point p, S_Point s) {
    return sqrt(pow(s.x - p.x, 2) + pow(s.y - p.y, 2) + pow(s.z - p.z, 2));
}

int main() {
    // Main Window
    RenderWindow window(VideoMode(s_l, s_h), "Conecept", Style::Default);

    // Sphere position (0,0,100)
    S_Point sphere{0, 0, 100};

    Image image;
    image.create(s_l, s_h, Color::Black);
    Texture texture;
    texture.create(s_l, s_h);
    Sprite pic;
    
    {
        const double leng = 200.0;
        const double PI = 3.14159265358979323846;
        // 水平方向角度:从PI/3到2PI/3(覆盖60度视场)
        const double angle_step_x = (2 * PI / 3 - PI / 3) / (s_l - 1);
        // 垂直方向角度:从PI/3到2PI/3
        const double angle_step_y = (2 * PI / 3 - PI / 3) / (s_h - 1);

        for (int x = 0; x < s_l; x++) {
            double i = PI / 3 + x * angle_step_x;
            for (int y = 0; y < s_h; y++) {
                double j = PI / 3 + y * angle_step_y;
                for (double l = 0; l <= leng; l += 1.0) {
                    // 修正射线生成:从相机原点(0,0,0)出发,沿角度i、j方向延伸
                    S_Point ray_point{
                        -cos(i) * l,
                        cos(j) * l,
                        sin(j) * l
                    };
                    if (p_dist(ray_point, sphere) < 50.0) {
                        // 根据距离设置灰度值
                        uint8_t brightness = static_cast<uint8_t>((-255.0 / leng * l) + 255);
                        image.setPixel(x, y, Color(brightness, brightness, brightness, 255));
                        break;
                    }
                }
            }
        }
    }

    printf("Done!\n");
    texture.update(image);
    pic.setTexture(texture);
    
    // Main Window Loop
    while (window.isOpen()) {
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed) {
                window.close();
            }
        }

        window.clear();
        window.draw(pic);
        window.display();
    }

    return 0;
}

额外优化说明

  1. 将循环变量调整为先遍历像素索引,再计算对应角度,逻辑更清晰,避免原代码中x++和y++与角度循环绑定的潜在问题。
  2. 显式计算角度步长,确保像素与角度的映射完全均匀。
  3. 修正了Colour为SFML标准的Color(原代码中拼写错误,部分编译器可能不兼容)。
  4. 将亮度计算转为浮点运算后再强制类型转换,避免整数除法导致的精度丢失。

内容的提问来源于stack exchange,提问作者ItsThatSpicymeme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:16:08