Основной алгоритм космической резьбы
У меня есть следующая проблема, как показано на рисунке. У меня есть облако точек и сетка, сгенерированная тетраэдрическим алгоритмом. Как бы я вырезал сетку, используя этот алгоритм? Являются ли ориентиры облаком точек?
Псевдокод алгоритма:
for every 3D feature point
convert it 2D projected coordinates
for every 2D feature point
cast a ray toward the polygons of the mesh
get intersection point
if zintersection < z of 3D feature point
for ( every triangle vertices )
cull that triangle.
Вот последующая реализация алгоритма, упомянутого Гуру Спектре:)
Обновить код для алгоритма:
int i;
for (i = 0; i < out.numberofpoints; i++)
{
Ogre::Vector3 ray_pos = pos; // camera position);
Ogre::Vector3 ray_dir = (Ogre::Vector3 (out.pointlist[(i*3)], out.pointlist[(3*i)+1], out.pointlist[(3*i)+2]) - pos).normalisedCopy(); // vertex - camea pos ;
Ogre::Ray ray;
ray.setOrigin(Ogre::Vector3( ray_pos.x, ray_pos.y, ray_pos.z));
ray.setDirection(Ogre::Vector3(ray_dir.x, ray_dir.y, ray_dir.z));
Ogre::Vector3 result;
unsigned int u1;
unsigned int u2;
unsigned int u3;
bool rayCastResult = RaycastFromPoint(ray.getOrigin(), ray.getDirection(), result, u1, u2, u3);
if ( rayCastResult )
{
Ogre::Vector3 targetVertex(out.pointlist[(i*3)], out.pointlist[(3*i)+1], out.pointlist[(3*i)+2]);
float distanceTargetFocus = targetVertex.squaredDistance(pos);
float distanceIntersectionFocus = result.squaredDistance(pos);
if(abs(distanceTargetFocus) >= abs(distanceIntersectionFocus))
{
if ( u1 != -1 && u2 != -1 && u3 != -1)
{
std::cout << "Remove index "<< "u1 ==> " <<u1 << "u2 ==>"<<u2<<"u3 ==> "<<u3<< std::endl;
updatedIndices.erase(updatedIndices.begin()+ u1);
updatedIndices.erase(updatedIndices.begin()+ u2);
updatedIndices.erase(updatedIndices.begin()+ u3);
}
}
}
}
if ( updatedIndices.size() <= out.numberoftrifaces)
{
std::cout << "current face list===> "<< out.numberoftrifaces << std::endl;
std::cout << "deleted face list===> "<< updatedIndices.size() << std::endl;
manual->begin("Pointcloud", Ogre::RenderOperation::OT_TRIANGLE_LIST);
for (int n = 0; n < out.numberofpoints; n++)
{
Ogre::Vector3 vertexTransformed = Ogre::Vector3( out.pointlist[3*n+0], out.pointlist[3*n+1], out.pointlist[3*n+2]) - mReferencePoint;
vertexTransformed *=1000.0 ;
vertexTransformed = mDeltaYaw * vertexTransformed;
manual->position(vertexTransformed);
}
for (int n = 0 ; n < updatedIndices.size(); n++)
{
int n0 = updatedIndices[n+0];
int n1 = updatedIndices[n+1];
int n2 = updatedIndices[n+2];
if ( n0 < 0 || n1 <0 || n2 <0 )
{
std::cout<<"negative indices"<<std::endl;
break;
}
manual->triangle(n0, n1, n2);
}
manual->end();
Следуйте алгоритму:
У меня сейчас две версии: одна - триангулированная, а другая - резная.
Это не поверхностная сетка. Вот два файла http://www.mediafire.com/file/cczw49ja257mnzr/ahmed_non_triangulated.obj http://www.mediafire.com/file/cczw49ja257mnzr/ahmed_triangulated.obj
1 ответ
Я вижу это так:
Таким образом, вы получили изображение с камеры с известной матрицей, FOV и фокусным расстоянием.
Из этого вы узнаете, где именно находится фокус, и где изображение проецируется на чип камеры (плоскость Z_near). Таким образом, любая вершина, соответствующий ей пиксель и фокус находятся на одной линии.
Таким образом, для каждого вида виден луч от фокальной точки до каждой видимой вершины точечного облака. и проверьте, попадет ли какая-либо грань меша перед тем, как ударить грань, содержащую целевую вершину. Если да, удалите его, так как это заблокирует видимость.
Ориентир в этом контексте - это просто характерная точка, соответствующая вершине из pointcloud. Это может быть что-либо обнаруживаемое (изменение интенсивности, цвета, рисунка и т. Д.), Обычно для этого используется SIFT/SURF. Вы должны располагать их уже, так как это вход для генерации pointcloud. Если нет, вы можете посмотреть пиксель, соответствующий каждой вершине, и проверить цвет фона.
Не уверен, как вы хотите сделать это без входных изображений. Для этого вам нужно решить, какая вершина видна с какой стороны / вида. Может быть, это выполнимо как-то сформировать близлежащие вершины (например, используя точки плотности вершин или отношение ядра к плоской грани...) или алгоритм каким-то образом изменяется для нахождения неиспользуемых вершин внутри сетки.
Чтобы сделать луч, сделайте это:
ray_pos=tm_eye*vec4(imgx/aspect,imgy,0.0,1.0);
ray_dir=ray_pos-tm_eye*vec4(0.0,0.0,-focal_length,1.0);
где tm_eye
матрица прямого преобразования камеры, imgx,imgy
является положением 2D пикселя в изображении, нормализованном к <-1,+1>
где (0,0)
это середина изображения. focal_length
определяет угол обзора камеры, а соотношение сторон - это соотношение разрешения изображения. image_ys/image_xs
Уравнение пересечения треугольника луча можно найти здесь:
Если я извлечу это:
vec3 v0,v1,v2; // input triangle vertexes
vec3 e1,e2,n,p,q,r;
float t,u,v,det,idet;
//compute ray triangle intersection
e1=v1-v0;
e2=v2-v0;
// Calculate planes normal vector
p=cross(ray[i0].dir,e2);
det=dot(e1,p);
// Ray is parallel to plane
if (abs(det)<1e-8) no intersection;
idet=1.0/det;
r=ray[i0].pos-v0;
u=dot(r,p)*idet;
if ((u<0.0)||(u>1.0)) no intersection;
q=cross(r,e1);
v=dot(ray[i0].dir,q)*idet;
if ((v<0.0)||(u+v>1.0)) no intersection;
t=dot(e2,q)*idet;
if ((t>_zero)&&((t<=tt)) // tt is distance to target vertex
{
// intersection
}
Последующие действия:
Для перемещения между нормализованным изображением (imgx,imgy)
и сырое изображение (rawx,rawy)
координаты для изображения размера (imgxs,imgys)
где (0,0)
это верхний левый угол и (imgxs-1,imgys-1)
в правом нижнем углу вам нужно:
imgx = (2.0*rawx / (imgxs-1)) - 1.0
imgy = 1.0 - (2.0*rawy / (imgys-1))
rawx = (imgx + 1.0)*(imgxs-1)/2.0
rawy = (1.0 - imgy)*(imgys-1)/2.0
[обновление прогресса 1]
Я наконец-то дошел до того, что могу скомпилировать пример входных тестовых данных для этого, чтобы начать работу (поскольку вы вообще не можете предоставить действительные данные):
Я создал небольшое приложение с жестко закодированной таблицей сетки (серый) и pointcloud (аква) и простым управлением камерой. Где я могу сохранить любое количество просмотров (скриншот + камера прямой матрицы). При загрузке он выравнивается с самой сеткой (желтый луч проходит через аква-точку на изображении и тоже проходит через сетку таблицы). Синие линии отведены от фокуса камеры к ее углам. Это будет эмулировать полученный вами вклад. Вторая часть приложения будет использовать только эти изображения и матрицы с облаком точек (больше нет поверхности сетки), тетрагонизируем его (уже закончено), теперь просто направляем луч через каждый ориентир в каждом виде (аква-точка) и удаляем все тетрагоналы перед целевой вершиной. в pointcloud есть удар (этот материал даже не запущен, но может быть и в выходные)... И, наконец, храните только поверхностные треугольники (просто используйте все треугольники, которые используются только один раз, и уже закончены, кроме части сохранения, но для записи объекта волнового фронта из это легко...).
[Обновление прогресса 2]
Я добавил обнаружение ориентира и сопоставление с облаком точек
как вы можете видеть, используются только действительные лучи (те, которые видны на изображении), поэтому некоторые точки на облаке точек не излучают лучи (единичные аквоточки)). Так что теперь только пересечение луча / треугольника и удаление тетраэдра из списка - вот чего не хватает...