Уроки, алгоритмы, программы, примеры

Вход на сайт

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

Спасибо за реализацию, она действительно быстрая. Но не все линии отрисовывает в нужную сторону... Необходимо добавить проверку для случая X-линии if(y1 "<" y0) grad=-grad; и аналогично для Y-линии if(x1 "<" x0) grad=-grad; P.S. На...
Отличные уроки(учу GL по ним), только в renderScene нужно добавить очистку буфера цвета и буфера глубины. При изменении размеров треугольники размножаются)
как исправить это , сделал все по инструкции
Timer1 - выдает ошибку. Использовал IdleTimer1, работает! unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, OpenGLContext, GL, GLU; type { TForm1 } TForm1 =...
в коде присутствуют ошибки! // Считываем координаты procedure TForm1.getCoords(Sender: TObject); var j1:longint; begin n:= StrToInt(Edit2.Text); //число точек s1:=Edit1.Text; s2:=''; i := 1; j:=1; k:=0...

Счетчики и рейтинг

Яндекс.Метрика Рейтинг@Mail.ru

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

Алгоритм:
Входные данные:
1) угол θ на который производится вращение.
2) координаты x, y, z вращаемой точки.
3) координаты i, j, k направляющего единичного вектора, вокруг которого происходит вращение.
На выходе алгоритм выдает кватернион, содержащий координаты точки, обращенной вокруг заданного вектора ПО часовой стрелке его направления.

Процедура:
1) присвоить q <- (cos(θ/2), i*sin(θ/2), j*sin(θ/2), k*sin(θ/2)), где i,j,k - координаты единичного вектора, вокруг которого вращаем координату.
2) присвоить p <- (0, x, y, z), где x,y,z - координаты вращаемой точки.
3) присвоить p <- q*p
4) присвоить p <- p*q^-1
Кватернион p теперь имеет координаты (0, x', y', z'), где x',y',z' - новые координаты.

Хочу напомнить что умножение кватернионов не коммутативно, т.е. a*b != b*a

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

package net.ilyi;
 
public class Quaternion {
    public double r, i, j, k;
 
    public Quaternion(double r, double i, double j, double k) {
        this.r = r;
        this.i = i;
        this.j = j;
        this.k = k;
    }
 
    public double mag() {
        return Math.sqrt(r*r + i*i + j*j + k*k);
    }
 
    public Quaternion inverse() {
        double mag = this.mag();
        return new Quaternion(r/mag, -i/mag, -j/mag, -k/mag);
    }
 
    public Quaternion unit() {
        double mag = this.mag();
        return new Quaternion(r, i/mag, j/mag, k/mag);
    }
 
    public Quaternion mul(Quaternion q) {
        double r = this.r*q.r - this.i*q.i - this.j*q.j - this.k*q.k;
        double i = this.r*q.i + this.i*q.r + this.j*q.k - this.k*q.j;
        double j = this.r*q.j - this.i*q.k + this.j*q.r + this.k*q.i;
        double k = this.r*q.k + this.i*q.j - this.j*q.i + this.k*q.r;
        return new Quaternion(r, i, j, k);
    }
}

А вот код, который реализует картинку статьи, без использования матричных вращений:

double phi = Math.PI/180.0*angle;
double i = 0.0;
double j = 1.0;
double k = 0.0;
double cosphi = Math.cos(phi/2.0);
double sinphi = Math.sin(phi/2.0);
Quaternion q = new Quaternion(cosphi, i*sinphi, j*sinphi, k*sinphi).unit();
Quaternion p;
 
// triangle
glTranslatef(0.0f, 0.0f, -2.0f);
glBegin(GL_TRIANGLES);
 
glColor3f(1.0f, 0.0f, 0.0f);
p = new Quaternion(0.0, -0.5, -0.5, 0.0);
p = q.mul(p.mul(q.inverse()));
glVertex3f((float)p.i, (float)p.j, (float)p.k);
 
glColor3f(0.0f, 1.0f, 0.0f);
p = new Quaternion(0.0, 0.5, -0.5, 0.0);
p = q.mul(p.mul(q.inverse()));
glVertex3f((float)p.i, (float)p.j, (float)p.k);
 
glColor3f(0.0f, 0.0f, 1.0f);
p = new Quaternion(0.0, 0.5, 0.5, 0.0);
p = q.mul(p.mul(q.inverse()));
glVertex3f((float)p.i, (float)p.j, (float)p.k);
 
glEnd();
 
angle += 0.1f * delta;