На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! правила раздела Алгоритмы
1. Помните, что название темы должно хоть как-то отражать ее содержимое (не создавайте темы с заголовком ПОМОГИТЕ, HELP и т.д.). Злоупотребление заглавными буквами в заголовках тем ЗАПРЕЩЕНО.
2. При создании темы постарайтесь, как можно более точно описать проблему, а не ограничиваться общими понятиями и определениями.
3. Приводимые фрагменты исходного кода старайтесь выделять тегами code.../code
4. Помните, чем подробнее Вы опишете свою проблему, тем быстрее получите вразумительный совет
5. Запрещено поднимать неактуальные темы (ПРИМЕР: запрещено отвечать на вопрос из серии "срочно надо", заданный в 2003 году)
6. И не забывайте о кнопочках TRANSLIT и РУССКАЯ КЛАВИАТУРА, если не можете писать в русской раскладке :)
Модераторы: Akina, shadeofgray
  
> как заставить закрутиться кубик
    Народ вот кусок функции рисующий линию в 3хмерных координатах

    void CKubikDlg::draw3dline(int x1,int y1,int z1,int x2,int y2,int z2,int ch)
    {
    float kx1,kx2,ky1,ky2;
    kx1 = x1 + x1 * (z1 * 0.007);
    ky1 = y1 + y1 * (z1 * 0.007);
    kx2 = x2 + x2 * (z2 * 0.007);
    ky2 = y2 + y2 * (z2 * 0.007);
    line(kx1,ky1,kx2,ky2,ch);

    }
    А как заставить его крутиться програмно, причем не по ламерски как в тесте директ 3Д, а по нажатию клавишь? При чем вертеться он должен на трёх осях симетрии(куба)Типа как глобус.
    Да, чуть не забыл, должен быть эфект фокуса, это когда дальние грани куба меньше передних.
      Вращай точки куба. Создай матрицу оборота или кватернионы оборота. Для матриц: создай матрицы оборота вокруг всех осей и перемножь (помня, что порядок умножения играет роль).
      Что у тебя за ф-ия проекции какая-то странная.
      Обычно берется x1 = x*C/z, y1 = y*C/z, а константа C высчитывается в зависимости от угла видения и величины окна-экрана.
      Фокус.. толщину линии сделай зависимой от z..
      При нажатии определенной клавиши оборачивай куб на данный угол.
        Вопрос достаточно объемный чтобы ответить на него одним постом.

        Проще работать с векторами. Значит нужен соответствующий класс.
        Все преобразования с векторами удобно делать в матричной форме --- класс матрицы
        Классы всех примитивов: отрезок, параллелепипед, и тд.
        Класс пространства с экранной плоскостью и со свойствами перспективы (проецирования).
        В общем, тут вариантов может быть много.

        При таком подходе, повернуть примитив вокруг одной из своих осей достаточно просто. Нужно перемножить матрицу вершин на матрицу вращения.
        Примерно так
        CODE

        CVector one(1, 1, 1);
        CVector two(9, 9, 9);

        CKub sample_kub(one, two);
        CKub rotated_kub;

        CMatrix matrix();

        CSpace space;

        matrix.RotateZ(10);

        rotated_kub = sample_kub * matrix;

        space.view(rotated_kub);


        Необходимо правильно математически реализовать вектора, матрицы, перспективу и их свойства.

        Как вариант смотри ниже
          CODE
          // Объявление класса вектор
          // Vectors.hpp

          #ifndef __VECTORS__
          #define __VECTORS__

          #include <math.h>

          //========================================================================
          class Vector
          {
          public:
           double x,y,z;
           //Vector();
           inline Vector(){x = y = z = 0;}
           Vector(double v) {x = y = z = v;};  // конструктор с одним параметром
           Vector(const Vector& v){x = v.x; y = v.y; z = v.z;};  // конструктор копировани
           Vector(double vx, double vy, double vz){x = vx; y = vy; z = vz;};  // конструктор с установкой всех координат
           Vector& operator = (const Vector& v)  // оператор присваивания вектора вектору
                  {x = v.x; y = v.y; z = v.z; return *this;};
           Vector& operator = (double f) {x = y = z = f; return *this;};  // оператор присваивания одного числа всем координатам
           Vector operator - ()const;          // оператор инвертирования всех координат
           Vector& operator += (const Vector&); // оператор увеличения координат одного вектора на координаты другого вектора
           Vector& operator -= (const Vector&); // оператор уменьшения координат одного вектора из координат другого вектора
           Vector& operator *= (const Vector&); // оператор умножения координат одного вектра на координаты другого вектора
           Vector& operator *= (double); // оператор умножения координат вектора на число
           Vector& operator /= (double); // оператор деления координат вектора на число

           friend Vector operator + (const Vector&,const Vector&); // оператор сложения векторов
           friend Vector operator - (const Vector&,const Vector&); // оператор вычитания векторов
           friend Vector operator * (const Vector&,const Vector&); // оператор перемножения векторов
           friend Vector operator * (double,const Vector&); // оператор умножения числа на вектор
           friend Vector operator * (const Vector&,double); // оператор умножения вектора на число
           friend Vector operator / (const Vector&,double); // оператор деления вектора на число
           friend Vector operator / (const Vector&,const Vector&); // оператор деления векторов
           friend double operator & (const Vector& u,const Vector& v); // оператор скалярного произведени
           friend Vector operator ^ (const Vector&,const Vector&); // оператор векторного произведени
           double operator ! () {return (double) sqrt(x*x + y*y + z*z);}; // оператор вычисления длинны вектора
           double& operator [] (int n) {return *(&x + n);}; // оператор получения компонента вектора
           int  operator < (double v){return x < v && y < v && z < v;}; // оператор сравнения векторов
           int  operator > (double v){return x > v && y > v && z > v;}; // оператор сравнения векторов
           int  operator <= (double v){return x <= v && y <= v && z <= v;}; // оператор сравнения векторов
           int  operator >= (double v){return x >= v && y >= v && z >= v;}; // оператор сравнения векторов
          //   operator int() {return (int)x,(int)y;};
          };

          //========================================================================
            class Ray
             {
              public:
               Vector Org;
               Vector Dir;
               Ray () {};
               Ray (Vector& o,Vector& d) {Org = 0;Dir = d;};
              Vector Point (double t){return Org + Dir*t;};
             };

          //========================================================================
          // Конструктор по умолчанию

          //========================================================================
          // оператор инвертирования всех координат вектора
          inline Vector Vector::operator - ()const
          {
           return Vector(-x,-y,-z);
          }
          //========================================================================
          // оператор скалярного произведения векторов
          inline double operator & (const Vector& u,const Vector& v)
          {
           return u.x*v.x + u.y*v.y + u.z*v.z;
          }
          //========================================================================
          // оператор сложения векторов
          inline Vector operator + (const Vector& u,const Vector& v)
          {
           return Vector (u.x + v.x,u.y + v.y, u.z + v.z);
          }
          //========================================================================
          // оператор вычитания векторов
            inline Vector operator - (const Vector& u,const Vector& v)
             {
              return Vector (u.x - v.x,u.y - v.y, u.z - v.z);
             }
          //========================================================================
          // оператор перемножения векторов
            inline Vector operator * (const Vector& u,const Vector& v)
             {
              return Vector (u.x * v.x,u.y * v.y, u.z * v.z);
             }
          //========================================================================
          // оператор умножения вектора на число
            inline Vector operator * (const Vector& u,double f)
             {
              return Vector (u.x * f,u.y * f, u.z * f);
             }
          //========================================================================
          // оператор умножения числа на вектор
            inline Vector operator * (double f, const Vector& u)
             {
              return Vector (f * u.x, f * u.y, f * u.z);
             }
          //========================================================================
          // оператор деления вектора на число
            inline Vector operator / (const Vector& u, double f)
             {
              return Vector (u.x / f, u.y / f, u.z / f);
             }
          //========================================================================
          // оператор деления векторов
            inline Vector operator / (const Vector& u, const Vector& v)
             {
              return Vector (u.x / v.x, u.y / v.y, u.z / v.z);
             }
          //========================================================================
          // оператор увеличения координат одного вектора на координаты другого вектора
           inline Vector&  Vector:: operator += (const Vector& v)
            {
             x+= v.x;
             y+= v.y;
             z+= v.z;
              return *this;
            }
          //========================================================================
          // оператор уменьшения координат одного вектора из координаты другого вектора
           inline Vector&  Vector:: operator -= (const Vector& v)
            {
             x-= v.x;
             y-= v.y;
             z-= v.z;
              return *this;
            }
          //========================================================================
          // оператор умножения координат вектора на число
           inline Vector&  Vector:: operator *= (double v)
            {
             x*= v;
             y*= v;
             z*= v;
              return *this;
            }
          //========================================================================
          // оператор умножения координат одного вектра на координаты другого вектора
           inline Vector&  Vector::operator *= (const Vector& v)
            {
             x*= v.x;
             y*= v.y;
             z*= v.z;
              return *this;
            }
          //========================================================================
          // оператор деления координат вектора на число
           inline Vector&  Vector:: operator /= (double v)
            {
             x/= v;
             y/= v;
             z/= v;
              return *this;
            }

          //========================================================================
          inline Vector Normalize(Vector& v){return v/!v;};  // Нормализация вектора
          //========================================================================
          // получение равномерно распределенного случайного единичного вектора
          Vector RndVector();
          //========================================================================
          Vector& Clip (Vector&);                // отсечение вектора

          #endif
            CODE

            // Vectors.cpp

            #include <math.h>
            #include <stdlib.h>
            #include "Vectors.hpp"
            //========================================================================
            // оператор векторного произведени
            Vector operator ^ (const Vector& u,const Vector& v)
             {
              return Vector (u.y * v.z - u.z * v.y , u.z * v.x - u.x * v.z,
                 u.x * v.y - u.y * v.x);
             }
            //========================================================================
            // получение равномерно распределенного случайного единичного вектора
             Vector RndVector()
              {
                Vector v(rand() - 0.5*RAND_MAX,
                  rand() - 0.5*RAND_MAX,rand() - 0.5*RAND_MAX);
                return Normalize(v);
              }
            //========================================================================
            // отсечение вектора
             Vector& Clip (Vector& v)
              {
                if (v.x < 0.0) v.x = 0.0;
                 else
                  if (v.x > 1.0) v.x = 1.0;
                 if (v.y < 0.0) v.y = 0.0;
                  else
            if (v.y > 1.0) v.y = 1.0;
                 if (v.z < 0.0) v.z = 0.0;
                  else
            if (v.z > 1.0) v.z = 1.0;
                return v;
              }
            //========================================================================
            Сообщение отредактировано: MeG -
              CODE
              // Определение класса матриц преобразования векторов
              // MATRIX.HPP

              #ifndef __MATRIX__
              #define __MATRIX__

              #include "Vectors.hpp"

              class Matrix
              {
               public:
               double x[4][4];
               Matrix () {};
               Matrix (double); // конструктор диагональной матрицы
               Matrix& operator += (const Matrix&); // прибавить матрицу
               Matrix& operator -= (const Matrix&);  // вычесть матрицу
               Matrix& operator *= (const Matrix&);  // умножить матрицу на матрицу
               Matrix& operator *= (double);      // умножить матрицу на число
               Matrix& operator /= (double);      // разделить матирцу на число
               void Invert();
               void Transpose();                  // транспонировать матрицу
               friend Matrix operator + (const Matrix&,const Matrix&);// сложить матрицы
               friend Matrix operator - (const Matrix&,const Matrix&);// вычесть матрицы
               friend Matrix operator * (const Matrix&,double);  // умножить матрицу
               friend Matrix operator * (const Matrix&,const Matrix&);// перемножить матрицы
               friend Vector operator * (const Matrix&,const Vector&);// перемножить матрицу и вектор
              };
               Matrix Translate (const Vector&);    // передвинуть матрицу на вектор
               Matrix Scale (const Vector&);        // масштабировать матрицу
               Matrix RotateX (double);             // повернуть матрицу вокруг X
               Matrix RotateY (double);             // повернуть матрицу вокруг Y
               Matrix RotateZ (double);             // повернуть матрицу вокруг Z
               Matrix Rotate (const Vector& v,double);// повернуть матрицу вокруг вектора
               Matrix MirrorX ();
               Matrix MirrorY ();
               Matrix MirrorZ ();

              #endif
                CODE
                // Matrix.cpp

                #include <math.h>
                #include "Matrix.hpp"

                //========================================================================
                Matrix::Matrix(double v)// конструктор диагональной матрицы
                {
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                     x[i][j]=(i==j)?v:0.0;
                 x[3][3]=1;
                }

                //========================================================================
                void Matrix::Invert()
                {
                 Matrix Out(1);
                 for (int i = 0; i < 4; i++)
                 {
                   double d = x[i][i];
                   if (d != 1.0)
                   {
                     for (int j = 0; j < 4; j++)
                     {
                       Out.x[i][j] /= d;
                       x[i][j] /= d;
                     }
                   }
                   for (int j = 0; j < 4; j++)
                   {
                     if (j != i)
                     {
                       if (x[j][i] != 0.0)
                       {
                         double mulby = x[j][i];
                         for (int k = 0; k < 4; k++)
                         {
                           x[j][k] -= mulby * x[i][k];
                           Out.x[j][k] -= mulby * Out.x[i][k];
                         }
                       }
                     }
                   }
                 }
                 *this = Out;
                }

                //========================================================================
                // транспонировать матрицу
                void Matrix::Transpose()
                {
                 double t;
                 for (int i = 0; i < 4; i++)
                   for (int j = i; j < 4; j++)
                     if (i != j)
                     {
                       t = x[i][j];
                       x[i][j]= x[j][i];
                       x[j][i]= t;
                     }
                }

                //========================================================================
                Matrix& Matrix::operator += (const Matrix& A)
                {
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                     x[i][j]  += A.x[i][j];
                 return *this;
                }

                //========================================================================
                Matrix& Matrix::operator -= (const Matrix& A)
                {
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                     x[i][j]  -= A.x[i][j];
                 return *this;
                }

                //========================================================================
                Matrix& Matrix::operator *= (double v)
                {
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                     x[i][j]  *= v;
                 return *this;
                }

                //========================================================================
                Matrix& Matrix::operator *= (const Matrix& A)
                {
                 Matrix res = *this;
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                   {
                     double sum = 0;
                     for (int k = 0; k < 4; k++)
                       sum += res.x[i][k] * A.x[k][j];
                     x[i][j]  = sum;
                   }
                 return *this;
                }

                //========================================================================
                Matrix  operator + (const Matrix& A,const Matrix& B)
                {
                 Matrix res;
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                      res.x[i][j] = A.x[i][j] + B.x[i][j];
                 return res;
                }

                //========================================================================
                Matrix  operator - (const Matrix& A,const Matrix& B)
                {
                 Matrix res;
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                     res.x[i][j] = A.x[i][j] - B.x[i][j];
                 return res;
                }

                //========================================================================
                Matrix  operator * (const Matrix& A,const Matrix& B)
                {
                 Matrix res;
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                   {
                     double sum = 0;
                     for (int k = 0; k < 4; k++)
                       sum +=  A.x[i][k] * B.x[k][j];
                     res.x[i][j] = sum;
                   }
                 return res;
                }

                //========================================================================
                Matrix  operator * (const Matrix& A,double v)
                {
                 Matrix res;
                 for (int i = 0; i < 4; i++)
                   for (int j = 0; j < 4; j++)
                     res.x[i][j] = A.x[i][j] * v;
                return res;
                }

                //========================================================================
                Vector operator * (const Matrix& M,const Vector& v)
                {
                 Vector res;
                 res.x = v.x * M.x[0][0] + v.y * M.x[1][0] + v.z * M.x[2][0] + M.x[3][0];
                 res.y = v.x * M.x[0][1] + v.y * M.x[1][1] + v.z * M.x[2][1] + M.x[3][1];
                 res.z = v.x * M.x[0][2] + v.y * M.x[1][2] + v.z * M.x[2][2] + M.x[3][2];
                 double denom = v.x * M.x[0][3] + v.y * M.x[1][3] + v.z * M.x[2][3] + M.x[3][3];
                 if ( denom != 1.0)
                   res /= denom;
                 return res;
                }

                //========================================================================
                Matrix Translate (const Vector& Loc)
                {
                 Matrix res(1);
                 res.x[3][0] = Loc.x;
                 res.x[3][1] = Loc.y;
                 res.x[3][2] = Loc.z;
                 return res;
                }

                //========================================================================
                Matrix Scale (const Vector& v)
                {
                 Matrix res(1);
                 res.x[0][0] = v.x;
                 res.x[1][1] = v.y;
                 res.x[2][2] = v.z;
                 return res;
                }

                //========================================================================
                Matrix RotateX (double Angle)
                {
                 Matrix res(1);
                 double Cosine = cos(Angle);
                 double Sine = sin(Angle);
                 res.x[1][1] = Cosine;
                 res.x[2][1] = -Sine;
                 res.x[1][2] = Sine;
                 res.x[2][2] = Cosine;
                 return res;
                }

                //========================================================================
                Matrix RotateY (double Angle)
                {
                 Matrix res(1);
                 double Cosine = cos(Angle);
                 double Sine = sin(Angle);
                 res.x[0][0] = Cosine;
                 res.x[2][0] = -Sine;
                 res.x[0][2] = Sine;
                 res.x[2][2] = Cosine;
                 return res;
                }

                //========================================================================
                Matrix RotateZ (double Angle)
                {
                 Matrix res(1);
                 double Cosine = cos(Angle);
                 double Sine = sin(Angle);
                 res.x[0][0] = Cosine;
                 res.x[1][0] = -Sine;
                 res.x[0][1] = Sine;
                 res.x[1][1] = Cosine;
                 return res;
                }

                //========================================================================
                Matrix Rotate (const Vector& axis, double Angle)
                {
                 Matrix res(1);
                 double Cosine = cos(Angle);
                 double Sine = sin(Angle);
                 res.x[0][0] = axis.x * axis.x + (1 - axis.x * axis.x)* Cosine;
                 res.x[0][1] = axis.x * axis.y * (1 - Cosine) + axis.z * Sine;
                 res.x[0][2] = axis.x * axis.z * (1 - Cosine) - axis.y * Sine;
                 res.x[0][3] = 0;
                 res.x[1][0] = axis.x * axis.y * (1 - Cosine) - axis.z * Sine;
                 res.x[1][1] = axis.y * axis.y + (1 - axis.y * axis.y)* Cosine;
                 res.x[1][2] = axis.y * axis.z * (1 - Cosine) + axis.x * Sine;
                 res.x[1][3] = 0;
                 res.x[2][0] = axis.x * axis.z * (1 - Cosine) + axis.y * Sine;
                 res.x[2][1] = axis.y * axis.z * (1 - Cosine) - axis.x * Sine;
                 res.x[2][2] = axis.z * axis.z + (1 - axis.z * axis.z)* Cosine;
                 res.x[2][3] = 0;
                 res.x[3][0] = 0;
                 res.x[3][1] = 0;
                 res.x[3][2] = 0;
                 res.x[3][3] = 1;
                 return res;
                }

                //========================================================================
                Matrix MirrorX ()
                {
                 Matrix res(1);
                 res.x[0][0] = -1;
                 return res;
                }

                //========================================================================
                Matrix MirrorY ()
                {
                 Matrix res(1);
                 res.x[1][1] = -1;
                 return res;
                }

                //========================================================================
                Matrix MirrorZ ()
                {
                 Matrix res(1);
                 res.x[2][2] = -1;
                 return res;
                }

                //========================================================================
                  CODE
                  // Класс отрезок
                  // SEGMENT.HPP

                  #ifndef __SEGMENT__
                  #define __SEGMENT__

                  #include "vectors.hpp"
                  #include "matrix.hpp"

                  class segment
                  {
                  private:
                   Vector begin_point, end_point;
                   int status;
                  public:
                   inline segment(){status = 0;}
                   inline segment(Vector b, Vector e)
                       {begin_point = b, end_point = e, status = 1;}
                   inline segment(Vector b, Vector e, int s)
                       {begin_point = b, end_point = e, status = s;}
                   segment & operator = (const segment &);
                  //  segment & operator * (const Matrix &);
                   friend segment  operator * (const segment &, const Matrix &);
                   inline Vector & get_begin(){return begin_point;};
                   inline Vector & get_end(){return end_point;};
                   inline int & get_status(){return status;};
                   inline Vector & operator [](int n)
                       {if(n) return end_point; else return begin_point;};
                  };

                  #endif
                    CODE
                    // SEGMENT.cpp

                    #include "segment.hpp"

                    //========================================================================
                    /*segment::segment(const segment & RR)
                    {
                     begin_point.x = RR.begin_point.x;
                     begin_point.y = RR.begin_point.y;
                     begin_point.z = RR.begin_point.z;
                     end_point = RR.end_point;
                     status = RR.status;
                    }*/
                    //========================================================================
                    segment & segment::operator = (const segment & s)
                    {
                     begin_point = s.begin_point;
                     end_point = s.end_point;
                     status = s.status; return * this;
                    }

                    //========================================================================
                    /*segment & segment::operator * (const Matrix & m)
                    {
                     begin_point = m * begin_point;
                     end_point = m * end_point;
                     return * this;
                    } */

                    //========================================================================
                    segment operator * (const segment & s, const Matrix & m)
                    {
                     return segment(m * s.begin_point, m * s.end_point, s.status);
                    }
                      CODE
                      // Параллелепипед
                      // PARALL0.HPP
                      #ifndef __PARALL0__
                      #define __PARALL0__
                      #include "vectors.hpp"
                      #include "matrix.hpp"
                      #include "segment.hpp"
                      class parall
                      {
                      private:
                       Vector tlb, brf;         // две вершины задающие параллелепипед
                       Vector solid[8];         // вершины позиционированные
                       segment view_table[12];  // отрезки на картинной плоскости
                       Vector normal[6];        // нормали к граням параллелепипеда
                       Matrix AA;
                       Matrix pos;      // матрица позиционирования параллелепипеда
                       void create_solid();// создает массивы вершин и нормалей к граням
                       int vis_seg(int, Vector);// проверка видимости ребра
                       float vis_plane(int, Vector);// проверка видимости грани
                      public:
                       parall();//{Matrix BB(1); AA = BB; pos = BB;}
                       segment * rot_x(int);
                       segment * rot_y(int);
                       segment * rot_z(int);
                       segment * rot_v(int);
                       segment * get_V_table(const Vector, const Matrix V);
                       inline Vector & get_tlb(){return tlb;}
                       inline Vector & get_brf(){return brf;}
                       inline Vector * get_solid(){return solid;}
                       inline Vector * get_normal(){return normal;}
                       inline Matrix & get_pos(){return pos;}
                       //inline int get_status(){return 0;}
                      };
                      #endif
                      Сообщение отредактировано: MeG -
                        CODE
                        // parall0.cpp

                        #include "parall0.hpp"

                        //========================================================================
                        parall::parall()
                        {
                         Matrix BB(1);
                         AA = BB;
                         pos = BB;
                         //tlb = Vector(-20);
                         //brf = Vector(80);
                         tlb = Vector(-30, -50, -30);
                         brf = Vector(30, 50, 50);
                        }

                        //========================================================================
                        void parall::create_solid()
                        {
                         //pos = RotateX(1.0);
                         //pos = RotateY(1.0) *  RotateX(1.0);
                         //pos = Scale( Vector() = 1.5) * RotateY(3.1415926 / 4) * RotateX(3.1415926 / 4);
                         //pos = Scale( Vector() = 1.5);
                         solid[0] = pos * tlb;                          // слева, сверху, сзади
                         solid[1] = pos * Vector(tlb.x, tlb.y, brf.z);  // слева, сверху, спереди
                         solid[2] = pos * Vector(brf.x, tlb.y, brf.z);  // справа, сверху, спереди
                         solid[3] = pos * Vector(brf.x, tlb.y, tlb.z);  // справа, сверху, сзади
                         solid[4] = pos * Vector(brf.x, brf.y, tlb.z);  // справа, снизу, сзади
                         solid[5] = pos * Vector(tlb.x, brf.y, tlb.z);  // слева, снизу, сзади
                         solid[6] = pos * Vector(tlb.x, brf.y, brf.z);  // слева, снизу, спереди
                         solid[7] = pos * brf;                          // спрва, снизу, спереди

                         normal[0] = pos * Vector(0, -1, 0);    // к верхней грани
                         normal[1] = pos * Vector(-1, 0, 0);   // к левой грани
                         normal[2] = pos * Vector(0, 0, 1);    // к передней грани
                         normal[3] = pos * Vector(1, 0, 0);    // к правой грани
                         normal[4] = pos * Vector(0, 0, -1);   // к задней грани
                         normal[5] = pos * Vector(0, 1, 0);   // к нижней грани
                        }

                        //========================================================================
                        // Заполняет таблицу отрезков и возвращает указатель на нее
                        segment * parall::get_V_table(const Vector d, const Matrix  V)
                        {
                         create_solid();
                         //vis_plane(d);//(Vector)//вычисляет cos_seg[6] с позиции камеры
                         view_table[0] = segment(solid[0], solid[1], vis_seg(0, d)) * V;
                         view_table[1] = segment(solid[1], solid[2], vis_seg(1, d)) * V;
                         view_table[2] = segment(solid[2], solid[3], vis_seg(2, d)) * V;
                         view_table[3] = segment(solid[0], solid[3], vis_seg(3, d)) * V;
                         view_table[4] = segment(solid[0], solid[5], vis_seg(4, d)) * V;
                         view_table[5] = segment(solid[1], solid[6], vis_seg(5, d)) * V;
                         view_table[6] = segment(solid[2], solid[7], vis_seg(6, d)) * V;
                         view_table[7] = segment(solid[3], solid[4], vis_seg(7, d)) * V;
                         view_table[8] = segment(solid[4], solid[5], vis_seg(8, d)) * V;
                         view_table[9] = segment(solid[5], solid[6], vis_seg(9, d)) * V;
                         view_table[10] = segment(solid[6], solid[7], vis_seg(10, d)) * V;
                         view_table[11] = segment(solid[7], solid[4], vis_seg(11, d)) * V;
                         return view_table;
                        }

                        //========================================================================

                        //========================================================================
                        // вычисляет видимость грани с позиции точки размещения камеры
                        float parall::vis_plane(int n, Vector s)
                        {
                         Vector v;
                         switch(n)
                         {
                           case 0 : v = solid[0]; break;       // 0, 1, 2, 3
                           case 1 : v = solid[0]; break;       // 0, 1, 5, 6
                           case 2 : v = solid[1]; break;       // 1, 2, 6, 7
                           case 3 : v = solid[2]; break;       // 2, 3, 4, 7
                           case 4 : v = solid[0]; break;       // 0, 3, 4, 5
                           case 5 : v = solid[4]; break;       // 4, 5, 6, 7
                         }
                         return normal[n].z * s.z - (normal[n].x * v.x +
                             normal[n].y * v.y + normal[n].z * v.z);
                        }

                        //========================================================================
                        // вычисляет видимость ребра
                        // возвращает номер типа линии для данного отрезка
                        int parall::vis_seg(int seg, Vector dir)
                        {
                         int v_s = 8, nv_s = 10;
                         switch(seg)
                         {
                           case 0: return
                           ((vis_plane(0, dir) < 0) && (vis_plane(1, dir) < 0)) ? nv_s : v_s;
                           case 1: return
                           ((vis_plane(0, dir) < 0) && (vis_plane(2, dir) < 0)) ? nv_s : v_s;
                           case 2: return
                           ((vis_plane(0, dir) < 0) && (vis_plane(3, dir) < 0)) ? nv_s : v_s;
                           case 3: return
                           ((vis_plane(0, dir) < 0) && (vis_plane(4, dir) < 0)) ? nv_s : v_s;
                           case 4: return
                           ((vis_plane(4, dir) < 0) && (vis_plane(1, dir) < 0)) ? nv_s : v_s;
                           case 5: return
                           ((vis_plane(2, dir) < 0) && (vis_plane(1, dir) < 0)) ? nv_s : v_s;
                           case 6: return
                           ((vis_plane(2, dir) < 0) && (vis_plane(3, dir) < 0)) ? nv_s : v_s;
                           case 7: return
                           ((vis_plane(3, dir) < 0) && (vis_plane(4, dir) < 0)) ? nv_s : v_s;
                           case 8: return
                           ((vis_plane(4, dir) < 0) && (vis_plane(5, dir) < 0)) ? nv_s : v_s;
                           case 9: return
                           ((vis_plane(1, dir) < 0) && (vis_plane(5, dir) < 0)) ? nv_s : v_s;
                           case 10: return
                           ((vis_plane(2, dir) < 0) && (vis_plane(5, dir) < 0)) ? nv_s : v_s;
                           case 11: return
                           ((vis_plane(3, dir) < 0) && (vis_plane(5, dir) < 0)) ? nv_s : v_s;
                         }
                         return 0;
                        }
                        //========================================================================
                          CODE
                          // Класс пространства
                          // Space.hpp
                          #ifndef __SPACE__
                          #define __SPACE__
                          #include "vectors.hpp"
                          #include "matrix.hpp"
                          #include "segment.hpp"
                          #include "parall0.hpp"
                          #include "seg_cross.hpp"
                          class space
                          {
                          //Vector * m_pp;
                          Vector m_center;
                          Vector view_center;
                          Vector camera_center;
                          Matrix view, proj;
                          segment AA, BB, CC;
                          segment axisX, axisY, axisZ;
                          segment seg[40], * par;
                          int proj_num;
                          parall parallelepiped;
                          Matrix & projection(int); // номер проекции
                          crosser line_c;
                          public:
                          space();
                          Vector & get_view_center();
                          void set_out_seg();
                          segment & get_seg(int);
                          segment & get_axis(int);
                          segment * get_parall();
                          inline segment * get_line()
                          {
                          line_c.inwardly(parallelepiped.get_solid(),
                          parallelepiped.get_normal());
                          // line_c.shadow(camera_center, parallelepiped.get_solid());
                          return line_c.get_cross(view);
                          };
                          inline Matrix & get_p_pos()
                          {
                          return parallelepiped.get_pos();
                          }
                          inline void move_seg_ex(int dx){line_c.move_end(Vector(dx, 0, 0));}
                          inline void move_seg_bx(int dx){line_c.move_begin(Vector(dx, 0, 0));}
                          };
                          #endif

                          CODE
                          Vector view_center; --- вектор для промежуточных вычислений матрицы
                          отображения;
                          Vector camera_center; --- вектор указывающий положение камеры;
                          Matrix view; --- матрица проецирования;
                          int proj_num; --- номер проекции;
                          parall parallelepiped; --- сам параллелепипед;
                          crosser line_c; --- пересекаемая линия;
                          методы:
                          Matrix & projection(int); --- устанавливает и возвращает матрицу проецирования;
                          space();] --- конструктор класса;
                          Vector & get_view_center(); --- возвращает ссылку на вектор смещения центра координат;
                          segment * get_parall(); --- возвращает указатель массива отрезков параллелепипеда;
                          segment * get_line(); --- возвращает указатель массива отрезков рассекаемой линии;
                          Matrix & get_p_pos() --- берет ссылку из объекта параллелепипеда на матрицу позиционирования;
                          void move_seg_ex(int dx) --- передает в объект пересекаемой линии смещение конца отрезка;
                          void move_seg_bx(int dx) --- передает в объект пересекаемой линии смещение начала отрезка;
                            а ещё говорят, что с++ - лаконичный язык!!
                            да я на паскале 3д екшын написал в ~600 строк, включая мыша и вывод на екран!!!
                            а если только ядро, то ~200 строк
                            http://enzyme.nm.ru/vrash.rar /action.exe
                            выходить буквой q
                              Лаконичный-лаконичный smile.gif

                              Если теперь забыть про внутренности етой векторно-матричной библиотеки, то вся программа будет написана в виде

                              vect2 = vect1 * matr3;
                              smile.gif
                                ну так у меня тоже приблизительно так, правда у меня матрица каждый раз заново считается sad.gif
                                только если её считать заранее, наверняка моя программа станет ещё меньше, со всеми внутренностями!
                                  2 wormball
                                  что то я не заметил что у тебя меньше кода wink.gif


                                  полностью программа с сорцами (управляется стрелками, +, -, правой кнопкой мыши)
                                  Сообщение отредактировано: MeG -
                                    утебя 52 килобайта, уменя 14 килобайт :P
                                    тебя наверное ввели в заблуждение остальные файлы, которые там есь. собственно исходников екшына четыре: action.pas, kol_mov.pas, _13h.pas и mouse.pas .
                                    зы. уменя там оказывается есь архив в чистом виде
                                    http://enzyme.nm.ru/prog/action.rar
                                    ззы. только ето немного более ранняя версия
                                    Сообщение отредактировано: wormball -

                                    Прикреплённый файлПрикреплённый файлaction.rar (35.95 Кбайт, скачиваний: 193)
                                      Блин ну вы даёте...Перемножать матрицы долго, Вот фукция поворота любой точки на плоскости вокруг данной на угол 4 пи/180. Применив такую фукцию к каждой точке куба спроектированой на одну из трёх плоскостей(те про одну из трех координат забываем), он повернётся мать его... Только надо обратить внимание на /*float Abs(float)*/.......
                                      void CKubikDlg::TurnVertex(int cx,int cy, float &x,float &y,int q)
                                      {
                                      float u,a,b,c;
                                      a=cx-x;b=cy-y;c=sqrt(a*a+b*;
                                      u = acos(Abs(a) / c) + q*(4*3.14/180) * b / Abs( * a / Abs(a) ;
                                      x=cx+c*cos(u)* a / (Abs(a) * (-1));
                                      y=cy+c*sin(u)* b / (Abs( * (-1));
                                      }
                                      сорец может дам попозжЕ.
                                        прямо скажем, не лучшее решение во избежание смайликов - удалить их к чёртовой бабушке в исходнике. лучше бы выключил галку со смайлами или писал бы всё в [code]
                                        более того, ты ошибаешься, что перемножать матрицы долго. там всего 9 умножений, как и у тебя, а у тебя ещё и синусы с корнями, что куда дольше.
                                          vect2 - это типа координаты вершины, а чё такое vect1? matr3-типа матрица поворота, лады. тогда
                                          как она заполняется, если надо повернуть на Альфа градусов по XY, по часовой стрелке?
                                            QUOTE (Serg-Zerg @ 15.11.03, 16:25)
                                            vect2 - это типа координаты вершины, а чё такое vect1? matr3-типа матрица поворота, лады. тогда
                                            как она заполняется, если надо повернуть на Альфа градусов по XY, по часовой стрелке?

                                            Тебе же MeG сорс выложил, там все есть. Осталось только copy-paste wink.gif. Матрица оборота строится или по шпаргалке (vide MeG's source) или оборачивая базовые версоры (что ты и сделал неявно). Перемножать матрицы недолго, зато в одной 4х4 матрице хранится инфа про обороты и перемещение ВСЕХ вершин, тебе остается только
                                            QUOTE
                                            vect2 = vect1 * matr3;
                                            каждую вершину.
                                            з.ы. тут vect1 - исходные координаты, vect2 - конечные координаты (после оборота-перемещения).
                                              QUOTE (Serg-Zerg @ 16.11.03, 00:25)
                                              vect2 - это типа координаты вершины, а чё такое vect1? matr3-типа матрица поворота, лады. тогда
                                              как она заполняется, если надо повернуть на Альфа градусов по XY, по часовой стрелке?

                                              Тут произошло разделение понятий. vect2 и vect1 нужно понимать как список вершин гарфического примитива. В моих сорцах вектор --- это направленный отрезок из начала координат в данную точку, а список координат содержится в соответствующем классе примитива.
                                              Если тебе нужно вращать параллелепипед:
                                              CODE
                                              // задаешь параллелепипед двумя вершинами главной диагонали, все стороны параллельны осям координат.
                                              CVector Avector(1, 1, 1); // левый нижний передний угол параллелепипеда
                                              CVector Bvector(3, 5, 7); // правый верхний задний угол параллелепипеда
                                              // в конструкторе получаешь координаты всех вершин примитива
                                              CParallelepiped Primitive(Avector, Bvector);
                                              CMatrix Rmatrix; // матрица без инициализации
                                              Rmatrix = RotateX(0.5); // получаем матрицу поворота вокруг оси X на 0,5 радиана

                                              Дальше нужно поворачивать примитив и отображать его
                                              CODE

                                              ByTimer(...)
                                              {
                                              Primitive.View(DC);
                                              Primitive *= Rmatrix;
                                              }

                                              CParallelepiped содержит в себе массив своих вершин
                                              CVector m_Vertex[8];
                                              и ребер
                                              int m_Segments[12][12]; // номера начальной и конечной вершин (векторов вершин)
                                              Функция Matrix RotateX (double);
                                              CODE
                                              Matrix RotateX (double Angle)
                                              {
                                              Matrix res(1);
                                              double Cosine = cos(Angle);
                                              double Sine = sin(Angle);
                                              res.x[1][1] = Cosine;
                                              res.x[2][1] = -Sine;
                                              res.x[1][2] = Sine;
                                              res.x[2][2] = Cosine;
                                              return res;
                                              }
                                              это глобальная функция, она не является членом какого-либо класса. Создает матрицу поворота вокруг начала координат. Внутри нее создается объект класса Matrix. Возвращает объект класса Matrix.
                                              В строчке Rmatrix = RotateX(0.5); используется оператрор присваивания по умолчанию, то есть матрица возвращаемая из RotateX() копируется один в один в матрицу Rmatrix.
                                              Для чего так сделано? Чтобы иметь однообразную запись для любых афинных преобразований.
                                              Rmatrix = RotateX(.) * RotateY(.) * Scale(.) * Translate(.); --- повернуть, повернуть, отмасштабировать, переместить. Таким образом можно получить любые преобразования объекта в пространстве.
                                                2 Serg-Zerg
                                                Вокруг чего ты собрался вращать?
                                                Вокруг начала координат, вокруг одного из ребер примитива, вокруг геометрического центра примитива, вокруг оси коодинат, вокруг некоторой прямой?
                                                  Афинные преобразования в пространстве в общем виде

                                                  Про координаты.
                                                  Чтобы иметь возможность сделать любые преобразования примитива в трехмерном пространстве, необходимо использовать однородные координаты!
                                                  то есть A(x, y, z, 1) --- четыре кооринаты, четвертая координата имеет геометрический смысл масштаба. Хранить четвертую координату не нужно, достаточно во всех алгоритмах преобразования приводить ее к единице.
                                                  Соответственно матрицы преобразования тоже размера 4х4


                                                  Матрицы в общем виде
                                                  • Матрицы вращения в пространстве
                                                    Вокруг оси X на угол A
                                                  CODE

                                                  Rx = | 1     0     0     0 |
                                                       | 0   cosA  sinA    0 |
                                                       | 0  -sinA  cosA    0 |
                                                       | 0     0     0     1 |

                                                  Вокруг оси Y на угол A
                                                  CODE

                                                  Ry = | cosA 0   -sinA  0  |
                                                       |  0    1    0    0  |
                                                       | sinA  0 cosA    0  |
                                                       |  0    0    0    1  |

                                                  Вокруг оси Z на угол A
                                                  CODE

                                                  Rz = |  cosA  sinA 0    0  |
                                                      | -sinA cosA  0    0  |
                                                       |   0    0    1    0  |
                                                       |   0    0    0    1  |


                                                • Матрица масштабирования
                                                  A --- вдоль оси X, B --- вдоль оси Y, C --- вдоль оси Z. A > 0, B > 0, C > 0.
                                                • CODE

                                                  |D| = | A  0  0  0 |
                                                        | 0  B  0  0 |
                                                        | 0  0  C  0 |
                                                        | 0  0  0  1 |


                                                • Матрицы отражения (зеркального)
                                                  относительно плоскости XY
                                                • CODE

                                                  |Mz| = | 1  0  0  0 |
                                                          | 0  1  0  0 |
                                                         | 0  0 -1  0 |
                                                         | 0  0  0  1 |


                                                  относительно плоскости YZ
                                                  CODE

                                                  |Mx| = | -1 0  0  0 |
                                                         | 0  1  0  0 |
                                                         | 0  0  1  0 |
                                                         | 0  0  0  1 |


                                                  относительно плоскости XZ
                                                  CODE

                                                  |My| = | 1  0  0  0 |
                                                         | 0 -1  0  0 |
                                                         | 0  0  1  0 |
                                                         | 0  0  0  1 |

                                                • Матрица переноса
                                                  a, b, c --- вектор переноса
                                                • CODE

                                                  |T| = | 1  0  0  0 |
                                                        | 0  1  0  0 |
                                                        | 0  0  1  0 |
                                                        | a  b  c  1 |
                                                  Сообщение отредактировано: MeG -
                                                    Проекции
                                                    Что это такое?
                                                    Есть трехмерное пространство, в этом пространстве резмещены трехмерные объекты. Нужно каким-то образом показать эти трехмерные объекты на плоском экране. Для этого и существуют проекции.Видов проекций огромное количество.
                                                    Преимущественно применяется параллельное и центральное проектирование (у каждого из них есть несколько подвидов)

                                                    Помещаем в наше пространство плоскость --- экранную плоскость, на нее мы будем проектировать наши трехмерные объекты, и изображение на этой плоскости будем выводить на экан монитора.
                                                    Дальше нужно задать направление проектирования. Для этого помещаем в пространство камеру. Камера имеет положение в пространстве и направление взгляда (вектор).
                                                    Для того чтоб на экранной плоскости чтото было видно, необходимо: направить камеру на наши трехмерные объекты, и разместить экранную плоскость между камерой и объектами. Обычно, экранная плоскость перпендикулярна направлению взгляда камеры, это позволяет упростить расчеты.
                                                    Удобно экранную плоскость разместить в начале координат нашего пространства, на одной из координатных проскостей, например XY. Камеру разместить на оси Z и направить в начало координат O(0, 0, 0). Камера будет описываться двумя векторами: положение Position(0, 0, -100) и направление Direction(0, 0, 1). Все трехмерные объекты размещаем по другую сторону экранной плоскости, для всех точек объектов координата Z будет больше нуля.

                                                    Проектируем.
                                                    На входе у нас массив трехмерных координат объектов в пространстве. На выходе массив двухмерных координат на экранной плоскости.
                                                    Паралельное проектирование (то которое тебе не нравится, нарушается перспектива), тут, по сути, камера не нужна
                                                    Матрица проектирования на плоскость параллельную координатной плоскости XY
                                                    | 1 0 0 0 |
                                                    | 0 1 0 0 |
                                                    | 0 0 0 0 |
                                                    | 0 0 k 1 |
                                                    k --- это смещение экранной плоскости воль оси Z
                                                    Как это применить? Берем все координаты трехмерных объектов и перемножаем на эту матрицу проектирования, получаем множество точек у которых координата z равна нулю (x, y, 0). Просто выводим эти точки на экран по X и Y, изображение готово.

                                                    Если матрицу проектирования домножать на матрицу поворота (поворачивать экранную плоскость), можно получить различные виды паралельного проектирования: диметрию, триметрию, изометрию. Еще немного извратившись с этой матрицей проектирования, можно получить свободную и кабинетную параллельные проекции.


                                                    Центральное (перспективное) проектирование
                                                    Матрица перспективного проектирования на плоскость XY, (z = 0) Камера находится в точке (0, 0, c)
                                                    | 1 0 0 0 |
                                                    | 0 1 0 0 |
                                                    | 0 0 0 -1/c|
                                                    | 0 0 0 1 |

                                                    Матрица перспективного проектирования на плоскость XY, для камеры в любой точке (a, b, c)пространства
                                                    | 1 0 0 -1/a |
                                                    | 0 1 0 -1/b |
                                                    | 0 0 0 -1/c |
                                                    | 0 0 k 1 |
                                                    k --- это смещение экранной плоскости воль оси Z

                                                    Применять матрицы перспективного проектирования так же как и матрицы параллельного проектирования.

                                                    Для изменения вида проекции остаточно просто сменить одну матрицу на другую.
                                                    Сообщение отредактировано: MeG -
                                                      QUOTE (MeG @ 16.11.03, 07:42)
                                                      2 Serg-Zerg
                                                      Вокруг чего ты собрался вращать?
                                                      Вокруг начала координат, вокруг одного из ребер примитива, вокруг геометрического центра примитива, вокруг оси коодинат, вокруг некоторой прямой?

                                                      Мечтал вокруг геометрического центра, но думаю вокруг оси коодинат будет более чем достаточно.
                                                        Чтобы повернуть объект вокруг своего геометрического центра нужно:
                                                        - найти координаты этого геометрического центра
                                                        - переместить объект в начало координат
                                                        - повернуть объект на требуемый угол
                                                        - переместить объект на пержнее место
                                                        CODE
                                                        CVector center(x1, y1, z1); // вектор из начала координат в геометрический центр.
                                                        double angleX = 0.1;     // угол поворота вокруг оси X
                                                        double angleZ = -0.3;     // угол поворота вокруг оси Z

                                                        CKub primitive; // вращаемый объект

                                                        CMatrix transform; // матрица преобразований

                                                        transform = Translate(-center) * RotateX(angleX) * RotateZ(angleZ) * Translate(center);

                                                        primitive *= transform; // вращаем объект вокруг своего центра
                                                        Сообщение отредактировано: MeG -
                                                          QUOTE
                                                          Матрица проектирования на плоскость параллельную координатной плоскости XY
                                                          | 1 0 0 0 |
                                                          | 0 1 0 0 |
                                                          | 0 0 0 0 |
                                                          | 0 0 k 1 |
                                                          k --- это смещение экранной плоскости воль оси Z

                                                          а ещё курсовую по графике писал!! матрица проектирования переводит трёхмерный вектор в двумерный, стало быть она размера 3*2 и выглядит так (для плоскости ху):
                                                          1 0 0
                                                          0 1 0

                                                          QUOTE
                                                          Центральное (перспективное) проектирование
                                                          Матрица перспективного проектирования на плоскость XY, (z = 0) Камера находится в точке (0, 0, c)
                                                          | 1 0 0 0 |
                                                          | 0 1 0 0 |
                                                          | 0 0 0 -1/c|
                                                          | 0 0 0 1 |

                                                          Матрица перспективного проектирования на плоскость XY, для камеры в любой точке (a, b, c)пространства
                                                          | 1 0 0 -1/a |
                                                          | 0 1 0 -1/b |
                                                          | 0 0 0 -1/c |
                                                          | 0 0 k 1 |
                                                          k --- это смещение экранной плоскости воль оси Z

                                                          Применять матрицы перспективного проектирования так же как и матрицы параллельного проектирования.

                                                          Для изменения вида проекции остаточно просто сменить одну матрицу на другую.
                                                          враньё! при перспективе используется нелинейное преобразование - там вращают точку матрицей поворота и делят х и у на разность между z и точкой, в которой находится центр камеры, тоесь точкой (0, 0, -с).
                                                            Не горячитесь smile.gif Используются действительно четырехмерные вектора и матрицы 4х4, т.к, ими можно описать и повороты, и масштабирования, и, самое главное, перемещения объектов smile.gif. А вот как результаты операций интерпретируются (какие координаты вектора используются) -- ето уже другое дело smile.gif
                                                            Сообщение отредактировано: Visitor -
                                                              всёравно перспективу матрицей не опишешь!!
                                                                Матрицей чисел. smile.gif
                                                                  QUOTE (wormball @ 17.11.03, 21:39)
                                                                  всёравно перспективу матрицей не опишешь!!

                                                                  ты открой глазки пошире, увидишь исходники

                                                                  еще можешь подумать, и написать уравнение проекции и переложить его на матрицу
                                                                    исходники то понятное дело работают.

                                                                    просто дело в том что матрицы - ето по определению умножение на некоторые числа, а сдесь идёт деление на z - компоненту входного вектора.

                                                                    QUOTE
                                                                    еще можешь подумать, и написать уравнение проекции и переложить его на матрицу


                                                                    уменя как ты помнишь свои исходники есь, так что сей путь я тоже прошёл
                                                                      QUOTE (wormball @ 17.11.03, 22:01)
                                                                      просто дело в том что матрицы - ето по определению умножение на некоторые числа, а сдесь идёт деление на z - компоненту входного вектора.

                                                                      после умножения вектора на матрицу, результирующий вектор в однородных координатах (a, b, c, d) приводится к виду (a/d, b/d, c/d, 1) (смотри выше), где и происходит деление на z (для данной матрицы)
                                                                      Добавлено в
                                                                      специально для wormball

                                                                      CODE

                                                                      | x |   | 1   0   0   0 |
                                                                      | y | *| 0   1   0   0 | = ( x   y   0   1-z/c )    ->   ( x/(1 - z/c)   y/(1 - z/c)   0   1 )
                                                                      | z |   | 0   0   0 -1/c|
                                                                      | 1 |   | 0   0   0   1 |
                                                                      Сообщение отредактировано: MeG -
                                                                        ну так z у тебя каждый раз разное, так что ты не сможешь как с поворотом сначала вычислить одну матрицу, а потом на неё умножать smile.gif
                                                                          QUOTE (wormball @ 17.11.03, 22:19)
                                                                          ну так z у тебя каждый раз разное, так что ты не сможешь как с поворотом сначала вычислить одну матрицу, а потом на неё умножать smile.gif

                                                                          сам прочти что написал smile.gif

                                                                          в матрице нет z
                                                                          Сообщение отредактировано: MeG -
                                                                            уже прочёл rolleyes.gif
                                                                              Усе ж гораздо проще можно показать: вот у нас есть рельсы. Мы стоим между ними, и смотрим туда вдаль, куда они уходят. Как они будут выглядеть на фотографии, и как -- после обработки каждой из их точек линейным оператором?
                                                                                а чо ж ты тогда так защищаешь матрицы?? помоему с самого начала было ясно, что линейным оператором перспективы не получить
                                                                                  wоrmball прав в том, что при построении матрицы перспективного проецирования с помощью входного вектора пропадает смысл использовать матрицу (исходный смысл был в том, что много преобразований для разных точек можно сложить в одно; матрицу проецирования к этим преобразованиям не зачислишь).
                                                                                    vot!! smile.gif

                                                                                    зы. только щас понял, что вас было двое, а не один. щас пойду находить отличия во взглядах smile.gif
                                                                                    Сообщение отредактировано: wormball -
                                                                                      такето что получается, что у мега каждое умножение сопровождается делением?? так же нефефективно
                                                                                        QUOTE (wormball @ 18.11.03, 00:04)
                                                                                        такето что получается, что у мега каждое умножение сопровождается делением?? так же нефефективно

                                                                                        Только для тех векторов где четвертая координата отлична от единицы.
                                                                                        Смотри исходники, прежде чем коментировать
                                                                                          не хочу я ети тонны де**ма раскапывать!! всё равно, что ни говори, ето нелинейный оператор!
                                                                                            не понимаю сыр-бора. никто точку в пространстве вертеть не умеет, что ли? а восемь?
                                                                                            а матрицы эти я бы все на фиг повыкидывал. еще для них класс писать - слишком много чести. там больше все нули в этих матрицах поворота перемножаются и складываются, а времени при типе double тратиться немеренно, так что лучше сразу формулу писать без всякиз еб*чих матриц.
                                                                                              Так чтоже получается, мой способ, который был прозван неявным поворотом, оказывается мало того самым простым, так еще и быстрым для конкретной задачи, полчаса програмли+4часа разгрёба глюков=готово...
                                                                                                Быстрее всего и проще взять готовую библиотеку работы с матрицами от интела, опимизированную под MMX, где премножение вектора на матрицу делается за один такт
                                                                                                  QUOTE (MeG @ 18.11.03, 10:14)
                                                                                                  Быстрее всего и проще взять готовую библиотеку работы с матрицами от интела, опимизированную под MMX, где премножение вектора на матрицу делается за один такт

                                                                                                  Gde etu biblioteku vziat pod VC++ ?
                                                                                                      QUOTE
                                                                                                      не понимаю сыр-бора. никто точку в пространстве вертеть не умеет, что ли? а восемь?
                                                                                                      а матрицы эти я бы все на фиг повыкидывал. еще для них класс писать - слишком много чести. там больше все нули в этих матрицах поворота перемножаются и складываются, а времени при типе double тратиться немеренно, так что лучше сразу формулу писать без всякиз еб*чих матриц.

                                                                                                      ну так матрицы нужны, чтобы синусы каждый раз не вычислять, а нули перемножаются только вначале. а с фиксированной точкой ето геморрой
                                                                                                        QUOTE (wormball @ 19.11.03, 11:41)
                                                                                                        QUOTE
                                                                                                        не понимаю сыр-бора. никто точку в пространстве вертеть не умеет, что ли? а восемь?
                                                                                                        а матрицы эти я бы все на фиг повыкидывал. еще для них класс писать - слишком много чести. там больше все нули в этих матрицах поворота перемножаются и складываются, а времени при типе double тратиться немеренно, так что лучше сразу формулу писать без всякиз еб*чих матриц.

                                                                                                        ну так матрицы нужны, чтобы синусы каждый раз не вычислять, а нули перемножаются только вначале. а с фиксированной точкой ето геморрой

                                                                                                        так, если ты повернул кубик, тебе в любом случае предстоит посчитать синус, хоть ты в матрице, хоть нет. biggrin.gif или я не прав?
                                                                                                        и потом, что ты имел в виду, что с фиксированной точкой геморой? вроде бы в компе с плавающей точкой вычисление производится или я что-то подзабыл-попутал? вроде полигональную модель не представить путево в целых числах?
                                                                                                        в общем, колись! biggrin.gif
                                                                                                        Сообщение отредактировано: experimenter -
                                                                                                          Считать его не надо. Его надо брать из один раз для фиксированного шага угла рассчитанной sincos-таблицы.

                                                                                                          А матрицами или не матрицами, действительно по=, в рассуждении использования SIMD-команд процессора...
                                                                                                            QUOTE
                                                                                                            так, если ты повернул кубик, тебе в любом случае предстоит посчитать синус, хоть ты в матрице, хоть нет.  или я не прав?
                                                                                                            да, но с матрицами тебе его надо будет один раз посчитать, а потом умножать все точки на одну и ту же матрицу.
                                                                                                            QUOTE
                                                                                                            Считать его не надо. Его надо брать из один раз для фиксированного шага угла рассчитанной sincos-таблицы.

                                                                                                            помоему если ты щитаешь синусы один раз, а потом тысячу точек вертишь, то ты врядли на синусе много секономишь, к тому же талбица будет много памяти занимать.
                                                                                                            QUOTE
                                                                                                            и потом, что ты имел в виду, что с фиксированной точкой геморой? вроде бы в компе с плавающей точкой вычисление производится или я что-то подзабыл-попутал? вроде полигональную модель не представить путево в целых числах?
                                                                                                            в общем, колись! 

                                                                                                            я лично етим никогда не занимался, но говорят особо извращённые люди представляют вещественные числа как целые, а потом считают их целочисленной математикой. для етого даже ммх придумали. говорят получается быстрее.
                                                                                                              QUOTE (wormball @ 20.11.03, 12:23)
                                                                                                              QUOTE
                                                                                                              так, если ты повернул кубик, тебе в любом случае предстоит посчитать синус, хоть ты в матрице, хоть нет.  или я не прав?
                                                                                                              да, но с матрицами тебе его надо будет один раз посчитать, а потом умножать все точки на одну и ту же матрицу.
                                                                                                              QUOTE
                                                                                                              Считать его не надо. Его надо брать из один раз для фиксированного шага угла рассчитанной sincos-таблицы.

                                                                                                              помоему если ты щитаешь синусы один раз, а потом тысячу точек вертишь, то ты врядли на синусе много секономишь, к тому же талбица будет много памяти занимать.
                                                                                                              QUOTE
                                                                                                              и потом, что ты имел в виду, что с фиксированной точкой геморой? вроде бы в компе с плавающей точкой вычисление производится или я что-то подзабыл-попутал? вроде полигональную модель не представить путево в целых числах?
                                                                                                              в общем, колись! 

                                                                                                              я лично етим никогда не занимался, но говорят особо извращённые люди представляют вещественные числа как целые, а потом считают их целочисленной математикой. для етого даже ммх придумали. говорят получается быстрее.

                                                                                                              я про матрицы упомянул в том смысле, что когда ты матрицы множишь, то там много лишних операций выполняется. с моей точки зрения представление преобразований в виде перемножения матриц для компа - это не совсем рационально. зачем использовать матрицы, когда можно преобразования написать, типа
                                                                                                              CODE

                                                                                                              Vertex::RotateX(double Angle)
                                                                                                              {
                                                                                                              x = ...;
                                                                                                              y = ...;
                                                                                                              z = ...;
                                                                                                              }

                                                                                                              чем писать перемножения матриц, типа V = V*M; так как там делается много лишнего из-за разряженности матрицы.
                                                                                                                не понял я тебя..... чойто за код ты понаписал??
                                                                                                                  QUOTE (wormball @ 21.11.03, 09:08)
                                                                                                                  не понял я тебя..... чойто за код ты понаписал??

                                                                                                                  ну, вот как поворачивается точка на плоскости
                                                                                                                  CODE

                                                                                                                  x = x cos ф - y sin ф,
                                                                                                                  y = x sin  ф+ y cos ф.

                                                                                                                  а при записи того же в матричном представлении, да еще в однородных координатах, как это любят делать, будет куча умножения на ноль, которую не понятно зачем делать.
                                                                                                                    ну так на ноль можно не умножать, если не хочешь, зато у тебя куча синусов. и с помощью матриц можно поворачивать не только в плоскости ху, и можно несколько поворотов представлять как один. tongue.gif
                                                                                                                    говорят есь ищо кватернионы, с их помощью тоже можно вращать
                                                                                                                      QUOTE (wormball @ 21.11.03, 09:35)
                                                                                                                      ну так на ноль можно не умножать, если не хочешь, зато у тебя куча синусов. и с помощью матриц можно поворачивать не только в плоскости ху, и можно несколько поворотов представлять как один. tongue.gif
                                                                                                                      говорят есь ищо кватернионы, с их помощью тоже можно вращать

                                                                                                                      уже устал с тобой спорить. ты не хочешь понять, что тебе говорю. я сам делал, как ты говоришь и проповедую и это тормозит комп.
                                                                                                                        а мож у тебя процедура неправильная, или ты каждый раз синус вычислял?? а без матриц не тормозит?? покажи процедуру
                                                                                                                          Цитата (TrivialCore @ 13.11.03, 22:42)
                                                                                                                          Что у тебя за ф-ия проекции какая-то странная.
                                                                                                                          Обычно берется x1 = x*C/z, y1 = y*C/z, а константа C высчитывается в зависимости от угла видения и величины окна-экрана.

                                                                                                                          Спасибо всем учасникам, лабу здал, вот только МОЯ ф-ия проекции преподу не понравилась как правильно считать эту const C?
                                                                                                                            Цитата (wormball @ 21.11.03, 10:38)
                                                                                                                            а мож у тебя процедура неправильная, или ты каждый раз синус вычислял?? а без матриц не тормозит?? покажи процедуру

                                                                                                                            вот, что я пытался сказать. я написал вот так:

                                                                                                                            template <class T>
                                                                                                                            void CxVertex<T>::RotateX(double Angle)
                                                                                                                            {
                                                                                                                            T COS = cos(Angle);
                                                                                                                            T SIN  = sin(Angle);
                                                                                                                            T Y, Z;

                                                                                                                             Y  = y * COS - z * SIN;
                                                                                                                             Z  = y * SIN + z * COS;
                                                                                                                             y  = Y;
                                                                                                                             z  = Z;
                                                                                                                            }

                                                                                                                            а если написать вот так:

                                                                                                                            template <class T>
                                                                                                                            void CxVertex<T>::RotateX(double Angle)
                                                                                                                            {
                                                                                                                            CxMatrix <T> M(4,4);
                                                                                                                            M.Fill(T(0));
                                                                                                                            M.At(0,0) = 1;
                                                                                                                            M.At(1,1) = cos(Angle);
                                                                                                                            M.At(2,2) = M.At(1,1);
                                                                                                                            M.At(1,2) = -sin(Angle);
                                                                                                                            M.At(2,1) = -M.At(1,2);
                                                                                                                            v = M*v;
                                                                                                                            }

                                                                                                                            то при v = M*v; будет происходить вот, что:

                                                                                                                            template <class T>
                                                                                                                            CxMatrix<T>& CxMatrix<T>::operator *= (CxMatrix &m)
                                                                                                                            {
                                                                                                                            u_int i,j,k,Ni = GetNumRows(),Nj = GetNumColumns();
                                                                                                                            if(m.GetNumRows() != Nj)
                                                                                                                             throw INVALID_MATRIX_SIZES;
                                                                                                                            CxMatrix mRet(Ni,m.GetNumColumns());
                                                                                                                            T tFillValue = T(0);
                                                                                                                            mRet.Fill(tFillValue);
                                                                                                                            for(i = 0; i < Ni; i++)
                                                                                                                             for(j = 0; j < m.GetNumColumns(); j++)
                                                                                                                              for(k = 0; k < Nj; k++)
                                                                                                                              mRet.At(i,j) += At(i,k)*m.At(k,j);
                                                                                                                            *this = mRet;
                                                                                                                            return  *this;
                                                                                                                            }

                                                                                                                            что есть не так круто, как первое. не знаю, вообще, как эти матрицы вообще используются здесь, если они столько ресурсов жрут.

                                                                                                                              Матрицы используются 4x4 (кстати, ето Cyrix придумал, а не Intel), и размеры операционных векторов у SIMD-инструкций, как вы уже догадываетесь, тоже 4 эл-та, типа float или fixed 16.16 smile.gif

                                                                                                                              Итого умножение матрицы 4x4 на вектор 4 занимает 12 векторных операций -- 4 х загрузка, умножение, суммирование елементов. Как правило ето быстрее, чем работа по "оптимизированным" формулам, где поток операндов _меньше_, но _не_регулярен_ и параллельных операций нет...

                                                                                                                                Цитата (Serg-Zerg @ 21.11.03, 13:09)
                                                                                                                                Спасибо всем учасникам, лабу здал, вот только МОЯ ф-ия проекции преподу не понравилась как правильно считать эту const C?

                                                                                                                                Например так:
                                                                                                                                C = 360*Resx/(2*PI*angle)

                                                                                                                                angle - угол поля зрения в градусах, Resx - разрешение окна по х, PI = 3.1415926535

                                                                                                                                Добавлено в
                                                                                                                                Цитата (experimenter @ 21.11.03, 07:18)
                                                                                                                                Цитата (wormball @ 21.11.03, 09:08)
                                                                                                                                не понял я тебя..... чойто за код ты понаписал??

                                                                                                                                ну, вот как поворачивается точка на плоскости

                                                                                                                                x = x cos ф - y sin ф,
                                                                                                                                y = x sin  ф+ y cos ф.

                                                                                                                                а при записи того же в матричном представлении, да еще в однородных координатах, как это любят делать, будет куча умножения на ноль, которую не понятно зачем делать.

                                                                                                                                Обычно поворот состоит из 3-х поворотов вокруг 3-х осей. По твоему способу придется каждую точку повернуть 3 раза. Используя матрицу - 1 раз. Если к этому прибавить перемещение, то у тебя будут 4 действия (3 поворота + перемещение); используя матрицу - 1 действие.
                                                                                                                                  Цитата (TrivialCore @ 21.11.03, 19:44)
                                                                                                                                  Цитата (Serg-Zerg @ 21.11.03, 13:09)
                                                                                                                                  Спасибо всем учасникам, лабу здал, вот только МОЯ ф-ия проекции преподу не понравилась как правильно считать эту const C?

                                                                                                                                  Например так:
                                                                                                                                  C = 360*Resx/(2*PI*angle)

                                                                                                                                  angle - угол поля зрения в градусах, Resx - разрешение окна по х, PI = 3.1415926535

                                                                                                                                  Добавлено в
                                                                                                                                  Цитата (experimenter @ 21.11.03, 07:18)
                                                                                                                                  Цитата (wormball @ 21.11.03, 09:08)
                                                                                                                                  не понял я тебя..... чойто за код ты понаписал??

                                                                                                                                  ну, вот как поворачивается точка на плоскости

                                                                                                                                  x = x cos ф - y sin ф,
                                                                                                                                  y = x sin  ф+ y cos ф.

                                                                                                                                  а при записи того же в матричном представлении, да еще в однородных координатах, как это любят делать, будет куча умножения на ноль, которую не понятно зачем делать.

                                                                                                                                  Обычно поворот состоит из 3-х поворотов вокруг 3-х осей. По твоему способу придется каждую точку повернуть 3 раза. Используя матрицу - 1 раз. Если к этому прибавить перемещение, то у тебя будут 4 действия (3 поворота + перемещение); используя матрицу - 1 действие.

                                                                                                                                  ну, с этой точки зрения, я согласен. наверное, действительно, эффект дает о себе знать, при большом количестве поворотов и все такого. хм, да действительно. спасибо за подсказанную идейку. biggrin.gif
                                                                                                                                    Цитата
                                                                                                                                    ну так на ноль можно не умножать, если не хочешь, зато у тебя куча синусов. и с помощью матриц можно поворачивать не только в плоскости ху, и можно несколько поворотов представлять как один. 

                                                                                                                                    Цитата
                                                                                                                                    Обычно поворот состоит из 3-х поворотов вокруг 3-х осей. По твоему способу придется каждую точку повернуть 3 раза. Используя матрицу - 1 раз. Если к этому прибавить перемещение, то у тебя будут 4 действия (3 поворота + перемещение); используя матрицу - 1 действие.

                                                                                                                                    именно ето я и хотел сказать
                                                                                                                                    Цитата
                                                                                                                                    вот, что я пытался сказать. я написал вот так:



                                                                                                                                    template <class T>
                                                                                                                                    void CxVertex<T>::RotateX(double Angle)
                                                                                                                                    {
                                                                                                                                    T COS = cos(Angle);
                                                                                                                                    T SIN  = sin(Angle);
                                                                                                                                    T Y, Z;

                                                                                                                                    Y  = y * COS - z * SIN;
                                                                                                                                    Z  = y * SIN + z * COS;
                                                                                                                                    y  = Y;
                                                                                                                                    z  = Z;
                                                                                                                                    }



                                                                                                                                    а если написать вот так:



                                                                                                                                    template <class T>
                                                                                                                                    void CxVertex<T>::RotateX(double Angle)
                                                                                                                                    {
                                                                                                                                    CxMatrix <T> M(4,4);
                                                                                                                                    M.Fill(T(0));
                                                                                                                                    M.At(0,0) = 1;
                                                                                                                                    M.At(1,1) = cos(Angle);
                                                                                                                                    M.At(2,2) = M.At(1,1);
                                                                                                                                    M.At(1,2) = -sin(Angle);
                                                                                                                                    M.At(2,1) = -M.At(1,2);
                                                                                                                                    v = M*v;
                                                                                                                                    }



                                                                                                                                    то при v = M*v; будет происходить вот, что:



                                                                                                                                    template <class T>
                                                                                                                                    CxMatrix<T>& CxMatrix<T>::operator *= (CxMatrix &m)
                                                                                                                                    {
                                                                                                                                    u_int i,j,k,Ni = GetNumRows(),Nj = GetNumColumns();
                                                                                                                                    if(m.GetNumRows() != Nj)
                                                                                                                                    throw INVALID_MATRIX_SIZES;
                                                                                                                                    CxMatrix mRet(Ni,m.GetNumColumns());
                                                                                                                                    T tFillValue = T(0);
                                                                                                                                    mRet.Fill(tFillValue);
                                                                                                                                    for(i = 0; i < Ni; i++)
                                                                                                                                    for(j = 0; j < m.GetNumColumns(); j++)
                                                                                                                                      for(k = 0; k < Nj; k++)
                                                                                                                                      mRet.At(i,j) += At(i,k)*m.At(k,j);
                                                                                                                                    *this = mRet;
                                                                                                                                    return  *this;
                                                                                                                                    }



                                                                                                                                    что есть не так круто, как первое. не знаю, вообще, как эти матрицы вообще используются здесь, если они столько ресурсов жрут.

                                                                                                                                    а ето я вобще не понял. я в етих с++ных заморочках ничо не понимаю, наверное у тебя тормозит не изза матриц, а именно изза них
                                                                                                                                    1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                                                                                                    0 пользователей:


                                                                                                                                    Рейтинг@Mail.ru
                                                                                                                                    [ Script execution time: 0.1801 ]   [ 14 queries used ]   [ Generated: 24.10.26, 05:46 GMT ]