Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Έχω τον εξής κώδικα OpenGL (GLUT) που δουλεύω στο Codeblocks.

Ουσιαστικά σχεδιάζει ένα ανθρωπάκι (MrRobot).

 

Αυτό που θέλω είναι όταν ο χρήστης πατάει τα arrow keys του πληκτρολογίου, το ρομποτάκι να κινείται στην οθόνη.

 

Αν θέλω να κινείται ένα απλό τετράγωνο, βάζω το εξής στην display(): glRecti(x1,y1,x2,y2);

Πως πρέπει να γίνει ο κώδικας για να κινείται όλο το "σχήμα/τα" που σχεδιάζει η MrRobot;

// KeyboardEvents.cpp : Defines the entry point for the console application.
//
/*
- Χρησιμοποίησα την glutSpecialFunc αντί της glutKeyboardFunc
... για να δουλέψουν οι σταθερές των arrow keys
*/

#include <GL/glut.h>

GLuint x1=10,y1=10;
GLuint x2=20,y2=20;

// σύνθετο σχήμα
GLuint listID;

void MrRobot(GLsizei displayListID)
{

    glNewList(displayListID,GL_COMPILE);

    //Save current colour state
    glPushAttrib(GL_CURRENT_BIT);

    // σώμα
    glColor3f(0.5,0.5,0.5);
    glBegin(GL_POLYGON);
    glVertex2f(0,10);
    glVertex2f(20,10);
    glVertex2f(20,30);
    glVertex2f(0,30);
    glEnd();

    // κεφάλι
    glColor3f(0,0,1);
    glBegin(GL_POLYGON);
    glVertex2f(5,30);
    glVertex2f(15,30);
    glVertex2f(15,40);
    glVertex2f(5,40);
    glEnd();

    // πόδια
    glColor3f(1,0,0);
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(10,10);
    glVertex2f(20,0);
    glVertex2f(10,-5);
    glVertex2f(0,0);
    glEnd();

    // δεξί χέρι
    glColor3f(0,1,0);
    glBegin(GL_TRIANGLES);
    glVertex2f(20,30);
    glVertex2f(30,27.5);
    glVertex2f(20,25);
    glEnd();

    // αριστερό χέρι
    glColor3f(0,1,0);
    glBegin(GL_TRIANGLES);
    glVertex2f(-10,27.5);
    glVertex2f(0,30);
    glVertex2f(0,25);
    glEnd();

    //Recall saved colour state
    glPopAttrib();

    glEndList();
}

void display()
{
    glClearColor(0,0,0,0);
    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1,0,0);

    glMatrixMode(GL_MODELVIEW);


    //Defining a modelview transform matrix
    glScalef(0.3,0.3,0.3);

    //Execute the display list (the modelview matrix will be applied)
    glCallList(listID);

    //glRecti(x1,y1,x2,y2);
    glFlush();
}

void keyboard(unsigned char key,int x, int y)
{
    printf("\nKeyboard event detected. \nCharacter key: %c\nMouse pointer position: x=%d y=%d",key,x,y);

    if (key==GLUT_KEY_UP)
    {
        y1++;
        y2++;
    }
    if (key==GLUT_KEY_DOWN)
    {
        y1--;
        y2--;
    }
    if (key==GLUT_KEY_LEFT)
    {
        x1--;
        x2--;
    }
    if (key==GLUT_KEY_RIGHT)
    {
        x1++;
        x2++;
    }

    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitWindowPosition(50,50);
    glutInitWindowSize(800,600);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutCreateWindow("MrROBOT");

    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(-5,35,-5,30);

    listID=glGenLists(1);

    MrRobot(listID);

    glutDisplayFunc(display);
    glutSpecialFunc(keyboard);
    glutMainLoop();

    return 0;
}
  • Moderators
Δημοσ.

Πρέπει οι συντεταγμένες των vertices που σχεδιάζεις να έχουν μέσα το x και το y του ρομπότ. Έτσι όπως το έχεις τώρα, σχεδιάζονται σε συγκεκριμένο σημείο κάθε φορά. Πρέπει να τα βάλεις να σχεδιάζονται συναρτήσει του x και του y.

Δημοσ.

Και πως μπορεί να γίνει αυτό;

 

Για παράδειγμα προσπάθησα το εξής με το τετράγωνο που είναι το κεφάλι.

Ωστόσο όταν πατάω τα arrow keys, το σχήμα συρρικνώνεται μέχρι που εξαφανίζεται...

Εγώ θέλω να κινείται..

GLuint kefali_x1=5, kefali_y1=30, kefali_x2=15, kefali_y2=30, kefali_x3=15,kefali_y3=40, kefali_x4=5,kefali_y4=40;

[...]

    // κεφάλι
    glColor3f(0,0,1);
    glBegin(GL_POLYGON);
    glVertex2f(kefali_x1,kefali_y1);
    glVertex2f(kefali_x2,kefali_y2);
    glVertex2f(kefali_x3,kefali_y3);
    glVertex2f(kefali_x4,kefali_y4);
    glEnd();


[...]

void keyboard(unsigned char key,int x, int y)
{
    printf("\nKeyboard event detected. \nCharacter key: %c\nMouse pointer position: x=%d y=%d",key,x,y);

    if (key==GLUT_KEY_UP)
    {
        kefali_y1++;
        kefali_y2++;
    }
    if (key==GLUT_KEY_DOWN)
    {
        kefali_y1--;
        kefali_y2--;
    }
    if (key==GLUT_KEY_LEFT)
    {
        kefali_x1--;
        kefali_x2--;
    }
    if (key==GLUT_KEY_RIGHT)
    {
        kefali_x1++;
        kefali_x2++;
    }

    glutPostRedisplay();
}
Δημοσ.

Δεν "μετακινούμε" το ρομποτάκι..αυτό θα φανεί αλλά στην πράξη φτιάχνουμε ένα άλλο frame με την νέα θέση. Εφόσον στο frame που έφτιαξες έχεις μια θέση, στο επόμενο πρέπει τα νούμερα να αλλάξουν. Το πώς θα το κάνεις είναι επιλογή σου. Π.χ. αν είχες μόνο δυο θέσεις π.χ. κάτι σαν το ανθρωπάκι στα φανάρια, τότε με δυο "προγράμματα" όπως το παραπάνω, με άλλα νούμερα, θα είχαμε δυο δυνατότητες, μια για το Γρηγόρη και μια για το Σταμάτη. Αν μάλιστα τα βάλουμε σε χωριστές ρουτίνες (βλέπε συναρτήσεις) θα είχαμε σε ένα πρόγραμμα δυο "στάσεις". Αν θες όμως ενδιάμεσες ή να ορίζεις με το πληκτρολόγιο τη θέση τότε πρέπει να κάνεις μια συνάρτηση να παίρνει τα Χ και Υ και να τα βάζει στα σταθερά νούμερα ως offsets (μεταθέσεις).

ας πούμε ότι μιλάμε για το σημείο 500,400 αντί να το έχεις σταθερό έτσι βάζεις τα 400+Χ, 500+Υ. Τώρα δίνεις την f(X,Y) και αν δώσεις την f(30,-20) θα πάρεις το σημείο 530, 380. Δες την εικόνα σε όλα.

Δημοσ.

Έχοντας κάποιες γνώσεις από άλλα προγράμματα θα έλεγα ότι για να κινείται όλο το ρομπότ πρέπει να το δεσεις να το κάνεις δηλαδή ένα αντικείμενο και να εφαρμόσεις τη κίνηση σε αυτό. Προφανώς θα υπάρχει κάποια εντολή join ή bind

 

Το ότι το σχήμα σου συρρικνώνεται αντί να κινείται, εφόσον το κινεις στο επίπεδο χψ προφανώς οφείλεται στο που έχεις την κάμερα. Βάλε την κάμερα στον άξονα των ζ+ εκεί που είναι τα μάτια σου δηλαδή και ξαναδοκιμασε.

Δημοσ.

Πως αλλάζω την κάμερα ώστε να μπει στον σωστό άξονα;
Έκανα 10δες προσπάθειες με την glTranslatef, αλλά χωρίς επιτυχία.

 

Απ' ότι κατάλαβα, αυτό που πρέπει να γίνεται με το πάτημα κάθε πλήκτρου είναι το εξής:

    if (key==GLUT_KEY_UP)
    {
        kefali_y1++;
        kefali_y2++;
        kefali_y3++;
        kefali_y4++;
    }
    if (key==GLUT_KEY_DOWN)
    {
        kefali_y1--;
        kefali_y2--;
        kefali_y3--;
        kefali_y4--;
    }
    if (key==GLUT_KEY_LEFT)
    {
        kefali_x1--;
        kefali_x2--;
        kefali_x3--;
        kefali_x4--;
    }
    if (key==GLUT_KEY_RIGHT)
    {
        kefali_x1++;
        kefali_x2++;
        kefali_x3++;
        kefali_x4++;
    }

Το θέμα είναι πως να αλλάξει ο άξονας.

Δημοσ.

Sorry δεν έχω ιδέα, νόμιζα ότι δουλεύει όπως το webgl (βασίζεται στο opengl). Το σκηνικό σου είναι 2d ή 3d ?

  • Moderators
Δημοσ.

Το πρόβλημά σου είναι ότι έχεις σχήματα, η θέση των οποίων αλλάζει βάση κάποιου input. Πρέπει αρχικά να μοντελοποιήσεις αυτά τα σχήματα έτσι ώστε να είναι πιο εύκολη η διαχείρισή τους.

 

Δες την εικόνα που σου ζωγράφισα. Έστω ότι αυτό είναι το κεφάλι. Το Κ είναι το κέντρο του (η θέση του δηλαδή), το Width το πλάτος του και το Height το ύψος του. Το κεφάλι σου λοιπόν περιγράφεται από αυτά τα 3 χαρακτηριστικά. Τα 4 σημεία που έχω κυκλώσει είναι τα vertices του κεφαλιού, τα οποία μπορείς να τα βρεις χρησιμοποιώντας αυτά τα 3 χαρακτηριστικά. Εάν η θέση του κεφαλιού (το Κ στο σχήμα) αλλάξει, τότε πρέπει να το ξαναζωγραφίσεις λαμβάνοντας υπ' όψην σου αυτή την αλλαγή.

Υπόψην ότι στην OpenGL χρησιμοποιείς "σημεία" (vertices) τα οποία ενώνονται με κάποιο τρόπο και σχηματίζουν ένα σχήμα.

 

post-284325-0-99353000-1463339781_thumb.png

 

Δεν ξέρω αν γράφεις C ή C++. Θα σου γράψω ένα απλουστευμένο παράδειγμα σε C++ και, αν γράφεις C, πες μου να σου γράψω και σε C (οι διαφορές δεν θα είναι μεγάλες έτσι κι αλλιώς).

 

 

 

struct Point
{
    float x;
    float y;

    Point()
    {}
    Point(float x_, float y_)
        : x(x_), y(x_)
    {}

    Point operator+(float Scalar) const
    {
        return Point(x + Scalar, y + Scalar);
    }

    Point operator-(float Scalar) const
    {
        return Point(x - Scalar, y - Scalar);
    }
};

class Shape
{
    public:
        Shape()
        {}

        // Το κέντρο του σχήματος, το οποίο είναι και η θέση του.
        Point Position;

        // Χρησιμοποιούμαι το μισό πλάτος και μήκος αντί για ολόκληρο
        // για να μη χρειάζεται να κάνουμε διαιρέσεις με το 2.

        float HalfWidth;
        float HalfHeight;

        // Η συνάρτηση που ζωγραφίζει το σχήμα στην οθόνη.
        void Draw()
        {
            glColor3f(0.5, 0.5, 0.5);
            glBegin(GL_POLYGON);
                // Το πρώτο vertex μας είναι το κάτω αριστερά.
                glVertex2f(Position - HalfWidth, Position - HalfHeight);

                // Μετά το πάνω αριστερά.
                glVertex2f(Position - HalfWidth, Position + HalfHeight);

                // Μετά το πάνω δεξιά.
                glVertex2f(Position + HalfWidth, Position + HalfHeight);

                // Και τέλος το κάτω δεξιά.
                glVertex2f(Position + HalfWidth, Position - HalfHeight);
            glEnd();
        }
};

int main()
{
    // Φτιάχνουμε ένα Shape που ονομάζουμε Head. Αυτό θα είναι το κεφάλι μας.
    Shape Head;
    
    // Ρύθμιση παραμέτρων του Head (Position, HalfWidth, HalfHeight)
    // . . .

    // Λέμε στο Head να ζωγραφιστεί. Αυτή η κλήση μπορεί να είναι μέσα στο input loop μας.
    Head.Draw();

    return 0;
}

Δημοσ.

1) Glut φτιαχνει ενα gl context στη GPU. Δηλαδη εχεις δυο context, ενα το προγραμμα σου και ενα το gl. 

2) Στο MrRobot λες στο context στη gpu που εχεις ανοιξει, να φτιαξει vertex και index buffer. Και το γεμιζεις vertices και indices.

(vertex ειναι datastruct που εχει πληροφοριες για το καθε σημειο, ελαχιστη πληροφορια ειναι το position a.k.a χ,ψ,ζ , στο δικο σου εχει και χρωμα. Συνηθως ενα vertex ειναι position και 1-4 texture coords)

(index αντιπροσωπευει την θεση του καθε vertex πχ 1 2 3 θα φτιαξει ενα τριγωνο με τα vertices που εχεις σε εκεινες τις θεσεις. Οκ, δεν το καταλαβαινεις αυτο τωρα, δες το σα WinZip)

3) Στο Display το context της gpu μας λεει πως ειναι ετοιμο να τρεξει τα σταδια της pipeline. Απο ολααααααααααα τα σταδια, εσυ θες μονο το geometry transformation. 

4) Στο keyboard... οκ δεν εχω να πω πολλα, ειναι απο το cpu context και απλα καλειται απο την glmainloop οταν εχεις καποιο event απο το keyboard

 

 

Αυτα ειναι καποια βασικα πραματα απο το προγραμμα σου τα οποια λογικα δεν ξερεις.

 

Τωρα λιγη γεωμετρια.

 

Πρωτα απολα δεν μιλαμε για σημεια (points) αλλα για διανυσματα (vectors)

10, 5 αυτο ειναι ενα σημειο

10, 5 αυτο ειναι ενα διανυσμα

Ποια ειναι η διαφορα στη δομη; Καμια.

Η διαφορα ειναι το πως το δουλευουμε. 

Σημειο ειναι μια μουτζουρα στο 10, 5

Διανυσμα ειναι ενα βελακι που αρχιζει απο το 0, 0 και τελειωνει στο 10, 5. 

Το διανυσμα (το βελακι) μπορω να το μακρυνω (μεγαλωσω) απλουστατα πολλαπλασιαζοντας το. Πχ Διανυσμα Α * 10 ( [10, 5] * 10 => 10 * 10,  5 * 10 => [100, 50] ) το βελακι αυτο θα ειναι 10 φορες μεγαλυτερο.

Μπορω να το μετακινησω προσθετοντας το.

Ακομα και να το στριφογυρισω, βεβαια με πιο συνθετη πραξη που θελει sin & cos.

 

Οπως ειπα πιο πανω, το σημειο δεν εχει καμια διαφορα με το διανυσμα σα δομη. Για αυτο θελουμε και την σειρα των πραξεων (μετατροπων) ενα διανυσμα Α * 10 + 10 δεν ειναι ιδιο με ενα διανυσμα (Α + 10) * 10

 

Το καλο με τα μαθηματικα ειναι πως, μπορεις να βαλεις αυτες τις μετατροπες, μεσα σε μια δομη που λεγεται μητρα (matrix). Μαλιστα μπορεις να βαλεις ολα τα ειδη των μετατροπων μαζι. Μια μητρα μπορει και να μεγαλωνει και να μετακινει και να στριφογυριζει ενα διανυσμα. Ετσι εαν εχουμε την μητρα Μ που μεγαλωνει 10 φορες το διανυσμα και το μετακινει 5 μοναδες, τοτε εαν πολλαπλασιασουμε το καθε διανυσμα με το Μ, αυτο θα μεγαλωσει 10 φορες και θα μετακινηθει 5 μοναδες.

 

Και το καλυτερο, μπορεις να πολλαπλασιαζεις τις μητρες κρατωντας την σειρα των πραξεων. 

 

 

Τωρα που πηρες μια γενικη ιδεα. Καπου καλεις την scalef η οποια κανει scale στο default matrix. Τι θες να κανεις τωρα που το εκανες scale; Να το πας πανω; Βαλε ενα matrix στη stack (pushMatrix αν θυμαμαι καλα) και καλεσε την translatef με χ 0 και ψ 5, κλπ κλπ τελος εφοσον καλεσεις την callList, κανεις popMatrix αυτα που pushαρες. 

 

 

Τελος, ενα μπονους. 

Ετσι οπως εχεις τον κωδικα. Κανε push ενα matrix, καντο translate αριστερα 10 καλεσε την calllist, κανε popmatrix, κανε pushmatrix κανε translate δεξια 10 καλεσε την calllist και μετα popmatrix. Σα να τα βλεπεις διπλα, λογικα θα επιασες και το νοημα.

  • Like 1

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...