<file_sep>#ifndef SUPERFICIE_H
#define SUPERFICIE_H

#include "vertice.h"

class Superficie {
private:
    Vertice *inicio;
    Vertice *final;
    Superficie *sig;
    float rojo, verde, azul;
    float nx, ny, nz;

public:
    Superficie();
    ~Superficie();
    Superficie *getSig();
    void setSig(Superficie *);
    void setColor(float, float, float);
    void setNormal(float, float, float);
    Superficie *copia();
    void agregar(Vertice *);
    void transformar(Matriz3D *);
    void desplegar();
};

#endif // SUPERFICIE_H
<file_sep>#include "pantalla.h"

Pantalla::Pantalla() : Objeto3D() {
}

Eje *Pantalla::getEjeVer() {
    return ejeVer;
}

Eje *Pantalla::getEjeHor() {
    return ejeHor;
}

void Pantalla::setEjeVer(Eje *ejeVer) {
    this->ejeVer = ejeVer;
}

void Pantalla::setEjeVer(float x1, float y1, float z1, float x2, float y2, float z2) {
    ejeVer = new Eje(new Punto(x1, y1, z1), new Punto(x2, y2, z2));
}

void Pantalla::setEjeHor(Eje *ejeHor) {
    this->ejeHor = ejeHor;
}

void Pantalla::setEjeHor(float x1, float y1, float z1, float x2, float y2, float z2) {
    ejeHor = new Eje(new Punto(x1, y1, z1), new Punto(x2, y2, z2));
}

Pantalla *Pantalla::copia() {
    Pantalla *c = new Pantalla();
    Superficie *s = inicio;
    while (s != 0) {
        c->agregar(s->copia());
        s = s->getSig(); // s++;
    }
    return c;
}

void Pantalla::girar(float ang) {
    rotar(ejeVer, ang);
    ejeHor->rotar(ejeVer, ang);
}

void Pantalla::mover(float ang) {
    rotar(ejeHor, ang);
}
<file_sep>#ifndef VERTICE_H
#define VERTICE_H

#include "punto.h"

class Vertice : public Punto {
private:
    Vertice *sig;

public:
    Vertice(float, float, float);
    Vertice *getSig();
    void setSig(Vertice *);
    Vertice *copia();
    void desplegar();
};

#endif // VERTICE_H
<file_sep>#include "superficie.h"
#include "QtOpenGL"

Superficie::Superficie() {
    inicio = 0;
    final = 0;
    sig = 0;
    rojo = 0;
    verde = 0;
    azul = 0;
    nx = 0;
    ny = 0;
    nz = 0;
}

Superficie::~Superficie() {
    Vertice *aux = 0;
    Vertice *v = inicio;
    while (v != 0) {
        aux = v->getSig();
        delete v;
        v = aux;
    }
}

Superficie *Superficie::getSig() {
    return sig;
}

void Superficie::setSig(Superficie *sig) {
    this->sig = sig;
}

void Superficie::setColor(float rojo, float verde, float azul) {
    this->rojo = rojo;
    this->verde = verde;
    this->azul = azul;
}

void Superficie::setNormal(float nx, float ny, float nz) {
    this->nx = nx;
    this->ny = ny;
    this->nz = nz;
}

Superficie *Superficie::copia() {
    Superficie *c = new Superficie();
    Vertice *v = inicio;
    while (v != 0) {
        c->agregar(v->copia());
        v = v->getSig(); // v++;
    }
    return c;
}

void Superficie::agregar(Vertice *v) {
    if (inicio == 0) {
        inicio = v;
        final = v;
    } else {
        final->setSig(v);
        final = v;
    }
}

void Superficie::transformar(Matriz3D *m) {
    Vertice *v = inicio;
    while (v != 0) {
        v->transformar(m);
        v = v->getSig(); // v++;
    }
}

void Superficie::desplegar() {
    GLfloat materialDiffuse[] = { rojo, verde, azul, 1 };
    glMaterialfv(GL_FRONT, GL_DIFFUSE, materialDiffuse);

    glNormal3f(nx, ny, nz);
    glBegin(GL_POLYGON);
    Vertice *v = inicio;
    while (v != 0) {
        v->desplegar();
        v = v->getSig(); // v++;
    }
    glEnd();
}
<file_sep>#ifndef MATRIZ3D_H
#define MATRIZ3D_H

class Matriz3D {
private:
    float matriz[4][4];

public:
    Matriz3D();
    Matriz3D(float, float, float, float, float, float, float, float, float, float, float, float);
    float getDato(int, int);
    void setDato(int, int, float);
    Matriz3D *copia();
    Matriz3D *mult(Matriz3D *);
};

#endif // MATRIZ3D_H
<file_sep>#include "hombro.h"

Hombro::Hombro() : Objeto3D() {
}

Eje *Hombro::getEjeVer() {
    return ejeVer;
}

Eje *Hombro::getEjeHor() {
    return ejeHor;
}

void Hombro::setEjeVer(Eje *ejeVer) {
    this->ejeVer = ejeVer;
}

void Hombro::setEjeVer(float x1, float y1, float z1, float x2, float y2, float z2) {
    ejeVer = new Eje(new Punto(x1, y1, z1), new Punto(x2, y2, z2));
}

void Hombro::setEjeHor(Eje *ejeHor) {
    this->ejeHor = ejeHor;
}

void Hombro::setEjeHor(float x1, float y1, float z1, float x2, float y2, float z2) {
    ejeHor = new Eje(new Punto(x1, y1, z1), new Punto(x2, y2, z2));
}

Hombro *Hombro::copia() {
    Hombro *c = new Hombro();
    Superficie *s = inicio;
    while (s != 0) {
        c->agregar(s->copia());
        s = s->getSig(); // s++;
    }
    return c;
}

void Hombro::girar(float ang) {
    rotar(ejeVer, ang);
    ejeHor->rotar(ejeVer, ang);
}

void Hombro::mover(float ang) {
    rotar(ejeHor, ang);
}
<file_sep>#include "antebrazo.h"

Antebrazo::Antebrazo() : Objeto3D() {
}

Eje *Antebrazo::getEjeVer() {
    return ejeVer;
}

Eje *Antebrazo::getEjeHor() {
    return ejeHor;
}

void Antebrazo::setEjeVer(Eje *ejeVer) {
    this->ejeVer = ejeVer;
}

void Antebrazo::setEjeVer(float x1, float y1, float z1, float x2, float y2, float z2) {
    ejeVer = new Eje(new Punto(x1, y1, z1), new Punto(x2, y2, z2));
}

void Antebrazo::setEjeHor(Eje *ejeHor) {
    this->ejeHor = ejeHor;
}

void Antebrazo::setEjeHor(float x1, float y1, float z1, float x2, float y2, float z2) {
    ejeHor = new Eje(new Punto(x1, y1, z1), new Punto(x2, y2, z2));
}

Antebrazo *Antebrazo::copia() {
    Antebrazo *c = new Antebrazo();
    Superficie *s = inicio;
    while (s != 0) {
        c->agregar(s->copia());
        s = s->getSig(); // s++;
    }
    return c;
}

void Antebrazo::girar(float ang) {
    rotar(ejeVer, ang);
    ejeHor->rotar(ejeVer, ang);
}

void Antebrazo::mover(float ang) {
    rotar(ejeHor, ang);
}
<file_sep>#include "punto.h"

Punto::Punto() {
    x = 0;
    y = 0;
    z = 0;
}

Punto::Punto(float x, float y, float z) {
    this->x = x;
    this->y = y;
    this->z = z;
}

float Punto::getX() {
    return x;
}

float Punto::getY() {
    return y;
}

float Punto::getZ() {
    return z;
}

void Punto::setX(float x) {
    this->x = x;
}

void Punto::setY(float y) {
    this->y = y;
}

void Punto::setZ(float z) {
    this->z = z;
}

Punto *Punto::copia() {
    return new Punto(x, y, z);
}

void Punto::transformar(Matriz3D *m)
{
    float xa = x;
    float ya = y;
    float za = z;

    float A = m->getDato(0, 0);
    float B = m->getDato(0, 1);
    float C = m->getDato(0, 2);
    float D = m->getDato(0, 3);

    float E = m->getDato(1, 0);
    float F = m->getDato(1, 1);
    float G = m->getDato(1, 2);
    float H = m->getDato(1, 3);

    float I = m->getDato(2, 0);
    float J = m->getDato(2, 1);
    float K = m->getDato(2, 2);
    float L = m->getDato(2, 3);

    x = (float) (A * xa + B * ya + C * za + D);
    y = (float) (E * xa + F * ya + G * za + H);
    z = (float) (I * xa + J * ya + K * za + L);
}
<file_sep>#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QKeyEvent>

#include "brazo.h"

extern int cx;
extern int cy;
extern int cz;
extern int estado;
extern int timer;
extern int tp;
extern Brazo *brazo;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void brazoMovP();
    void brazoMovN();

private slots:
    void on_actionAbrir_triggered();
    void on_actionGirar_Hombro_triggered();
    void on_actionMover_Hombro_triggered();
    void on_actionMover_Antebrazo_triggered();
    void on_actionGirar_Pantalla_triggered();
    void on_actionMover_Pantalla_triggered();

private:
    Ui::MainWindow *ui;
    int timerId;

protected:
    void timerEvent(QTimerEvent *);
    void keyPressEvent(QKeyEvent *);
};

#endif // MAINWINDOW_H
<file_sep>#include "vertice.h"
#include "QtOpenGL"

Vertice::Vertice(float x, float y, float z) : Punto(x, y, z) {
    sig = 0;
}

Vertice *Vertice::getSig() {
    return sig;
}

void Vertice::setSig(Vertice *sig) {
    this->sig = sig;
}

Vertice *Vertice::copia() {
    Vertice *c = new Vertice(x, y, z);
    c->setSig(sig);
    return c;
}

void Vertice::desplegar() {
    glVertex3f(x, y, z);
}
<file_sep>#ifndef LINEA_H
#define LINEA_H

#include "punto.h"

class Linea {
protected:
    Punto *p1;
    Punto *p2;

public:
    Linea();
    Linea(Punto *, Punto *);
    Linea(float, float, float, float, float, float);
    Punto *getP1();
    Punto *getP2();
    void setP1(Punto *);
    void setP1(float, float, float);
    void setP2(Punto *);
    void setP2(float, float, float);
    Linea *copia();
    void transformar(Matriz3D *);
};

#endif // LINEA_H
<file_sep>#include "mainwindow.h"
#include "ui_mainwindow.h"

int cx = 0;
int cy = 0;
int cz = 18;
int estado = -1;
int timer = 0;
int tp = 0;
Brazo *brazo = 0;

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);
    timerId = startTimer(100);
}

MainWindow::~MainWindow() {
    killTimer(timerId);
    delete ui;
}

void MainWindow::brazoMovP() {
    switch (estado) {
        case 0: {
            // Girar Hombro.
            brazo->girarHombro(0.01);
            timer = 1;
            break;
        }
        case 1: {
            // Mover Hombro.
            brazo->moverHombro(0.01);
            timer = 1;
            break;
        }
        case 2: {
            // Mover Antebrazo.
            brazo->moverAntebrazo(0.01);
            timer = 1;
            break;
        }
        case 3: {
            // Girar Pantalla.
            brazo->girarPantalla(0.01);
            timer = 1;
            break;
        }
        case 4: {
            // Mover Pantalla.
            brazo->moverPantalla(0.01);
            timer = 1;
            break;
        }
    }
}

void MainWindow::brazoMovN() {
    switch (estado) {
        case 0: {
            // Girar Hombro.
            brazo->girarHombro(-0.01);
            timer = 1;
            break;
        }
        case 1: {
            // Mover Hombro.
            brazo->moverHombro(-0.01);
            timer = 1;
            break;
        }
        case 2: {
            // Mover Antebrazo.
            brazo->moverAntebrazo(-0.01);
            timer = 1;
            break;
        }
        case 3: {
            // Girar Pantalla.
            brazo->girarPantalla(-0.01);
            timer = 1;
            break;
        }
        case 4: {
            // Mover Pantalla.
            brazo->moverPantalla(-0.01);
            timer = 1;
            break;
        }
    }
}

void MainWindow::timerEvent(QTimerEvent *) {
    if (tp != 0) {
        if (tp == 1) {
            brazoMovP();
        } else if (tp == 2) {
            brazoMovN();
        }
    }
    if (timer != 0) {
        ui->widget_1->updateGL();
        ui->widget_2->updateGL();
        ui->widget_3->updateGL();
        ui->widget_4->updateGL();
        timer = 0;
    }
}

void MainWindow::keyPressEvent(QKeyEvent *event) {
    if (event->key() == Qt::Key_Right) {
        cx++;
        timer = 1;
    } else if (event->key() == Qt::Key_Left) {
        cx--;
        timer = 1;
    } else if (event->key() == Qt::Key_Up) {
        cy++;
        timer = 1;
    } else if (event->key() == Qt::Key_Down) {
        cy--;
        timer = 1;
    } else if (event->key() == Qt::Key_Q) {
        cz++;
        timer = 1;
    } else if (event->key() == Qt::Key_E) {
        cz--;
        timer = 1;
    } else if (event->key() == Qt::Key_Z) {
        brazoMovP();
    } else if (event->key() == Qt::Key_X) {
        brazoMovN();
    }
}

void MainWindow::on_actionAbrir_triggered() {
    QString dir = QFileDialog::getOpenFileName(this, "Abrir");
    QFile file(dir);
    file.open(QIODevice::ReadOnly | QIODevice::Text);
    QDomDocument document;
    document.setContent(&file);
    brazo = new Brazo();
    brazo->abrir(document);
    timer = 1;
}

void MainWindow::on_actionGirar_Hombro_triggered() {
    estado = 0;
}

void MainWindow::on_actionMover_Hombro_triggered() {
    estado = 1;
}

void MainWindow::on_actionMover_Antebrazo_triggered() {
    estado = 2;
}

void MainWindow::on_actionGirar_Pantalla_triggered() {
    estado = 3;
}

void MainWindow::on_actionMover_Pantalla_triggered() {
    estado = 4;
}
<file_sep>#ifndef HOMBRO_H
#define HOMBRO_H

#include "objeto3d.h"

class Hombro : public Objeto3D {
private:
    Eje *ejeVer;
    Eje *ejeHor;

public:
    Hombro();
    Eje *getEjeVer();
    Eje *getEjeHor();
    void setEjeVer(Eje *);
    void setEjeVer(float, float, float, float, float, float);
    void setEjeHor(Eje *);
    void setEjeHor(float, float, float, float, float, float);
    Hombro *copia();
    void girar(float);
    void mover(float);
};

#endif // HOMBRO_H
<file_sep>#include "widget.h"
#include "mainwindow.h"
#include "QtOpenGL"
#include "GL/glu.h"

int cwidget = 0;
int xa = 0;

Widget::Widget(QWidget *parent) : QGLWidget(parent) {
}

void Widget::initializeGL() {
    qglClearColor(Qt::white);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);

    GLfloat lightPosition[] = { 0, 20, 15, 1 };
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

    GLfloat lightAmbient[] = { 1, 1, 1, 0 };
    glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmbient);
}

void Widget::resizeGL(int w, int h) {
    glViewport(0, 0, w, h);
}

void Widget::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, 1, 1, 100);

    switch (cwidget) {
        case 0: {
            gluLookAt(cx, cy, cz, 0, 0, 0, 0, 1, 0);
            cwidget++;
            break;
        }
        case 1: {
            // Lateral derecha.
            gluLookAt(18, 5, 0, 0, 0, 0, 0, 1, 0);
            cwidget++;
            break;
        }
        case 2: {
            // Vista superior.
            gluLookAt(0, 18, 5, 0, 0, 0, 0, 0, -1);
            cwidget++;
            break;
        }
        case 3: {
            // Vista posterior.
            gluLookAt(0, 5, -18, 0, 0, 0, 0, 1, 0);
            cwidget = 0;
            break;
        }
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(-5, -3, 4);
    if (brazo != 0) {
        brazo->desplegar();
    }
}

void Widget::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        tp = 1;
    } else if (event->button() == Qt::RightButton) {
        tp = 2;
    }
}

void Widget::mouseMoveEvent(QMouseEvent *event) {
    float x = event->x();
    switch (estado) {
        case 0: {
            // Girar Hombro.
            if (x > xa) {
                brazo->girarHombro(0.01);
            } else {
                brazo->girarHombro(-0.01);
            }
            xa = x;
            timer = 1;
            break;
        }
        case 1: {
            // Mover Hombro.
            if (x > xa) {
                brazo->moverHombro(0.01);
            } else {
                brazo->moverHombro(-0.01);
            }
            xa = x;
            timer = 1;
            break;
        }
        case 2: {
            // Mover Antebrazo.
            if (x > xa) {
                brazo->moverAntebrazo(0.01);
            } else {
                brazo->moverAntebrazo(-0.01);
            }
            xa = x;
            timer = 1;
            break;
        }
        case 3: {
            // Girar Pantalla.
            if (x > xa) {
                brazo->girarPantalla(0.01);
            } else {
                brazo->girarPantalla(-0.01);
            }
            xa = x;
            timer = 1;
            break;
        }
        case 4: {
            // Mover Pantalla.
            if (x > xa) {
                brazo->moverPantalla(0.01);
            } else {
                brazo->moverPantalla(-0.01);
            }
            xa = x;
            timer = 1;
            break;
        }
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *) {
    tp = 0;
}
<file_sep>#include "objeto3d.h"
#include "cmath"

Objeto3D::Objeto3D() {
    inicio = 0;
    final = 0;
}

Objeto3D::~Objeto3D() {
}

Superficie *Objeto3D::getInicio() {
    return inicio;
}

Superficie *Objeto3D::getFinal() {
    return final;
}

void Objeto3D::setInicio(Superficie *inicio) {
    this->inicio = inicio;
}

void Objeto3D::setFinal(Superficie *final) {
    this->final = final;
}

Objeto3D *Objeto3D::copia() {
    Objeto3D *c = new Objeto3D();
    Superficie *s = inicio;
    while (s != 0) {
        c->agregar(s->copia());
        s = s->getSig(); // s++;
    }
    return c;
}

void Objeto3D::agregar(Superficie *s) {
    if (inicio == 0) {
        inicio = s;
        final = s;
    } else {
        final->setSig(s);
        final = s;
    }
}

void Objeto3D::transformar(Matriz3D *m) {
    Superficie *s = inicio;
    while (s != 0) {
        s->transformar(m);
        s = s->getSig(); // s++;
    }
}

void Objeto3D::rotar(Eje *eje, float ang) {
    float x1 = eje->getP1()->getX();
    float y1 = eje->getP1()->getY();
    float z1 = eje->getP1()->getZ();
    float x2 = eje->getP2()->getX();
    float y2 = eje->getP2()->getY();
    float z2 = eje->getP2()->getZ();
    float a = x2 - x1;
    float b = y2 - y1;
    float c = z2 - z1;
    float alfa = atan(b / c);
    if (isnan(alfa)) {
        alfa = 3.1416;
    }
    if (c < 0) {
        alfa += 3.1416;
    }
    float d = sqrt(pow(b, 2) + pow(c, 2));
    float beta = atan(a / d);
    Matriz3D *T1 = new Matriz3D(
                1, 0, 0, -x1,
                0, 1, 0, -y1,
                0, 0, 1, -z1); // -T
    Matriz3D *Rx1 = new Matriz3D(
                1, 0, 0, 0,
                0, cos(alfa), -sin(alfa), 0,
                0, sin(alfa), cos(alfa), 0); // +A
    Matriz3D *Ry1 = new Matriz3D(
                cos(-beta), 0, sin(-beta), 0,
                0, 1, 0, 0,
                -sin(-beta), 0, cos(-beta), 0); // -B
    Matriz3D *Rz = new Matriz3D(
                cos(ang), -sin(ang), 0, 0,
                sin(ang), cos(ang), 0, 0,
                0, 0, 1, 0);
    Matriz3D *Ry2 = new Matriz3D(
                cos(beta), 0, sin(beta), 0,
                0, 1, 0, 0,
                -sin(beta), 0, cos(beta), 0); // +B
    Matriz3D *Rx2 = new Matriz3D(
                1, 0, 0, 0,
                0, cos(-alfa), -sin(-alfa), 0,
                0, sin(-alfa), cos(-alfa), 0); // -A
    Matriz3D *T2 = new Matriz3D(
                1, 0, 0, x1,
                0, 1, 0, y1,
                0, 0, 1, z1); // +T
    Matriz3D *M = T2->mult(Rx2->mult(Ry2->mult(Rz->mult(Ry1->mult(Rx1->mult(T1))))));
    transformar(M);
}

void Objeto3D::desplegar() {
    Superficie *s = inicio;
    while (s != 0) {
        s->desplegar();
        s = s->getSig(); // s++;
    }
}
<file_sep>#ifndef BRAZO_H
#define BRAZO_H

#include "QtXml"
#include "qfiledialog.h"

#include "hombro.h"
#include "antebrazo.h"
#include "pantalla.h"

class Brazo {
private:
    Hombro *hombro;
    Antebrazo *antebrazo;
    Pantalla *pantalla;

public:
    Brazo();
    Hombro *getHombro();
    Antebrazo *getAntebrazo();
    Pantalla *getPantalla();
    void setHombro(Hombro *);
    void setAntebrazo(Antebrazo *);
    void setPantalla(Pantalla *);
    Brazo *copia();
    void abrir(QDomDocument);
    void girarHombro(float);
    void moverHombro(float);
    void moverAntebrazo(float);
    void girarPantalla(float);
    void moverPantalla(float);
    void desplegar();
};

#endif // BRAZO_H
<file_sep>#include "eje.h"
#include "cmath"
#include "QtOpenGL"

Eje::Eje(Punto *p1, Punto *p2) : Linea(p1, p2) {
}

void Eje::rotar(Eje *eje, float ang) {
    float x1 = eje->getP1()->getX();
    float y1 = eje->getP1()->getY();
    float z1 = eje->getP1()->getZ();
    float x2 = eje->getP2()->getX();
    float y2 = eje->getP2()->getY();
    float z2 = eje->getP2()->getZ();
    float a = x2 - x1;
    float b = y2 - y1;
    float c = z2 - z1;
    float alfa = atan(b / c);
    if (isnan(alfa)) {
        alfa = 3.1416;
    }
    if (c < 0) {
        alfa += 3.1416;
    }
    float d = sqrt(pow(b, 2) + pow(c, 2));
    float beta = atan(a / d);
    Matriz3D *T1 = new Matriz3D(
                1, 0, 0, -x1,
                0, 1, 0, -y1,
                0, 0, 1, -z1); // -T
    Matriz3D *Rx1 = new Matriz3D(
                1, 0, 0, 0,
                0, cos(alfa), -sin(alfa), 0,
                0, sin(alfa), cos(alfa), 0); // +A
    Matriz3D *Ry1 = new Matriz3D(
                cos(-beta), 0, sin(-beta), 0,
                0, 1, 0, 0,
                -sin(-beta), 0, cos(-beta), 0); // -B
    Matriz3D *Rz = new Matriz3D(
                cos(ang), -sin(ang), 0, 0,
                sin(ang), cos(ang), 0, 0,
                0, 0, 1, 0);
    Matriz3D *Ry2 = new Matriz3D(
                cos(beta), 0, sin(beta), 0,
                0, 1, 0, 0,
                -sin(beta), 0, cos(beta), 0); // +B
    Matriz3D *Rx2 = new Matriz3D(
                1, 0, 0, 0,
                0, cos(-alfa), -sin(-alfa), 0,
                0, sin(-alfa), cos(-alfa), 0); // -A
    Matriz3D *T2 = new Matriz3D(
                1, 0, 0, x1,
                0, 1, 0, y1,
                0, 0, 1, z1); // +T
    Matriz3D *M = T2->mult(Rx2->mult(Ry2->mult(Rz->mult(Ry1->mult(Rx1->mult(T1))))));
    transformar(M);
}

void Eje::desplegar() {
    glLineWidth(1);
    glColor3f(1, 0, 0);

    glBegin(GL_LINES);
    glVertex3f(p1->getX(), p1->getY(), p1->getZ());
    glVertex3f(p2->getX(), p2->getY(), p2->getZ());
    glEnd();
}
<file_sep>#include "brazo.h"

Brazo::Brazo() {
    hombro = new Hombro();
    antebrazo = new Antebrazo();
    pantalla = new Pantalla();
}

Hombro *Brazo::getHombro() {
    return hombro;
}

Antebrazo *Brazo::getAntebrazo() {
    return antebrazo;
}

Pantalla *Brazo::getPantalla() {
    return pantalla;
}

void Brazo::setHombro(Hombro *hombro) {
    this->hombro = hombro;
}

void Brazo::setAntebrazo(Antebrazo *antebrazo) {
    this->antebrazo = antebrazo;
}

void Brazo::setPantalla(Pantalla *pantalla) {
    this->pantalla = pantalla;
}

Brazo *Brazo::copia() {
    Brazo *c = new Brazo();
    c->setHombro(hombro->copia());
    c->setAntebrazo(antebrazo->copia());
    c->setPantalla(pantalla->copia());
    return c;
}

void Brazo::abrir(QDomDocument qd) {
    QDomElement brazo = qd.firstChildElement();
    QDomElement objeto = brazo.firstChildElement();
    while (objeto.isElement()) {
        // Vectores verticales y horizontales.
        float vx1 = objeto.attribute("VX1").toFloat();
        float vy1 = objeto.attribute("VY1").toFloat();
        float vz1 = objeto.attribute("VZ1").toFloat();
        float vx2 = objeto.attribute("VX2").toFloat();
        float vy2 = objeto.attribute("VY2").toFloat();
        float vz2 = objeto.attribute("VZ2").toFloat();
        float hx1 = objeto.attribute("HX1").toFloat();
        float hy1 = objeto.attribute("HY1").toFloat();
        float hz1 = objeto.attribute("HZ1").toFloat();
        float hx2 = objeto.attribute("HX2").toFloat();
        float hy2 = objeto.attribute("HY2").toFloat();
        float hz2 = objeto.attribute("HZ2").toFloat();
        if (objeto.tagName() == "Hombro") {
            hombro->setEjeVer(vx1, vy1, vz1, vx2, vy2, vz2);
            hombro->setEjeHor(hx1, hy1, hz1, hx2, hy2, hz2);
        } else if (objeto.tagName() == "Antebrazo") {
            antebrazo->setEjeVer(vx1, vy1, vz1, vx2, vy2, vz2);
            antebrazo->setEjeHor(hx1, hy1, hz1, hx2, hy2, hz2);
        } else if (objeto.tagName() == "Pantalla") {
            pantalla->setEjeVer(vx1, vy1, vz1, vx2, vy2, vz2);
            pantalla->setEjeHor(hx1, hy1, hz1, hx2, hy2, hz2);
        }
        QDomElement superficie = objeto.firstChildElement();
        while (superficie.isElement()) {
            float rojo = superficie.attribute("ROJO").toFloat();
            float verde = superficie.attribute("VERDE").toFloat();
            float azul = superficie.attribute("AZUL").toFloat();
            float nx = superficie.attribute("NX").toFloat();
            float ny = superficie.attribute("NY").toFloat();
            float nz = superficie.attribute("NZ").toFloat();
            Superficie *s = new Superficie();
            s->setColor(rojo, verde, azul);
            s->setNormal(nx, ny, nz);
            QDomElement vertice = superficie.firstChildElement();
            while (vertice.isElement()) {
                float x = vertice.attribute("X").toFloat();
                float y = vertice.attribute("Y").toFloat();
                float z = vertice.attribute("Z").toFloat();
                Vertice *v = new Vertice(x, y, z);
                s->agregar(v);
                vertice = vertice.nextSiblingElement(); // v++;
            }
            if (objeto.tagName() == "Hombro") {
                hombro->agregar(s);
            } else if (objeto.tagName() == "Antebrazo") {
                antebrazo->agregar(s);
            } else if (objeto.tagName() == "Pantalla") {
                pantalla->agregar(s);
            }
            superficie = superficie.nextSiblingElement(); // s++;
        }
        objeto = objeto.nextSiblingElement(); // o++;
    }
}

void Brazo::girarHombro(float ang) {
    hombro->girar(ang);

    antebrazo->rotar(hombro->getEjeVer(), ang);
    antebrazo->getEjeVer()->rotar(hombro->getEjeVer(), ang);
    antebrazo->getEjeHor()->rotar(hombro->getEjeVer(), ang);

    pantalla->rotar(hombro->getEjeVer(), ang);
    pantalla->getEjeVer()->rotar(hombro->getEjeVer(), ang);
    pantalla->getEjeHor()->rotar(hombro->getEjeVer(), ang);
}

void Brazo::moverHombro(float ang) {
    hombro->mover(ang);

    antebrazo->rotar(hombro->getEjeHor(), ang);
    antebrazo->getEjeVer()->rotar(hombro->getEjeHor(), ang);
    antebrazo->getEjeHor()->rotar(hombro->getEjeHor(), ang);

    pantalla->rotar(hombro->getEjeHor(), ang);
    pantalla->getEjeVer()->rotar(hombro->getEjeHor(), ang);
    pantalla->getEjeHor()->rotar(hombro->getEjeHor(), ang);
}

void Brazo::moverAntebrazo(float ang) {
    antebrazo->mover(ang);

    pantalla->rotar(antebrazo->getEjeHor(), ang);
    pantalla->getEjeVer()->rotar(antebrazo->getEjeHor(), ang);
    pantalla->getEjeHor()->rotar(antebrazo->getEjeHor(), ang);
}

void Brazo::girarPantalla(float ang) {
    pantalla->girar(ang);
}

void Brazo::moverPantalla(float ang) {
    pantalla->mover(ang);
}

void Brazo::desplegar() {
    hombro->desplegar();
    hombro->getEjeVer()->desplegar();
    hombro->getEjeHor()->desplegar();

    antebrazo->desplegar();
    antebrazo->getEjeVer()->desplegar();
    antebrazo->getEjeHor()->desplegar();

    pantalla->desplegar();
    pantalla->getEjeVer()->desplegar();
    pantalla->getEjeHor()->desplegar();
}
<file_sep>#ifndef OBJETO3D_H
#define OBJETO3D_H

#include "superficie.h"
#include "eje.h"

class Objeto3D {
protected:
    Superficie *inicio;
    Superficie *final;

public:
    Objeto3D();
    ~Objeto3D();
    Superficie *getInicio();
    Superficie *getFinal();
    void setInicio(Superficie *);
    void setFinal(Superficie *);
    Objeto3D *copia();
    void agregar(Superficie *);
    void transformar(Matriz3D *);
    void rotar(Eje *, float);
    void desplegar();
};

#endif // OBJETO3D_H
<file_sep>#ifndef EJE_H
#define EJE_H

#include "linea.h"

class Eje : public Linea {
public:
    Eje(Punto *, Punto *);
    void rotar(Eje *, float);
    void desplegar();
};

#endif // EJE_H
<file_sep>#include "linea.h"

Linea::Linea() {
    p1 = new Punto();
    p2 = new Punto();
}

Linea::Linea(Punto *p1, Punto *p2) {
    this->p1 = p1;
    this->p2 = p2;
}

Linea::Linea(float x1, float y1, float z1, float x2, float y2, float z2) {
    p1 = new Punto(x1, y1, z1);
    p2 = new Punto(x2, y2, z2);
}

Punto *Linea::getP1() {
    return p1;
}

Punto *Linea::getP2() {
    return p2;
}

void Linea::setP1(Punto *p1) {
    this->p1 = p1;
}

void Linea::setP1(float x, float y, float z) {
    p1 = new Punto(x, y, z);
}

void Linea::setP2(Punto *p2) {
    this->p2 = p2;
}

void Linea::setP2(float x, float y, float z) {
    p2 = new Punto(x, y, z);
}

Linea *Linea::copia() {
    return new Linea(p1->copia(), p2->copia());
}

void Linea::transformar(Matriz3D *m) {
    p1->transformar(m);
    p2->transformar(m);
}
<file_sep>#ifndef WIDGET_H
#define WIDGET_H

#include <QGLWidget>

class Widget : public QGLWidget {
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);

public slots:
    void initializeGL();
    void resizeGL(int, int);
    void paintGL();
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
};

#endif // WIDGET_H
<file_sep>#include "matriz3d.h"

Matriz3D::Matriz3D() {
    matriz[0][0] = 1;
    matriz[0][1] = 0;
    matriz[0][2] = 0;
    matriz[0][3] = 0;

    matriz[1][0] = 0;
    matriz[1][1] = 1;
    matriz[1][2] = 0;
    matriz[1][3] = 0;

    matriz[2][0] = 0;
    matriz[2][1] = 0;
    matriz[2][2] = 1;
    matriz[2][0] = 0;

    matriz[3][0] = 0;
    matriz[3][1] = 0;
    matriz[3][2] = 0;
    matriz[3][3] = 1;
}

Matriz3D::Matriz3D(float a, float b, float c, float d,
                   float e, float f, float g, float h,
                   float i, float j, float k, float l) {
    matriz[0][0] = a;
    matriz[0][1] = b;
    matriz[0][2] = c;
    matriz[0][3] = d;

    matriz[1][0] = e;
    matriz[1][1] = f;
    matriz[1][2] = g;
    matriz[1][3] = h;

    matriz[2][0] = i;
    matriz[2][1] = j;
    matriz[2][2] = k;
    matriz[2][3] = l;

    matriz[3][0] = 0;
    matriz[3][1] = 0;
    matriz[3][2] = 0;
    matriz[3][3] = 1;
}

float Matriz3D::getDato(int i, int j) {
    return matriz[i][j];
}

void Matriz3D::setDato(int i, int j, float d) {
    matriz[i][j] = d;
}

Matriz3D *Matriz3D::copia() {
    Matriz3D *c = new Matriz3D();
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            c->setDato(i, j, matriz[i][j]);
        }
    }
    return c;
}

Matriz3D *Matriz3D::mult(Matriz3D *obj) {
    Matriz3D *aux = new Matriz3D();
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            float d =
                    matriz[i][0] * obj->getDato(0, j) +
                    matriz[i][1] * obj->getDato(1, j) +
                    matriz[i][2] * obj->getDato(2, j) +
                    matriz[i][3] * obj->getDato(3, j);
            aux->setDato(i, j, d);
        }
    }
    return aux;
}
