Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

sf::IntRect pochylonego chunka mapy 3D w płaszczyźnie SFMLA 2D

Ostatnio zmodyfikowano 2026-10-28 20:46
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
sf::IntRect pochylonego chunka mapy 3D w płaszczyźnie SFMLA 2D
» 2026-10-28 17:40:39
Cześć! :D
Piszę mapę 2.5D w SFML 3.1. Mam problem z wyznaczeniem granic każdego chunka. Mapa jest odchylona o 45 stopni w osi X.
Potrzebuję wyznaczyć granice chunku mapy w płaszczyźnie SFMLA XY tak, żeby sprawdzać czy chunk mieści się na ekranie.

C/C++
sf::IntRect Chunk::getRect() {
   
   
sf::IntRect rect;
   
rect.position.x = _coords.x * tilesCols * Tile::tileSize;
   
rect.position.y = _coords.y * tilesRows * Tile::tileSize;
   
rect.size.x = tilesCols * Tile::tileSize;
   
rect.size.y = tilesRows * Tile::tileSize;
   
   
return rect;
   
}

C/C++
// vertex3D.vert
uniform vec2 cameraCenter;
uniform float cameraDistance;
uniform float cameraAngle;
uniform float aspect;


varying vec2 worldPos;

void main()
{
   
float angle = radians( cameraAngle );
   
float s = sin( angle );
   
float c = cos( angle );
   
   
// Rotate around the center of the view
   
vec4 pos = gl_Vertex;
   
pos.xy -= cameraCenter;
   
   
// Rotate around the X-axis
   
vec3 rotated = vec3(
   
pos.x,
   
pos.y * c,
   
pos.y * s
    );
   
   
// Camera looks along the negative Z-axis
   
float depth = cameraDistance - rotated.z;
   
   
// 60-degree perspective
   
float f = 1.7320508; // 1 / tan(30 stopni)
   
   
gl_Position = vec4(
   
rotated.x * f / aspect,
   
- rotated.y * f,
   
depth - 0.2,
   
depth
    );
   
   
gl_TexCoord[ 0 ] = gl_TextureMatrix[ 0 ] * gl_MultiTexCoord0;
   
worldPos = gl_Vertex.xy;
   
gl_FrontColor = gl_Color;
}
P-184859
tBane
Temat założony przez niniejszego użytkownika
» 2026-10-28 18:01:09
C/C++
sf::View view = Main::render_window->getView();
sf::FloatRect cameraRect( view.getCenter() - view.getSize() * 0.5f, view.getSize() );
sf::FloatRect chunkRect( chunk->getRect() );

if( cameraRect.findIntersection( chunkRect ) ) {
   
chunk->setVisible();
}

C/C++
sf::IntRect Chunk::getRect() {
   
   
sf::IntRect rect;
   
rect.position.x = _coords.x * tilesCols * Tile::tileSize;
   
rect.position.y = _coords.y * tilesRows * Tile::tileSize;
   
rect.size.x = tilesCols * Tile::tileSize;
   
rect.size.y = tilesRows * Tile::tileSize;
   
   
// TO-DO - to delete
   
if( MapEditor::editor->_camera ) {
       
sf::View view = Main::render_window->getView();
       
sf::Vector2f cameraCenter = view.getCenter();
       
sf::Vector2u windowSize = Main::render_window->getSize();
       
       
float zoom = MapEditor::editor->_camera->_zoom;
       
       
if( windowSize.x == 0 || windowSize.y == 0 || zoom <= 0.f )
           
 return sf::IntRect();
       
       
sf::Vector2f size( float( windowSize.x ) / zoom, float( windowSize.y ) / zoom );
       
float aspect = float( windowSize.x ) / windowSize.y;
       
float fov = 60.f;
       
float distance =( size.y * 0.5f ) / std::tan( fov * 0.5f * 3.14159265f / 180.f );
       
float angle = sf::degrees( MapEditor::editor->_camera->_angle ).asRadians();
       
       
float s = std::sin( angle );
       
float c = std::cos( angle );
       
float f = 1.7320508f;
       
       
float width = float( tilesCols * Tile::tileSize );
       
float height = float( tilesRows * Tile::tileSize );
       
       
float x = float( _coords.x ) * width;
       
float y = float( _coords.y ) * height;
       
       
const sf::Vector2f points[ ] = {
            {
x, y },
           
{ x + width, y },
           
{ x + width, y + height },
           
{ x, y + height }
        }
;
       
       
float minX = std::numeric_limits < float >::max();
       
float minY = std::numeric_limits < float >::max();
       
float maxX = std::numeric_limits < float >::lowest();
       
float maxY = std::numeric_limits < float >::lowest();
       
       
for( const auto & point: points ) {
           
float px = point.x - cameraCenter.x;
           
float py = point.y - cameraCenter.y;
           
           
float rotatedX = px;
           
float rotatedY = py * c;
           
float rotatedZ = py * s;
           
           
float depth = distance - rotatedZ;
           
           
// Przy przecięciu płaszczyzny bliskiej nie odrzucamy chunka.
           
if( depth <= 0.1f ) {
               
minX = cameraCenter.x - size.x * 0.5f;
               
minY = cameraCenter.y - size.y * 0.5f;
               
maxX = cameraCenter.x + size.x * 0.5f;
               
maxY = cameraCenter.y + size.y * 0.5f;
               
break;
           
}
           
           
// Projekcja jak w shaderze + dzielenie przez W.
           
float ndcX =( rotatedX * f / aspect ) / depth;
           
float ndcY =( - rotatedY * f ) / depth;
           
           
// Przeliczenie do jednostek widoku, nie pikseli okna.
           
float projectedX = cameraCenter.x + ndcX * size.x * 0.5f;
           
float projectedY = cameraCenter.y - ndcY * size.y * 0.5f;
           
           
minX = std::min( minX, projectedX );
           
minY = std::min( minY, projectedY );
           
maxX = std::max( maxX, projectedX );
           
maxY = std::max( maxY, projectedY );
       
}
       
       
int left = int( std::floor( minX ) );
       
int top = int( std::floor( minY ) );
       
int right = int( std::ceil( maxX ) );
       
int bottom = int( std::ceil( maxY ) );
       
       
return sf::IntRect( sf::Vector2i( left, top ), sf::Vector2i( right - left, bottom - top ) );
   
}
   
   
return rect;
   
}
P-184860
DejaVu
» 2026-10-28 18:20:55
Jeżeli mapa jest 2D i masz kwadratowe tilesy to raczej nic Ci nie zmienia nachylenie kamery?
P-184861
tBane
Temat założony przez niniejszego użytkownika
» 2026-10-28 18:24:01
Mapa jest w 2.5D tj. jest rotowana shaderem i przeliczana przez perspektywę. Potrzebowałem granic chunka w płaszczyźnie XY SFMLa po to żeby w wygodny sposób sprawdzać czy mieści się chunk w widoku :-)
Dzięki temu mogę rysować tylko te chunki maapy, które są widoczne w widoku, a nie wszystkie :-)
P-184862
« 1 »
  Strona 1 z 1