#cpp #3d #directx #mesh
Пишу программу, которая должна деформировать модель по опорным точкам. Получилось написать следующий код, который создает полотно процедурно по 16 опорным точкам. Вот как это выглядит: //вычисляем полином Бершнейна третьей степени на основании четырех точек XMFLOAT3 Bernstein(float u, XMFLOAT3 p1, XMFLOAT3 p2, XMFLOAT3 p3, XMFLOAT3 p4) { XMFLOAT3 a, b, c, d; a = pointTimes(pow(u, 3), p1); b = pointTimes(3 * pow(u, 2) * (1 - u), p2); c = pointTimes(3 * u * pow((1 - u), 2), p3); d = pointTimes(pow((1 - u), 3), p4); return pointAdd(pointAdd(a, b), pointAdd(c, d)); } //тоже самое что и верхняя функция, только принимаем указатель на массив точек XMFLOAT3 Bernstein(float u, XMFLOAT3 *p) { XMFLOAT3 a, b, c, d; a = pointTimes(pow(u, 3), p[0]); b = pointTimes(3 * pow(u, 2) * (1 - u), p[1]); c = pointTimes(3 * u * pow(1 - u, 2), p[2]); d = pointTimes(pow(1 - u, 3), p[3]); return pointAdd(pointAdd(a, b), pointAdd(c, d)); } void CreateSurfaceByControlPoints(XMFLOAT3 points[], D3DTextureVertex **ppVertices) { const int step = 16; //количество делений у полотна //чем больше делений, тем глаже модель становится (создается больше вершин) const int max = (step * (step + 1) * 2); //общее количество вершин у модели XMFLOAT3 temp[4]; XMFLOAT3 *last = new XMFLOAT3[step + 1]; //в массиве points, размером 16 точек, //у меня верхняя линия с индексами от 0 до 3, следющая от 4 до 7 и т.д. for(int i = 0; i < 4; i++) { temp[i] = points[(i + 1) * 4 - 1]; } for(int i = 0; i < step + 1; i++) { last[i] = Bernstein((float)i / (float)step, temp); } *ppVertices = new D3DTextureVertex[max]; int c = 0; //счетчик текущей вершины for(int i = 1; i < step + 1; i++) { float py = (float)i / (float)step; float pyold = ((float)i - 1.0f) / (float)step; for(int j = 0; j < 4; j++) { temp[j] = Bernstein(py, points[j * 4 + 0], points[j * 4 + 1], points[j * 4 + 2], points[j * 4 + 3]); } for(int j = 0; j <= step; j++) { float px = static_cast(j) / (float)step; (*ppVertices)[c++] = D3DTextureVertex(last[j].x, last[j].y, last[j].z, pyold, px); last[j] = Bernstein(px, temp); (*ppVertices)[c++] = D3DTextureVertex(last[j].x, last[j].y, last[j].z, py, px); } } delete[] last; } Все вышесказанное работает отлично, но теперь задача усложнилась и мне нужно загружать произвольную модель (она тоже 2D, как и моя процедурная), добавлять опорные точки таким же образом и деформировать меш по такому же подобию. Модель уже имеет свою геометрию и UV координаты. Выглядит следующим образом: Главный вопрос - есть ли какая-нибудь формула, чтобы рассчитать позицию для каждого вертекса, основываясь на 8 кривых Безье (4 горизонтальных и 4 вертикальных), учитывая их первоначальную позицию? Как, например, в профессиональных программах Maya или Blender есть такие инструменты, как произвольно расставить опорные точки и делать с моделью любые деформации.
Ответы
Ответ 1
Спасибо за помощь! Получилось решить проблему следующим образом: //1378 и 861 - значения у меня рассчитаны, чтобы вся модель умещалась на экране //у вас они могут быть другие или вообще по-другому считаться, главное, чтобы pz и px были в пределах [0.0f, 1.0f] //в переменной points хранятся опорные точки //в ppOutVertices хранится указатель на вершины, которые будем задавать //в ppBaseVertices хранится массив вершин по-умолчанию, на основе которых формируем новый массив //nVertices - количество вершин в моделе void UpdateSurface(XMFLOAT3 points[], D3DTextureVertex **ppOutVertices, D3DTextureVertex **ppBaseVertices, UINT nVertices) { XMFLOAT3 tmp[4]; *ppOutVertices = new D3DTextureVertex[nVertices]; for(int i = 0; i < nVertices; i++) { float pz = (float)(*ppBaseVertices)[i].Pos.x / (1378.0f / 100.0f); for(int j = 0; j < 4; j++) { tmp[j] = Bernstein(pz, points[j * 4 + 0], points[j * 4 + 1], points[j * 4 + 2], points[j * 4 + 3]); } float px = (float)(*ppBaseVertices)[i].Pos.z / (861.0f / 100.0f); XMFLOAT3 bern = XMFLOAT3(Bernstein(px, tmp)); (*ppOutVertices)[i].Pos = XMFLOAT3(bern.x, 0.0f, bern.z); } }
Комментариев нет:
Отправить комментарий