sunLoadingImage
whowedImag
decoration left 1
decoration left 2
transhome
transprojects
transgallery
transarticles
decoration rigth
English
Українська
Show/Hide search bar
black cat logo variable logo
[23 Січ 2013]

Герерація сітки вздовж сплайнів Без'є

Далі описано базовий принцип генерації сітки вздовж сплайнів Без'є.
Перш за все потрібно згенерувати контрольні точки кривої Без'є. Сплайн Без'є - зєднані криві Без'є. Для утворення сплайну, криві Без'є повинні з'єднюватися так, щоб дотична на кінці попередньої кривої була рівна дотичній на початку наступної кривої. Тобто передостання точка попередньої кривої, спільна точка двох кривих та друга точка наступної кривої повинні лежати на одній прямій:
Bezier Spline
Вхідні дані:
  • numParts - кількість підкривих у сплайні
  • splineControlPoints -контрольні точки сплайну
  • level - кількість контрольних точок на криву
  • numSegmentsAlongCurve - кількість сегментів вздовж кривої
  • numVerticesAroundCurve - кількість сегментів навколо кривої
Segments along curve Segments around curve Additional subdivision
Найпростішим способом генерації сітки вздовж кривої є її розділення на дискретні значення відповідно numSegmentsAlongCurve, побудова для цих точок кільця вершин, а потім зєднання вершин у трикутники. Якщо кривизна кривої невелика, і немає перекручень, то сітка може бути згенерована правильно. Але у більшості випадків в певній частині сітки буде утворюватися перекручення. Потрібно будувати вершини з врахуванням кривизни кривої.
Спочатку потрібно розрахувати для кожної дискретної точки значення дотичної та нормалі:
Triads of tangent, normal and binormals
Генерація починається з початку першої підкривої. Від нормалі в першій точці залежить уся наступна генерація сітки. Поточне t (параметничне значення для визначення точки на кривій Безє) приймемо як 0. Першу дотичну можна розрахувати як вектор з точки кривої t1=t до точки t2=t+△, де △ рівне малому зсуву вздовж кривої, наприклад, △=0.1/numSegmentsAlongCurve. vec3 t1 = bezierPos(splineControlPoints,part,t1);
vec3 t2 = bezierPos(splineControlPoints,part,t2);
vec3 tangent = (t2-t1).normalize();
Для початкової точки і розрахованої дотичної існує безкінечна кількість нормалей. Виберемо будь-яку. Нормаль в цій точці можна розрахувати як векторний добуток дотичної і наприклад вектора up(0,1,0); vec3 normal= crossProduct(tangent,up);
Збережемо позицію точки (t1), розраховану дотичну і нормаль. Визначаємо змінні prevNormal = normal, prevTangent = tangent.
Переходимо до наступної дискретної точки на кривій, тобто: t+=1.0/numSegmentsAlongCurve;
Дотична і нормаль для наступної точки мають бути розраховані з врахуванням повороту кривої і попередньої розрахованої нормалі. Дотична розраховується аналогічно, як вектор з точки поточного t до точки t+△.
Для розрахунку нормалі потрібно визначити на скільки повернула крива на відрізку від попередньої точки до поточної. Розраховуємо перпендикуляр до поточної дотичної і до попередньої, як векторний добуток цих двох векторів. Цей перпендикуляр є вектором навколо якого зігнулася крива від попередньої ітерації: vec3 perp = crossProduct(prevTangent,tangent);
Розраховуємо кут між поточною дотичною і попередньою з врахуванням напряму: float cosBetweenTangents=dotProduct(tangent,prevTangent);
float angle = atan2(perpLen, angleBetweenTans);
Розраховуємо матрицю повороту навколо вектора pert на кут angle. Поточну нормаль розраховуємо як трансформовану матрицею повороту попередню нормаль. mat4 rotMatrix = rotateAroundAxis(perp,angle);
normal = rotMatrix * prevNormal;
Зберігаємо позицію, дотичну і нормаль. Перевизначаємо змінні prevNormal = normal, prevTangent = tangent.
Переходимо до наступної дискретної точки на кривій і повторюємо процес розрахунку дотичних і нормалей з врахуванням попередньої нормалі і дотичної. При закінчені кривої, коли t>1, відбувається перехід на наступну криву, або відбувається перехід до генерації вершин.
Навколо кожної дискретної точки потрібно згенерувати кільце з вершин. Наприклад, перша вершина кільця буде рівна position + normal * radius. Для розрахунку наступної вершини потрібно повернути нормаль навколо дотичної. Кут повороту залежить від кількості сегментів навколо кривої.
Vertex rings around each point
Принцип наведено в наступному коді: for(short j=0;j<numDiscretePoints;j++){
    for(short i=0;i<numVerticesAroundCurve;i++){
        float rotAngle = 360.0 / numVerticesAroundCurve * i;
        mat4 M = rotateAroundAxis(tangents[j],rotAngle);
        vec3 dir = M * normals[j];
        generatedPositions.add(positions[j] + dir * radius);
        generatedNormals.add(dir);
    }
}
Зі згенерованих вершин потрібно сформувати трикутники:
Form triangles from generated vertices
Щоб cформована сітка була більш гладка на місцях згинів, потрібно проаналізувати angle при формуванні нормалей, і якщо він завеликий, то розрахувати додаткові нормаль і дотичну між сегментами, наприклад, в точці t=t-1.0/numSegmentsAlongCurve/2. Залежно від кута можна додавати більшу кількість підрозбиттів.
Приклади використання:

Tube for game
As fibers



Sun and Black Cat- Ігор Дихта (igor dykhta email) © 2007-2014