Implement convex hull algorithm.
parent
ecdc896e08
commit
106cea6b3f
|
@ -36,7 +36,7 @@ Two caps and many strips composites a cylinder.
|
||||||
Almost all 3D editor have a infinite grid ground, I just made a finite one, in the future, I should expand the grid outside of the screen to make it infinite.
|
Almost all 3D editor have a infinite grid ground, I just made a finite one, in the future, I should expand the grid outside of the screen to make it infinite.
|
||||||
Now, for just beginning, I think it's a not bad start.
|
Now, for just beginning, I think it's a not bad start.
|
||||||
<img src="screenshot/dust3d_sphere_cylinder.png">
|
<img src="screenshot/dust3d_sphere_cylinder.png">
|
||||||
- [ ] Implement B-Mesh algorithm (Dec 18, 2016 ~ Dec 25, 2016)
|
- [ ] Implement B-Mesh algorithm (Dec 18, 2016 ~ Dec 26, 2016)
|
||||||
*Drawing Skeletal Shape Balls*
|
*Drawing Skeletal Shape Balls*
|
||||||
Draw shape ball is easy, no need to rotate, I just need scale it along the ball's radius.
|
Draw shape ball is easy, no need to rotate, I just need scale it along the ball's radius.
|
||||||
Draw the cylinder which connects two shape balls is more difficult, I need do some math to rotate it. [Here](http://www.thjsmith.com/40/cylinder-between-two-points-opengl-c) described it.
|
Draw the cylinder which connects two shape balls is more difficult, I need do some math to rotate it. [Here](http://www.thjsmith.com/40/cylinder-between-two-points-opengl-c) described it.
|
||||||
|
@ -54,8 +54,8 @@ I created the test nodes's geometry information from Blender. Here is the render
|
||||||
<img src="screenshot/dust3d_generate_quad.png" width="124" height="128">
|
<img src="screenshot/dust3d_generate_quad.png" width="124" height="128">
|
||||||
When I am implementing the B-Mesh algorithm, I am also think in the future, how to create a library of bunch of initial base models. There is a paper [the Skeleton of a Closed 3D Shape](http://www1.idc.ac.il/icgf/GraphicsSeminar2006/DCGskeleton06.pdf) described how to generate skeleton from mesh, this is the reverse progress of what I am doing, I think it can resolve the problem of insufficient initial base models, I can generate from tons of existed models.
|
When I am implementing the B-Mesh algorithm, I am also think in the future, how to create a library of bunch of initial base models. There is a paper [the Skeleton of a Closed 3D Shape](http://www1.idc.ac.il/icgf/GraphicsSeminar2006/DCGskeleton06.pdf) described how to generate skeleton from mesh, this is the reverse progress of what I am doing, I think it can resolve the problem of insufficient initial base models, I can generate from tons of existed models.
|
||||||
*Convex Hull*
|
*Convex Hull*
|
||||||
After finish the rotation at the two connected bones, I need implement [3D Convex Hull](https://en.wikipedia.org/wiki/Convex_hull) algorithm at joint ball.
|
After finish the rotation at the two connected bones, I need implement 3D Convex Hull algorithm at the joint ball, there are so many methods to get the convex hull, I found the [Gift wrapping](http://dccg.upc.edu/people/vera/wp-content/uploads/2014/11/GA2014-ConvexHulls3D-Roger-Hernando.pdf) is the most strait-forward one, though is not the most efficient one.
|
||||||
|
<img src="screenshot/dust3d_convex_hull.png" width="124" height="128">
|
||||||
- [ ] Export Wavefront .obj
|
- [ ] Export Wavefront .obj
|
||||||
- [ ] Render B-Mesh result
|
- [ ] Render B-Mesh result
|
||||||
- [ ] Design UI for monster parts configuration
|
- [ ] Design UI for monster parts configuration
|
||||||
|
|
|
@ -14,7 +14,8 @@ SOURCES += main.cpp \
|
||||||
draw.cpp \
|
draw.cpp \
|
||||||
array.c \
|
array.c \
|
||||||
bmesh.c \
|
bmesh.c \
|
||||||
matrix.c
|
matrix.c \
|
||||||
|
convexhull.c
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
render.h \
|
render.h \
|
||||||
|
@ -22,4 +23,5 @@ HEADERS += mainwindow.h \
|
||||||
draw.h \
|
draw.h \
|
||||||
array.h \
|
array.h \
|
||||||
bmesh.h \
|
bmesh.h \
|
||||||
matrix.h
|
matrix.h \
|
||||||
|
convexhull.h
|
Binary file not shown.
After Width: | Height: | Size: 324 KiB |
47
src/bmesh.c
47
src/bmesh.c
|
@ -6,6 +6,7 @@
|
||||||
#include "bmesh.h"
|
#include "bmesh.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "matrix.h"
|
#include "matrix.h"
|
||||||
|
#include "convexhull.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
|
||||||
#define BMESH_STEP_DISTANCE 0.4
|
#define BMESH_STEP_DISTANCE 0.4
|
||||||
|
@ -245,6 +246,7 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
|
||||||
generateYZfromBoneDirection(&boneDirection,
|
generateYZfromBoneDirection(&boneDirection,
|
||||||
&localYaxis, &localZaxis);
|
&localYaxis, &localZaxis);
|
||||||
|
|
||||||
|
/*
|
||||||
glColor3f(0.0, 0.0, 0.0);
|
glColor3f(0.0, 0.0, 0.0);
|
||||||
drawDebugPrintf("<%f,%f,%f> <%f,%f,%f> <%f,%f,%f>",
|
drawDebugPrintf("<%f,%f,%f> <%f,%f,%f> <%f,%f,%f>",
|
||||||
localYaxis.x,
|
localYaxis.x,
|
||||||
|
@ -256,7 +258,8 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
|
||||||
boneDirection.x,
|
boneDirection.x,
|
||||||
boneDirection.y,
|
boneDirection.y,
|
||||||
boneDirection.z);
|
boneDirection.z);
|
||||||
|
*/
|
||||||
|
|
||||||
distance = vec3Length(&boneDirection);
|
distance = vec3Length(&boneDirection);
|
||||||
if (distance > BMESH_STEP_DISTANCE) {
|
if (distance > BMESH_STEP_DISTANCE) {
|
||||||
float offset;
|
float offset;
|
||||||
|
@ -485,7 +488,7 @@ static bmeshBall *bmeshFindBallForConvexHull(bmesh *bm, bmeshBall *root,
|
||||||
bmeshBallIterator iterator;
|
bmeshBallIterator iterator;
|
||||||
bmeshBall *child;
|
bmeshBall *child;
|
||||||
float distance = vec3Distance(&root->position, &ball->position);
|
float distance = vec3Distance(&root->position, &ball->position);
|
||||||
if (distance >= root->radius) {
|
if (distance > root->radius) {
|
||||||
return ball;
|
return ball;
|
||||||
}
|
}
|
||||||
child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||||
|
@ -502,11 +505,51 @@ static int bmeshStichFrom(bmesh *bm, bmeshBall *ball) {
|
||||||
bmeshBall *child;
|
bmeshBall *child;
|
||||||
bmeshBall *ballForConvexHull;
|
bmeshBall *ballForConvexHull;
|
||||||
if (BMESH_BALL_TYPE_ROOT == ball->type) {
|
if (BMESH_BALL_TYPE_ROOT == ball->type) {
|
||||||
|
convexHull *hull = convexHullCreate();
|
||||||
|
if (!hull) {
|
||||||
|
fprintf(stderr, "%s:convexHullCreate failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||||
child;
|
child;
|
||||||
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
||||||
|
vec3 z, y;
|
||||||
|
quad q;
|
||||||
|
int vertexIndices[4];
|
||||||
|
|
||||||
ballForConvexHull = bmeshFindBallForConvexHull(bm, ball, child);
|
ballForConvexHull = bmeshFindBallForConvexHull(bm, ball, child);
|
||||||
|
|
||||||
|
vec3Scale(&ballForConvexHull->localYaxis, ballForConvexHull->radius, &y);
|
||||||
|
vec3Scale(&ballForConvexHull->localZaxis, ballForConvexHull->radius, &z);
|
||||||
|
vec3Sub(&ballForConvexHull->position, &y, &q.pt[0]);
|
||||||
|
vec3Add(&q.pt[0], &z, &q.pt[0]);
|
||||||
|
vec3Sub(&ballForConvexHull->position, &y, &q.pt[1]);
|
||||||
|
vec3Sub(&q.pt[1], &z, &q.pt[1]);
|
||||||
|
vec3Add(&ballForConvexHull->position, &y, &q.pt[2]);
|
||||||
|
vec3Sub(&q.pt[2], &z, &q.pt[2]);
|
||||||
|
vec3Add(&ballForConvexHull->position, &y, &q.pt[3]);
|
||||||
|
vec3Add(&q.pt[3], &z, &q.pt[3]);
|
||||||
|
|
||||||
|
vertexIndices[0] = convexHullAddVertex(hull, &q.pt[0]);
|
||||||
|
vertexIndices[1] = convexHullAddVertex(hull, &q.pt[1]);
|
||||||
|
vertexIndices[2] = convexHullAddVertex(hull, &q.pt[2]);
|
||||||
|
vertexIndices[3] = convexHullAddVertex(hull, &q.pt[3]);
|
||||||
}
|
}
|
||||||
|
convexHullGenerate(hull);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
{
|
||||||
|
int triIndex;
|
||||||
|
glColor3f(1.0, 1.0, 1.0);
|
||||||
|
for (triIndex = 0; triIndex < convexHullGetTriangleNum(hull);
|
||||||
|
++triIndex) {
|
||||||
|
triangle *tri = (triangle *)convexHullGetTriangle(hull, triIndex);
|
||||||
|
drawTriangle(tri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
convexHullDestroy(hull);
|
||||||
}
|
}
|
||||||
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||||
child;
|
child;
|
||||||
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "convexhull.h"
|
||||||
|
#include "array.h"
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Implement Gift wrapping method which describled in http://dccg.upc.edu/people/vera/wp-content/uploads/2014/11/GA2014-ConvexHulls3D-Roger-Hernando.pdf
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Translate from Danielhst's lua version https://github.com/danielhst/3d-Hull-gift-wrap/blob/master/giftWrap.lua
|
||||||
|
//
|
||||||
|
|
||||||
|
struct convexHull {
|
||||||
|
array *vertexArray;
|
||||||
|
array *openEdgeArray;
|
||||||
|
array *triangleArray;
|
||||||
|
int nextEdgeIndex;
|
||||||
|
unsigned int *openEdgeExistMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int firstVertex;
|
||||||
|
int secondVertex;
|
||||||
|
} edge;
|
||||||
|
|
||||||
|
convexHull *convexHullCreate(void) {
|
||||||
|
convexHull *hull = (convexHull *)calloc(1, sizeof(convexHull));
|
||||||
|
if (!hull) {
|
||||||
|
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
hull->vertexArray = arrayCreate(sizeof(vec3));
|
||||||
|
if (!hull->vertexArray) {
|
||||||
|
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
hull->openEdgeArray = arrayCreate(sizeof(edge));
|
||||||
|
if (!hull->openEdgeArray) {
|
||||||
|
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
hull->triangleArray = arrayCreate(sizeof(triangle));
|
||||||
|
if (!hull->triangleArray) {
|
||||||
|
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return hull;
|
||||||
|
}
|
||||||
|
|
||||||
|
void convexHullMarkEdgeAsExsits(convexHull *hull, int firstVertex,
|
||||||
|
int secondVertex) {
|
||||||
|
int mapIndex = firstVertex * arrayGetLength(hull->vertexArray) + secondVertex;
|
||||||
|
int unitIndex = mapIndex / (sizeof(unsigned int) * 8);
|
||||||
|
int unitOffset = mapIndex % (sizeof(unsigned int) * 8);
|
||||||
|
hull->openEdgeExistMap[unitIndex] |= (0x00000001 << unitOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullEdgeExsits(convexHull *hull, int firstVertex,
|
||||||
|
int secondVertex) {
|
||||||
|
int mapIndex = firstVertex * arrayGetLength(hull->vertexArray) + secondVertex;
|
||||||
|
int unitIndex = mapIndex / (sizeof(unsigned int) * 8);
|
||||||
|
int unitOffset = mapIndex % (sizeof(unsigned int) * 8);
|
||||||
|
return hull->openEdgeExistMap[unitIndex] & (0x00000001 << unitOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullAddVertex(convexHull *hull, vec3 *vertex) {
|
||||||
|
int newVertex = arrayGetLength(hull->vertexArray);
|
||||||
|
if (0 != arraySetLength(hull->vertexArray, newVertex + 1)) {
|
||||||
|
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*((vec3 *)arrayGetItem(hull->vertexArray, newVertex)) = *vertex;
|
||||||
|
return newVertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullAddOpenEdgeNoCheck(convexHull *hull, int firstVertex,
|
||||||
|
int secondVertex) {
|
||||||
|
edge *e;
|
||||||
|
int newEdge = arrayGetLength(hull->openEdgeArray);
|
||||||
|
if (firstVertex < 0 || secondVertex < 0) {
|
||||||
|
fprintf(stderr, "%s:Invalid params(firstVertex:%d secondVertex:%d).\n",
|
||||||
|
__FUNCTION__, firstVertex, secondVertex);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (0 != arraySetLength(hull->openEdgeArray, newEdge + 1)) {
|
||||||
|
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
e = (edge *)arrayGetItem(hull->openEdgeArray, newEdge);
|
||||||
|
memset(e, 0, sizeof(edge));
|
||||||
|
e->firstVertex = firstVertex;
|
||||||
|
e->secondVertex = secondVertex;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullAddEdge(convexHull *hull, int p1, int p2) {
|
||||||
|
convexHullMarkEdgeAsExsits(hull, p1, p2);
|
||||||
|
if (!convexHullEdgeExsits(hull, p2, p1)) {
|
||||||
|
return convexHullAddOpenEdgeNoCheck(hull, p2, p1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullAddTriangle(convexHull *hull, int firstVertex, int secondVertex,
|
||||||
|
int thirdVertex) {
|
||||||
|
triangle *tri;
|
||||||
|
int newTri = arrayGetLength(hull->triangleArray);
|
||||||
|
if (0 != arraySetLength(hull->triangleArray, newTri + 1)) {
|
||||||
|
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tri = (triangle *)arrayGetItem(hull->triangleArray, newTri);
|
||||||
|
memset(tri, 0, sizeof(triangle));
|
||||||
|
tri->pt[0] = *((vec3 *)arrayGetItem(hull->vertexArray, firstVertex));
|
||||||
|
tri->pt[1] = *((vec3 *)arrayGetItem(hull->vertexArray, secondVertex));
|
||||||
|
tri->pt[2] = *((vec3 *)arrayGetItem(hull->vertexArray, thirdVertex));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convexHullReleaseForGenerate(convexHull *hull) {
|
||||||
|
free(hull->openEdgeExistMap);
|
||||||
|
hull->openEdgeExistMap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void convexHullDestroy(convexHull *hull) {
|
||||||
|
arrayDestroy(hull->vertexArray);
|
||||||
|
arrayDestroy(hull->openEdgeArray);
|
||||||
|
arrayDestroy(hull->triangleArray);
|
||||||
|
convexHullReleaseForGenerate(hull);
|
||||||
|
free(hull);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int convexHullPrepareForGenerate(convexHull *hull) {
|
||||||
|
free(hull->openEdgeExistMap);
|
||||||
|
hull->openEdgeExistMap = (unsigned int *)calloc(
|
||||||
|
arrayGetLength(hull->vertexArray) * arrayGetLength(hull->vertexArray) /
|
||||||
|
(sizeof(unsigned int) * 8) + 1,
|
||||||
|
sizeof(unsigned int));
|
||||||
|
if (!hull->openEdgeExistMap) {
|
||||||
|
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
hull->nextEdgeIndex = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullGetLower(convexHull *hull) {
|
||||||
|
int index = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 1; i < arrayGetLength(hull->vertexArray); ++i) {
|
||||||
|
vec3 *pI = (vec3 *)arrayGetItem(hull->vertexArray, i);
|
||||||
|
vec3 *pIndex = (vec3 *)arrayGetItem(hull->vertexArray, index);
|
||||||
|
if (pI->z < pIndex->z) {
|
||||||
|
index = i;
|
||||||
|
} else if (pI->z == pIndex->z) {
|
||||||
|
if (pI->y < pIndex->y) {
|
||||||
|
index = i;
|
||||||
|
} else if (pI->x < pIndex->x) {
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index) {
|
||||||
|
vec3 pCorner = {1, 1, 0};
|
||||||
|
vec3 *p1 = (vec3 *)arrayGetItem(hull->vertexArray, p1Index);
|
||||||
|
vec3 *p2 = p2Index < 0 ? &pCorner : (vec3 *)arrayGetItem(hull->vertexArray,
|
||||||
|
p2Index);
|
||||||
|
vec3 edge;
|
||||||
|
int candidateIndex = -1;
|
||||||
|
int i;
|
||||||
|
vec3Sub(p2, p1, &edge);
|
||||||
|
vec3Normalize(&edge);
|
||||||
|
for (i = 0; i < arrayGetLength(hull->vertexArray); ++i) {
|
||||||
|
if (i != p1Index && i != p2Index) {
|
||||||
|
if (-1 == candidateIndex) {
|
||||||
|
candidateIndex = 0;
|
||||||
|
} else {
|
||||||
|
vec3 v, proj, candidate, canProj, cross;
|
||||||
|
vec3Sub((vec3 *)arrayGetItem(hull->vertexArray, i), p1, &v);
|
||||||
|
vec3ProjectOver(&v, &edge, &proj);
|
||||||
|
vec3Sub(&v, &proj, &v);
|
||||||
|
vec3Sub((vec3 *)arrayGetItem(hull->vertexArray,
|
||||||
|
candidateIndex), p1, &candidate);
|
||||||
|
vec3ProjectOver(&candidate, &edge, &canProj);
|
||||||
|
vec3Sub(&candidate, &canProj, &candidate);
|
||||||
|
vec3CrossProduct(&candidate, &v, &cross);
|
||||||
|
if (vec3DotProduct(&cross, &edge) > 0) {
|
||||||
|
candidateIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return candidateIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullGenerate(convexHull *hull) {
|
||||||
|
int index1, index2, index3;
|
||||||
|
convexHullReleaseForGenerate(hull);
|
||||||
|
if (0 != convexHullPrepareForGenerate(hull)) {
|
||||||
|
fprintf(stderr, "%s:convexHullPrepareForGenerate failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
index1 = convexHullGetLower(hull);
|
||||||
|
index2 = convexHullGetNextVertex(hull, index1, -1);
|
||||||
|
convexHullAddEdge(hull, index2, index1);
|
||||||
|
//glColor3f(0.0, 0.0, 0.0);
|
||||||
|
//drawDebugPrintf("edgeLength:%d", arrayGetLength(hull->openEdgeArray));
|
||||||
|
while (hull->nextEdgeIndex < arrayGetLength(hull->openEdgeArray)) {
|
||||||
|
edge *e = (edge *)arrayGetItem(hull->openEdgeArray, hull->nextEdgeIndex++);
|
||||||
|
index1 = e->firstVertex;
|
||||||
|
index2 = e->secondVertex;
|
||||||
|
if (convexHullEdgeExsits(hull, index1, index2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
convexHullMarkEdgeAsExsits(hull, index1, index2);
|
||||||
|
index3 = convexHullGetNextVertex(hull, index1, index2);
|
||||||
|
//drawDebugPrintf("%d,%d,%d", index1, index2, index3);
|
||||||
|
convexHullAddTriangle(hull, index1, index2, index3);
|
||||||
|
convexHullAddEdge(hull, index1, index2);
|
||||||
|
convexHullAddEdge(hull, index2, index3);
|
||||||
|
convexHullAddEdge(hull, index3, index1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convexHullGetTriangleNum(convexHull *hull) {
|
||||||
|
return arrayGetLength(hull->triangleArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
triangle *convexHullGetTriangle(convexHull *hull, int index) {
|
||||||
|
triangle *tri = (triangle *)arrayGetItem(hull->triangleArray, index);
|
||||||
|
return tri;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef CONVEX_HULL_H
|
||||||
|
#define CONVEX_HULL_H
|
||||||
|
#include "vector3d.h"
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
|
typedef struct convexHull convexHull;
|
||||||
|
convexHull *convexHullCreate(void);
|
||||||
|
int convexHullAddVertex(convexHull *hull, vec3 *vertex);
|
||||||
|
void convexHullDestroy(convexHull *hull);
|
||||||
|
int convexHullGenerate(convexHull *hull);
|
||||||
|
int convexHullGetTriangleNum(convexHull *hull);
|
||||||
|
triangle *convexHullGetTriangle(convexHull *hull, int index);
|
||||||
|
|
||||||
|
#endif
|
|
@ -105,23 +105,27 @@ float vec3Angle(vec3 *a, vec3 *b) {
|
||||||
float angle;
|
float angle;
|
||||||
vec3 p;
|
vec3 p;
|
||||||
float distance;
|
float distance;
|
||||||
float dot;
|
|
||||||
float acosParam;
|
float acosParam;
|
||||||
float acosVal;
|
|
||||||
vec3Sub(a, b, &p);
|
vec3Sub(a, b, &p);
|
||||||
distance = vec3Length(&p);
|
distance = vec3Length(&p);
|
||||||
if (0 == distance) {
|
if (0 == distance) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dot = vec3DotProduct(a, b);
|
acosParam = vec3DotProduct(a, b) / distance;
|
||||||
acosParam = dot / distance;
|
|
||||||
if (acosParam < -1) {
|
if (acosParam < -1) {
|
||||||
acosParam = -1;
|
acosParam = -1;
|
||||||
}
|
}
|
||||||
if (acosParam > 1) {
|
if (acosParam > 1) {
|
||||||
acosParam = 1;
|
acosParam = 1;
|
||||||
}
|
}
|
||||||
acosVal = acos(acosParam);
|
angle = 180 / M_PI * acos(acosParam);
|
||||||
angle = 180 / M_PI * acosVal;
|
|
||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vec3ProjectOver(vec3 *a, vec3 *over, vec3 *result) {
|
||||||
|
float length = vec3DotProduct(a, over);
|
||||||
|
result->x = length * over->x;
|
||||||
|
result->y = length * over->y;
|
||||||
|
result->z = length * over->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ float vec3Distance(vec3 *a, vec3 *b);
|
||||||
void vec3Normal(vec3 *a, vec3 *b, vec3 *c, vec3 *normal);
|
void vec3Normal(vec3 *a, vec3 *b, vec3 *c, vec3 *normal);
|
||||||
void vec3RotateAlong(vec3 *a, float angle, vec3 *axis, vec3 *result);
|
void vec3RotateAlong(vec3 *a, float angle, vec3 *axis, vec3 *result);
|
||||||
float vec3Angle(vec3 *a, vec3 *b);
|
float vec3Angle(vec3 *a, vec3 *b);
|
||||||
|
void vec3ProjectOver(vec3 *a, vec3 *over, vec3 *result);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue