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

[SFML] Cienie

Ostatnio zmodyfikowano 2014-07-19 12:25
Autor Wiadomość
unkn9wn
Temat założony przez niniejszego użytkownika
[SFML] Cienie
» 2014-07-17 17:50:41
Witam, czy ktoś obeznany mógłby sprawdzić co mam źle, gdyż od kilku godzin nie mogę nic kontynuować

próbuję stworzyć własne cienie dla obiektów ConvexShape według artykułu
http://www.gamedev.net/page​/resources/_/technical​/graphics-programming-and-theor​y​/dynamic-2d-soft-shadows-r2032

i za nic nie mogę odnaleźć tych dwóch punktów prawidłowo, gdzie przy pierwszym zaczyna się cień, przy drugim kończy
Opisane to zostało na strońce powyżej pt.: Finding the boundary points

zacytuję

Our first step is to determine which points our shadow should be cast from. The list of points that make up the ConvexHull is looped though, and each edge is classified in regard to the light position. In pseudo code:
For every edge:
*Find normal for edge<
*Classify edge as front facing or back facing
*Determine if either edge points are boundary points or not.
 The normal for the edge is found as:

float nx = currentPoint.y - prevPoint.y;
float ny = currentPoint.x - prevPoint.x;

Then a dot product is performed with this vector and the vector to the light. If this is greater than zero, the edge is front facing. Once and edge has been classified, it is compared against the previous edge. If one is front facing and the other back facing, then the shared vertex is a boundary point. As we walk around the edge of the hull (in an anti-clockwise direction) the boundary point from light to shadow is the start shadow point. The boundary from shadow to light is the end shadow point.


C/C++
void Shadow::updateShadow( sf::ConvexShape object, sf::Vector2f lightSourcePos, float lightSourceRadius )
{
    std::vector < sf::Vector2f > realObjectPos;
    for( size_t i = 0; i < object.getPointCount(); i++ )
         realObjectPos.push_back( object.getPosition() + object.getPoint( i ) );
    // anti-clockwise
    int boundaryPoint1 = 0;
    int boundaryPoint2 = 0;
    float dotProduct;
    sf::Vector2f edgeNormal;
    sf::Vector2f lightDistanceFromPoint;
    //float lightDistanceNormal;
    bool frontFacing;
    bool prevFrontFacing;
    //prepare prevFrontFacing-----------------------------------------------------------
    edgeNormal.x = realObjectPos[ 0 ].y - realObjectPos[ object.getPointCount() - 1 ].y;
    edgeNormal.y = realObjectPos[ 0 ].x - realObjectPos[ object.getPointCount() - 1 ].x;
    lightDistanceFromPoint = realObjectPos[ 0 ] - lightSourcePos;
    dotProduct =( edgeNormal.x * lightDistanceFromPoint.x ) +( edgeNormal.y * lightDistanceFromPoint.y );
    if( dotProduct > 0 ) prevFrontFacing = true;
    else prevFrontFacing = false;
    //---------------------------------------------------------------------------------------
    for( int i = 0; i < object.getPointCount(); i++ )
    {
        if( i == 0 )
        {
            edgeNormal.x = realObjectPos[ 0 ].y - realObjectPos[ object.getPointCount() - 1 ].y;
            edgeNormal.y = realObjectPos[ 0 ].x - realObjectPos[ object.getPointCount() - 1 ].x;
        }
        else
        {
            edgeNormal.x = realObjectPos[ i ].y - realObjectPos[ i - 1 ].y;
            edgeNormal.y = realObjectPos[ i ].x - realObjectPos[ i - 1 ].x;
        }
        lightDistanceFromPoint = realObjectPos[ i ] - lightSourcePos;
        //lightDistanceNormal = sqrt(lightDistanceFromPoint.x * lightDistanceFromPoint.x + lightDistanceFromPoint.y * lightDistanceFromPoint.y);
        dotProduct =( edgeNormal.x * lightDistanceFromPoint.x ) +( edgeNormal.y * lightDistanceFromPoint.y );
        if( dotProduct > 0 )
        {
            frontFacing = true;
            if( !prevFrontFacing && frontFacing ) boundaryPoint2 = i;
           
        }
        else {
            frontFacing = false;
            if( prevFrontFacing && !frontFacing ) boundaryPoint1 = i;
           
        }
        // prepare next iteration
        prevFrontFacing = frontFacing;
    }
   
    // dalej tworzenie cienia
}


# poprawiłem kilka zmiennych, gdyż ConvexShape::getPoint() nie zwraca pozycji na ekranie jak miałem przedtem.
Teraz przynajmniej zmieniają się odpowiednio wartości boundaryPoint1 i boundaryPoint2, gdy namierzam źródłem światła z różnych stron, tyle że są one złe
P-113929
unkn9wn
Temat założony przez niniejszego użytkownika
» 2014-07-18 13:20:01
Problem rozwiązany

float nx = currentPoint.y - prevPoint.y;
float ny = currentPoint.x - prevPoint.x;
błąd autora artykułu?

zmieniłem na
C/C++
float nx = currentPoint.x - prevPoint.x;
float ny = currentPoint.y - prevPoint.y;

i o dziwo cienie rysują się tak jak powinny, choć muszę poprawić rysowanie wielokątów. Na razie efekt działa poprawnie na czworokącie

efekt w gif'ie :
http://mkerala.com/n/di/TTJ0​/capture2.gif
P-113949
arczi14
» 2014-07-18 14:13:46
Dzięki za artykuł z pewnością skorzystam :D
P-113950
unkn9wn
Temat założony przez niniejszego użytkownika
» 2014-07-19 12:25:30
Jednak błąd miałem u siebie, a to że się prawidłowo narysował cień - czysty przypadek

Dodaję prawidłowy kod do rysowania cienia ConvexShape'a, z jakąkolwiek liczbą wierzchołków (oczywiście większą niż 0).
Być może ktoś skorzysta.

potrzebna deklaracja cienia -

sf::VertexArray shadow(sf::TrianglesStrip);

C/C++
void Shadow::updateShadow( sf::ConvexShape & object, sf::Vector2f lightSourcePos )
{
    int totalVerticesCount = object.getPointCount();
    // real shape's points positions
    std::vector < sf::Vector2f > realVertexPos;
    for( size_t i = 0; i < object.getPointCount(); i++ )
         realVertexPos.push_back( object.getPosition() + object.getPoint( i ) );
    //------------------------- let's find backfacing edges ---------------------------------------------------
    float dotProduct;
    sf::Vector2f edgeMiddle;
    sf::Vector2f edgeNormal;
    sf::Vector2f lightDistanceFromEdgeM;
    sf::Vector2f currentVertex;
    sf::Vector2f nextVertex;
   
    std::vector < bool > backFacingEdge;
    backFacingEdge.resize( totalVerticesCount );
   
    int backFacingEdgesCount = 0; // for later, to count shadow points
    for( int i = 0; i < totalVerticesCount; i++ )
    {
        currentVertex = realVertexPos[ i ];
        nextVertex = realVertexPos[( i + 1 ) % totalVerticesCount ];
        edgeMiddle = sf::Vector2f(( currentVertex.x + nextVertex.x ) / 2,( currentVertex.y + nextVertex.y ) / 2 );
        edgeNormal.x = -( nextVertex.y - currentVertex.y );
        edgeNormal.y = nextVertex.x - currentVertex.x;
        lightDistanceFromEdgeM = lightSourcePos - edgeMiddle;
        dotProduct =( edgeNormal.x * lightDistanceFromEdgeM.x ) +( edgeNormal.y * lightDistanceFromEdgeM.y );
        if( dotProduct > 0 )
        {
            backFacingEdge[ i ] = false;
            backFacingEdgesCount++;
        }
        else {
            backFacingEdge[ i ] = true;
        }
    } // --------------------------------- GOT THEM ---------------------------------------------
    // looking for these, anti-clockwise
    int boundaryPointFirst = 0;
    int boundaryPointSecond = 0;
    // temp
    int currentEdge;
    int nextEdge;
    for( int i = 0; i < totalVerticesCount; i++ )
    {
        currentEdge = i;
        nextEdge =( i + 1 ) % totalVerticesCount;
       
        if( backFacingEdge[ currentEdge ] && !backFacingEdge[ nextEdge ] ) boundaryPointSecond = nextEdge;
       
        if( !backFacingEdge[ currentEdge ] && backFacingEdge[ nextEdge ] ) boundaryPointFirst = nextEdge;
       
    }
   
    int shadowPointsCount;
    // count shadow points
    shadowPointsCount = backFacingEdgesCount * 2 + 2;
    shadow.resize( shadowPointsCount );
    // setup
    int currentShadowPoint = boundaryPointFirst;
    int shadowNum = 0;
    while( shadowNum < shadowPointsCount )
    {
        if( currentShadowPoint < 0 ) currentShadowPoint = object.getPointCount() - 1;
       
        shadow[ shadowNum ].texCoords = shadow[ shadowNum ].position = realVertexPos[ currentShadowPoint ];
        shadow[ shadowNum ].color = sf::Color( 0, 0, 0, 0 );
        shadowNum++;
        shadow[ shadowNum ].texCoords = shadow[ shadowNum ].position = realVertexPos[ currentShadowPoint ] +( realVertexPos[ currentShadowPoint ] - lightSourcePos ) +( realVertexPos[ currentShadowPoint ] - lightSourcePos );
        shadow[ shadowNum ].color = sf::Color( 0, 0, 0, 0 );
       
        shadowNum++;
        currentShadowPoint--;
    }
   
}
P-114001
« 1 »
  Strona 1 z 1