Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Petit problème de positionnement.  (Lu 4970 fois)

0 Membres et 1 Invité sur ce sujet

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Petit problème de positionnement.
« le: Septembre 18, 2013, 10:46:38 am »
Salut,
j'aimerais positionner la tile et lorsque je change l'origine de la tile pour la redimentionner, que celle-ci ne bouge pas.

Par exemple je met la position de la tile a (0, 0) qui est la position du coin supérieur gauche de la tile.

Si ma tile fait 100*50 de taille, je met l'origine a 50,25 pour la redimentionner ok mais le problème c'est que la position du coin supérieur gauche de la tile devient alors -50,25 à cause de la formule suivante :

float tx     = -m_origin.x * sxc - m_origin.y * sys + m_position.x;
float ty     =  m_origin.x * sxs - m_origin.y * syc + m_position.y;

Donc ça donne :

x = -50 * 1 + 25 * 0 + 0 = -50
y = 50 * 0 + 25 * 1 + 0 = 25

Donc ma tile à bougé et je ne voudrais justement pas qu'elle ne bouge, je n'ai pas trouvé d'autre solution que d'initialiser la position avec le centre de la tile.

J'ai essayer de faire une variable m_center pour avoir les coordonnées globales de l'origine et de faire ça :

float tx     = -m_origin.x * sxc - m_origin.y * sys + m_center.x;
float ty     =  m_origin.x * sxs - m_origin.y * syc + m_center.y;

ou center est la position + l'origine.

Malheureusement ça ne marche pas, le redimentionnement ne se fait pass autour de l'origine mais autour du coin supérieur gauche de la tile.

Comment je pourrai faire ça donc sans être obligé à chaque fois d'initialiser la tile avec la position de son centre de transformation ?
« Modifié: Septembre 18, 2013, 10:48:56 am par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Petit problème de positionnement.
« Réponse #1 le: Septembre 18, 2013, 11:31:56 am »
Là tu essayes d'aller à l'encontre de la définition de l'origine. Il n'y a pas de "truc" pour que ton entité ne bouge pas quand tu changes l'origine, puisque par définition l'origine définit l'origine de la translation. La seule solution c'est d'ajuster la position de l'entité en conséquence.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Petit problème de positionnement.
« Réponse #2 le: Septembre 18, 2013, 12:32:33 pm »
Ouais mais ajuster la position de l'origine pour toutes mes entités m'ennuiye vraiment..., surtout que j'ai des entités qui sont membres d'autres entités et je dois ajuster la position par rapport à l'origine à chaque fois. --' (Pour que la position et l'origine soient bien la même!)
Sinon j'ai trouvé une autre manière de faire qui je pense est mieux.

Grâce à la propriété suivante :

Soit le vecteur p qui est le coin haut gauche de ma tile, et le vecteur c qui est le centre de ma tile.

Vu que les transormations sont linéaires (bref dans mon cas en tout cas j'ai test ça sur une feuille de papier et ça marche pour toutes les transformations donc...) on peut écrire que la transformation du veteur p autour du vecteur o est égale à la transformation du vecteur p - c (que j'appelerai le vecteur d.) + le vecteur o.

Donc :

Scale (p)c = Scale(p - c) + c.
Rot (p)c = Rot(p - c) + c.
Transl(p)c = Transl(p - c) + c.

Bref je vais essayer ça, je ne devrais pas ainsi à chaque fois ajuster la position de l'origine pour chaque entité par rapport à la position des entités parents. (En récupérant le centre des entités parents plutôt que la position ça va mieux mais, le problème c'est que si j'utilise une entité SFML aussi en interne ça devient plus compliqué pour placer le sf::ConvexShape de l'ombre au bonne endroit, je dois calculer le centre des points de ma sf::conveShape et lui mettre un centre, j'ai en + le centre de l'entité parents en + aussi à ajuster bref, un vrai bordel et je ne m'y retrouve plus et je n'ai rien qui se positionne au bonne endroit. :/

PS : mais il reste un soucis : je n'ai pas la position des vertex dans le getTransofrm. :/

Y'a pas moyen de récupérer les vertex et appliquer une transormation par vertex plutôt que de devoir faire à chaque fois une seule transfomation pour tout les vertex de la même entité ?

Bref je pense que je vais modifier SFML...
J'ai juste besoin d'une seule matrice de transformation par vertex...
« Modifié: Septembre 18, 2013, 12:44:49 pm par Lolilolight »

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Petit problème de positionnement.
« Réponse #3 le: Septembre 18, 2013, 07:18:18 pm »
Bon après plusieurs ajustements j'ai réussi à bien positionner les tiles :

IntRect subRect = parent->getSubRectImage();
        Vec2f position (rectBrush.getPosition().x - subRect.width * 0.5f, rectBrush.getPosition().y - subRect.height * 0.5f);
 

En retirant la moitié de la taille du subrect à la position du coin supérieur gauche de la tile avant de faire la transformation.

Tile::Tile (sf::Texture &image, Vec2f position, Vec2f size, IntRect subRect, bool bToAnim) : TexturedDynamicDrawableEntity (position, Vec2f (subRect.width, subRect.height), Vec2f (size.x * 0.5f, size.y * 0.5f), 0, E_TILE) {
    sprite.setTexture(image);
    sprite.setTextureRect(subRect);
   
    float factorX = size.x / (float) subRect.width;
    float factorY = size.y / (float) subRect.height;
    setScale(Vec2f(factorX, factorY));
    this->bToAnim = bToAnim;
}
 

#ifndef DYNAMIC_DRAWABLE_ENTITY
#define DYNAMIC_DRAWABLE_ENTITY
#include "drawableEntity.h"
class DynamicDrawableEntity : public DrawableEntity {
public :

    FloatRect getLocalBounds() {
        return localBounds;
    }
    void setCenter(Vec2f center) {
        Vec2f t = center - m_center;
        move(t);
        needToUpdate = true;
        inverseNeedToUpdate = true;
    }
    Vec2f getCenter() {
        return m_center;
    }
    void setPosition(Vec2f position) {
        Vec2f t = position - m_position;
        move(t);
        needToUpdate = true;
        inverseNeedToUpdate = true;
    }
    Vec2f getSize() {
        return m_size;
    }
    Vec2f getPosition() {
        return m_position;
    }
    void setRotation (float angle) {
        m_rotation = static_cast<float>(fmod(angle, 360));
        if (m_rotation < 0)
            m_rotation += 360.f;
        angle  = -m_rotation * 3.141592654f / 180.f;
        m_size.x = getTransform().transformRect(localBounds).width;
        m_size.y = getTransform().transformRect(localBounds).height;
        Vec2f t (m_scale.x * m_origin.x, m_scale.y * m_origin.y);
        m_position = m_center - t;
        needToUpdate = true;
        inverseNeedToUpdate = true;
        onRotate(angle);
    }
    void setScale(Vec2f scale) {
        m_scale = scale;
        m_size.x = localBounds.width * m_scale.x;
        m_size.y = localBounds.height * m_scale.y;
        Vec2f t (m_scale.x * m_origin.x, m_scale.y * m_origin.y);
        m_position = m_center - t;
        needToUpdate = true;
        inverseNeedToUpdate = true;
        onScale(scale);
    }
    void scale(Vec2f s) {
        setScale(m_scale * s);
    }
    void rotate (float angle) {
        setRotation(m_rotation + angle);
    }
    void move (Vec2f t) {
        m_position += t;
        m_center += t;
        needToUpdate = true;
        inverseNeedToUpdate = true;
        onMove(t);
    }
    void setOrigin(Vec2f origin) {
       m_origin = origin;
       Vec2f t = origin - m_origin;
       m_center -= t;
       m_position -= t;
       needToUpdate = true;
       inverseNeedToUpdate = true;
    }

    Vec2f getScale() {
        return m_scale;
    }
    float getRotation() {
        return m_rotation;
    }
    Vec2f getOrigin() {
        return m_origin;
    }
    void setSize (Vec2f size) {
        setScale(size / m_size);
        needToUpdate = true;
        inverseNeedToUpdate = true;
    }

    FloatRect getGlobalBounds() {
        FloatRect globalBounds = getTransform().transformRect(localBounds);
    }
    const sf::Transform getTransform() const {
         // Recompute the combined transform if needed
        if (needToUpdate) {

            float angle  = -m_rotation * 3.141592654f / 180.f;
            float cosine = static_cast<float>(std::cos(angle));
            float sine   = static_cast<float>(std::sin(angle));
            float sxc    = m_scale.x * cosine;
            float syc    = m_scale.y * cosine;
            float sxs    = m_scale.x * sine;
            float sys    = m_scale.y * sine;
            float tx     = -m_origin.x * sxc - m_origin.y * sys + m_center.x;
            float ty     =  m_origin.x * sxs - m_origin.y * syc + m_center.y;

            const_cast<DynamicDrawableEntity*>(this)->m_transform = sf::Transform( sxc, sys, tx,
                                      -sxs, syc, ty,
                                      0.f, 0.f, 1.f);
            const_cast<DynamicDrawableEntity*>(this)->needToUpdate = false;
        }
        return m_transform;
    }
    const sf::Transform& getInverseTransform()
    {
        // Recompute the inverse transform if needed
        if (inverseNeedToUpdate)
        {
            const_cast<DynamicDrawableEntity*>(this)->m_inverseTransform = getTransform().getInverse();
            const_cast<DynamicDrawableEntity*>(this)->inverseNeedToUpdate = false;
        }

        return m_inverseTransform;
    }
protected :
    DynamicDrawableEntity(Vec2f position, Vec2f size, Vec2f origin, int zOrder, TYPE type) : DrawableEntity(type) {
        localBounds = FloatRect(position.x, position.y, size.x, size.y);
        m_position = position;
        m_size = size;
        m_center = Vec2f (m_position.x + origin.x, m_position.y + origin.y);
        m_origin = origin;
        m_scale = Vec2f(1.f, 1.f);
        m_rotation = 0;
        setZOrder(zOrder);
        needToUpdate = true;
        inverseNeedToUpdate = true;
    }
    virtual void onRotate(float angle) {}
    virtual void onScale(Vec2f s) {}
    virtual void onMove(Vec2f t) {}
private :
    FloatRect localBounds;
    Vec2f m_position, m_size, m_center,m_scale,m_origin;
    float m_rotation;
    sf::Transform m_transform;
    sf::Transform m_inverseTransform;
    bool needToUpdate, inverseNeedToUpdate;
};
#endif // TRANSF_ENTITY

 

Cependant j'ai toujours un soucis pour les ombres, elle s'affichent pas au bonne endroit, je voudrais les afficher en dessous du mur, mais au lieu de ça, elles s'affichent à la place du mur. :/

#include "shadowWall.h"
#include "wall.h"
ShadowWall::ShadowWall (const Light &light, Wall *wall) : Shadow (light, wall) {
    shadow = NULL;
    createShadow (light, wall);
}
void ShadowWall::createShadow (const Light &light, Wall *wall) {

    Vec2f lightPos (const_cast<Light&> (light).getCenter().x, const_cast<Light&> (light).getCenter().y);

    Vec2f v = lightPos.normalize() * WALL_HEIGHT;


    int lightHeight = const_cast<Light&> (light).getHauteur();
    float scale;
    if (lightHeight == 0)
        scale = 1.f;
    else if (lightHeight >= 200)
        scale = 0.f;
    else
        scale = 1.f /  (100.f / (float) const_cast<Light&> (light).getHauteur());
    shadow = new ConvexShape (wall->getBottomPoints().size() * 2);
    vector<Vec2f*> points;

    Vec2f positionShadow (wall->getBottomPoints()[0]->x, wall->getBottomPoints()[0]->y);

    for (int i = 0; i < wall->getBottomPoints().size(); i++) {
        Vec2f *point = new Vec2f(*wall->getBottomPoints()[i]);
        shadow->setPoint(i, Vector2f(point->x - positionShadow.x, point->y - positionShadow.y));
        points.push_back(point);
    }
    for (int j = wall->getBottomPoints().size(), i = wall->getBottomPoints().size() - 1; i >=0 ; j++, i--) {
        Vec2f *projPoint = new Vec2f(*wall->getBottomPoints()[i] + -v * scale);
        shadow->setPoint(j, Vector2f ((int) projPoint->x - positionShadow.x, (int) projPoint->y - positionShadow.y));
        points.push_back(projPoint);
    }
    Vec2f shadowOrigin = Computer::getMoy(points);
    shadow->setFillColor(Color::Black);
    shadow->setPosition(Vec2f(positionShadow.x, positionShadow.y));

    setOrigin(shadowOrigin);
    setRotation(wall->getRotation());
    for (unsigned int i = 0; i < points.size(); i++) {
        delete points[i];
    }
    points.clear();
}
void ShadowWall::draw(RenderTarget &target, RenderStates states) const {
    states.transform = states.transform * getTransform();
    target.draw(*shadow, states);
}
Drawable* ShadowWall::getShadow () {
    return shadow;
}
int ShadowWall::getType() {
    return SHADOWWALL;
}
ShadowWall::~ShadowWall () {
    delete shadow;
}
 
#include "shadow.h"
using namespace sf;
/*Crée une ombre à partir de la lumière (light) et le tile (tile.)
*/


Shadow::Shadow (const Light &light, DrawableEntity *entity) : DynamicDrawableEntity (entity->getPosition(), entity->getSize(), Vec2f(0, 0), DEFAULT_SHADOW_Z_ORDER, Entity::E_SHADOW) {

    entityId = &entity->getId();
    lightId = &(const_cast<Light&> (light).getId());
}

int& Shadow::getLightId () {
    return *lightId;
}
int& Shadow::getEntityId () {
    return *entityId;
}

 


bottomPoints sont 2 points qui sont de chaque côté en bas du mur que j'utilise pour projeter les 2 autres points en fonction de la position et de la hauteur du soleil.

Bref avant je n'avais pas de soucis tout s'affichais au bonne endroit.

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Petit problème de positionnement.
« Réponse #4 le: Septembre 18, 2013, 07:30:51 pm »
Bon ça va mieux en faisant ça mais elle est trop décalée en x la :
Shadow::Shadow (const Light &light, DrawableEntity *entity) : DynamicDrawableEntity (entity->getCenter(), entity->getSize(), Vec2f(0, 0), DEFAULT_SHADOW_Z_ORDER, Entity::E_SHADOW) {

    entityId = &entity->getId();
    lightId = &(const_cast<Light&> (light).getId());
}
[code]

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Petit problème de positionnement.
« Réponse #5 le: Septembre 18, 2013, 08:58:00 pm »
Est-ce que tu sais que personne ne peux suivre ton cheminement là ? Tu postes les choses au fur et à mesure qu'elles te viennent, et c'est beaucoup trop abondant et compliqué pour que quiconque puisse suivre et te répondre.

Pourquoi est-ce que tu ne continue pas tranquillement à coder / réflechir, et puis lorsque vraiment tu as un problème tu viens en expliquant correctement, voire avec un code complet minimal. Moi ça m'est égal si tu continues à réflechir sur le forum, mais j'imagine que tu perds du temps pour pas grand chose en faisant ça.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Petit problème de positionnement.
« Réponse #6 le: Septembre 19, 2013, 12:01:24 pm »
Oui tu as raison je vais réfléchir à ça mais si je veux faire une translation par rapport au coin supérieur gauche de la tile puis une rotation et un redimentionnement par rapport au cenre de la tile, la classe Transformable ne convient pas.

En utilisant 2 matrices avec une origine différente peut être en en combinant les transformations mais je ne vois pas comment faire celà avec la SFML. (Contrairement à opengl ou il suffisait de faire glPopMatrix et glPushMatrix.)

« Modifié: Septembre 19, 2013, 12:04:00 pm par Lolilolight »

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Petit problème de positionnement.
« Réponse #7 le: Septembre 19, 2013, 12:11:17 pm »
Bon écoutes j'ai essayé de faire, un redimentionnement de mon entité par rapport au repère local à son origine (le centre de la tile.) et ensuite de faire une translation dans le repère global (ou l'origine est 0, 0 donc.) et de combiner ses 2 transformations mais ça ne marche pas, le sprite n'est pas au bonne endroit, la SFML ne combine pas bien mes 2 transformations, je vais faire un code minimal et le poster.

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Petit problème de positionnement.
« Réponse #8 le: Septembre 19, 2013, 01:28:42 pm »
Haaa j'ai trouvé, c'était la position de ma brush qui n'était plus bonne et qui donnait donc l'impression que les transformations ne se combinaient pas bien car mes tiles était trop loin par rapport au RectangleShape de ma brush... --'
(Vu que avant je ne pouvais pas combiner les transformations avec la SFML 1.6, je devais absolument  ajuster la position de ma brush avec l'origine de la transformation pour la tile de plus ça changeait si les coordonnées étaien négative.)