9 changed files with 226 additions and 288 deletions
@ -0,0 +1,181 @@ |
|||||
|
#include "Intersection.h" |
||||
|
|
||||
|
using namespace std; |
||||
|
|
||||
|
TriangleSegmentIntersectRes::TriangleSegmentIntersectRes(bool h, float tt) : hit(h), t(tt) {} // VS2008
|
||||
|
|
||||
|
TriangleSegmentIntersectRes |
||||
|
triangleSegmentIntersection(const LineSegment &segment, const Vec3f &a, const Vec3f &b, const Vec3f &c) |
||||
|
{ |
||||
|
Vec3f e1 = b - a; |
||||
|
Vec3f e2 = c - a; |
||||
|
Vec3f s = segment.start - a; |
||||
|
Vec3f s1 = segment.getDir().cross(e2); |
||||
|
Vec3f s2 = s.cross(e1); |
||||
|
float s1_dot_e1 = s1.dot(e1); |
||||
|
float b1 = s1.dot(s) / s1_dot_e1; |
||||
|
float b2 = s2.dot(segment.getDir()) / s1_dot_e1; |
||||
|
if (b1 >= 0. && b2 >= 0. && b1 + b2 <= 1.) |
||||
|
{ |
||||
|
return TriangleSegmentIntersectRes(true, s2.dot(e2) / s1_dot_e1); |
||||
|
} |
||||
|
return TriangleSegmentIntersectRes(false, 0.f); |
||||
|
} |
||||
|
|
||||
|
BVHNode::BVHNode(size_t l, size_t r, size_t p, const AABB &aabb) : left(l), right(r), parent(p), boundingBox(aabb) {} |
||||
|
BVHNode::BVHNode() : left(0), right(0), parent(0), boundingBox() {} |
||||
|
|
||||
|
BVH_intersection::BVH_intersection(const Mesh &mesh_) : mesh(mesh_) |
||||
|
{ |
||||
|
faceCenters.reserve(mesh.indices.size()); |
||||
|
for (vector<Vec3u>::const_iterator it = mesh.indices.begin(); it != mesh.indices.end(); ++it) |
||||
|
{ |
||||
|
const Vec3u &face = *it; |
||||
|
Vec3f center = (mesh.vertices[face[0]] + mesh.vertices[face[1]] + mesh.vertices[face[2]]) / 3.0f; |
||||
|
faceCenters.push_back(center); |
||||
|
} |
||||
|
vector<size_t> indicesList(mesh.indices.size()); |
||||
|
for (size_t i = 0; i < indicesList.size(); ++i) |
||||
|
{ |
||||
|
indicesList[i] = i; |
||||
|
} |
||||
|
try |
||||
|
{ |
||||
|
nodes.resize(2 * mesh.indices.size() - 1); |
||||
|
} |
||||
|
catch (const length_error &e) |
||||
|
{ |
||||
|
cout << "vector.length:" << nodes.size() << " resize_pa:" << (2 * mesh.indices.size() - 1) << endl; |
||||
|
cerr << "Caught a length_error: " << e.what() << endl; |
||||
|
} |
||||
|
size_t nowIdx = 0; |
||||
|
dfsBuild(indicesList, computeAABB(indicesList), nowIdx); |
||||
|
} |
||||
|
|
||||
|
size_t BVH_intersection::dfsBuild(vector<size_t> &indicesList, AABB aabb, size_t &nowIdx) |
||||
|
{ |
||||
|
const size_t nodeIdx = nowIdx; |
||||
|
nowIdx++; |
||||
|
if (indicesList.size() == 1) |
||||
|
{ |
||||
|
nodes[nodeIdx] = BVHNode(0, indicesList[0], 0, aabb); // VS2008
|
||||
|
return nodeIdx; |
||||
|
} |
||||
|
int longAxis = -1; |
||||
|
float longAxisLen = -1; |
||||
|
for (int i = 0; i < 3; ++i) |
||||
|
{ |
||||
|
const float axisLen = aabb.max[i] - aabb.min[i]; |
||||
|
if (axisLen > longAxisLen) |
||||
|
{ |
||||
|
longAxisLen = axisLen; |
||||
|
longAxis = i; |
||||
|
} |
||||
|
} |
||||
|
const size_t k = indicesList.size() / 2; |
||||
|
nth(indicesList, k - 1, longAxis); |
||||
|
vector<size_t> leftIndices(indicesList.begin(), indicesList.begin() + k); |
||||
|
vector<size_t> rightIndices(indicesList.begin() + k, indicesList.end()); |
||||
|
const AABB leftAABB = computeAABB(leftIndices); |
||||
|
const AABB rightAABB = computeAABB(rightIndices); |
||||
|
const size_t leftIdx = dfsBuild(leftIndices, leftAABB, nowIdx); |
||||
|
const size_t rightIdx = dfsBuild(rightIndices, rightAABB, nowIdx); |
||||
|
nodes[nodeIdx] = BVHNode(leftIdx, rightIdx, 0, aabb); // VS2008
|
||||
|
nodes[leftIdx].parent = nodeIdx; |
||||
|
nodes[rightIdx].parent = nodeIdx; |
||||
|
return nodeIdx; |
||||
|
} |
||||
|
|
||||
|
bool BVH_intersection::intersectWithLineSegment(const LineSegment &lineSegment) const |
||||
|
{ |
||||
|
return recursiveLineSegIntersection(lineSegment, 0); |
||||
|
} |
||||
|
|
||||
|
AABB BVH_intersection::computeAABB(const vector<size_t> &indices) |
||||
|
{ |
||||
|
AABB aabb; |
||||
|
for (vector<size_t>::const_iterator it = indices.begin(); it != indices.end(); ++it) |
||||
|
{ |
||||
|
const Vec3u &face = mesh.indices[*it]; |
||||
|
for (int i = 0; i < 3; ++i) |
||||
|
{ |
||||
|
const Vec3f &vertex = mesh.vertices[face[i]]; |
||||
|
for (int j = 0; j < 3; ++j) |
||||
|
{ |
||||
|
aabb.min[j] = min(aabb.min[j], vertex[j]); |
||||
|
aabb.max[j] = max(aabb.max[j], vertex[j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return aabb; |
||||
|
} |
||||
|
|
||||
|
bool BVH_intersection::recursiveLineSegIntersection(const LineSegment &lineSegment, size_t nodeIdx) const |
||||
|
{ |
||||
|
const AABB &aabb = nodes[nodeIdx].boundingBox; |
||||
|
const Vec3f &dir = lineSegment.getDir(); |
||||
|
bool hit = false; |
||||
|
for (int i = 0; !hit && i < 3; ++i) |
||||
|
{ |
||||
|
float t_min = (aabb.min[i] - lineSegment.start[i]) / dir[i]; |
||||
|
float t_max = (aabb.max[i] - lineSegment.start[i]) / dir[i]; |
||||
|
if (t_min > t_max) |
||||
|
{ |
||||
|
swap(t_min, t_max); |
||||
|
} |
||||
|
if (t_min > lineSegment.getLength() || t_max < 0) |
||||
|
return false; |
||||
|
Vec3f hitPt = lineSegment.start + dir * t_min; |
||||
|
int otherPlane1 = (i + 1) % 3, otherPlane2 = (i + 2) % 3; |
||||
|
if (hitPt[otherPlane1] >= aabb.min[otherPlane1] && hitPt[otherPlane1] <= aabb.max[otherPlane1] && |
||||
|
hitPt[otherPlane2] >= aabb.min[otherPlane2] && hitPt[otherPlane2] <= aabb.max[otherPlane2]) |
||||
|
{ |
||||
|
hit = true; |
||||
|
} |
||||
|
} |
||||
|
if (hit) |
||||
|
{ |
||||
|
if (nodes[nodeIdx].left == 0) |
||||
|
{ |
||||
|
Vec3u face = mesh.indices[nodes[nodeIdx].right]; |
||||
|
TriangleSegmentIntersectRes res = triangleSegmentIntersection(lineSegment, mesh.vertices[face[0]], mesh.vertices[face[1]], |
||||
|
mesh.vertices[face[2]]); |
||||
|
if (!res.hit || res.t < 0 || res.t > lineSegment.getLength()) |
||||
|
return false; |
||||
|
return true; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return recursiveLineSegIntersection(lineSegment, nodes[nodeIdx].left) || |
||||
|
recursiveLineSegIntersection(lineSegment, nodes[nodeIdx].right); |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
void BVH_intersection::nth(vector<size_t> &indicesList, size_t kth, int longAxis) |
||||
|
{ |
||||
|
recursiveChoose(indicesList, 0, indicesList.size() - 1, kth, longAxis); |
||||
|
} |
||||
|
|
||||
|
void BVH_intersection::recursiveChoose(vector<size_t> &indicesList, size_t begin, size_t end, size_t kth, int longAxis) |
||||
|
{ |
||||
|
if (begin >= end) |
||||
|
return; |
||||
|
int i = begin, j = end; |
||||
|
while (i < j) |
||||
|
{ |
||||
|
while (i < j && faceCenters[indicesList[j]][longAxis] >= faceCenters[indicesList[begin]][longAxis]) |
||||
|
j--; |
||||
|
while (i < j && faceCenters[indicesList[i]][longAxis] <= faceCenters[indicesList[begin]][longAxis]) |
||||
|
i++; |
||||
|
swap(indicesList[i], indicesList[j]); |
||||
|
} |
||||
|
swap(indicesList[begin], indicesList[i]); |
||||
|
if (i == kth) |
||||
|
return; |
||||
|
if (i < kth) |
||||
|
recursiveChoose(indicesList, i + 1, end, kth, longAxis); |
||||
|
else |
||||
|
recursiveChoose(indicesList, begin, i - 1, kth, longAxis); |
||||
|
} |
@ -1,8 +0,0 @@ |
|||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
|
||||
// xmlsql.pch 将作为预编译头
|
|
||||
// stdafx.obj 将包含预编译类型信息
|
|
||||
|
|
||||
#include "stdafx.h" |
|
||||
|
|
||||
// TODO: 在 STDAFX.H 中
|
|
||||
// 引用任何所需的附加头文件,而不是在此文件中引用
|
|
@ -1,26 +0,0 @@ |
|||||
// stdafx.h : ��ϵͳ�����ļ��İ����ļ���
|
|
||||
// ���Ǿ���ʹ�õ��������ĵ�
|
|
||||
// �ض�����Ŀ�İ����ļ�
|
|
||||
//
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
// #pragma comment(lib, "tinyxml.lib")
|
|
||||
|
|
||||
#define Word Microsoft::Office::Interop::Word |
|
||||
|
|
||||
#include "targetver.h" |
|
||||
|
|
||||
#include <stdio.h> |
|
||||
#ifdef _WIN32 |
|
||||
#include <tchar.h> |
|
||||
#include <windows.h> |
|
||||
#include <atlstr.h> |
|
||||
#endif |
|
||||
#include <ctype.h> |
|
||||
#include <iostream> |
|
||||
#include <tinyxml2.h> |
|
||||
|
|
||||
// #include <tinystr.h>
|
|
||||
|
|
||||
// TODO: �ڴ˴����ó�����Ҫ������ͷ�ļ�
|
|
Loading…
Reference in new issue