mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-11-23 04:19:50 +00:00
Work on portal surface hole cutting
This commit is contained in:
parent
92247567e0
commit
17ef47fe2c
@ -41,7 +41,8 @@ RUN apt install -y binutils-mips-n64 \
|
||||
build-essential \
|
||||
wget \
|
||||
unzip \
|
||||
sox
|
||||
sox \
|
||||
mpg123
|
||||
|
||||
COPY skelatool64/src skelatool64/src
|
||||
COPY skelatool64/main.cpp skelatool64/main.cpp
|
||||
|
12
Makefile
12
Makefile
@ -215,17 +215,27 @@ build/src/levels/levels.o: build/assets/test_chambers/level_list.h build/assets/
|
||||
|
||||
SOUND_ATTRIBUTES = $(shell find assets/ -type f -name '*.sox')
|
||||
|
||||
MUSIC_ATTRIBUTES = $(shell find assets/sound/music/ -type f -name '*.msox')
|
||||
|
||||
INS_SOUNDS = $(shell find assets/ -type f -name '*.ins')
|
||||
|
||||
SOUND_CLIPS = $(SOUND_ATTRIBUTES:%.sox=build/%.aifc) $(INS_SOUNDS)
|
||||
SOUND_CLIPS = $(SOUND_ATTRIBUTES:%.sox=build/%.aifc) $(INS_SOUNDS) $(MUSIC_ATTRIBUTES:%.msox=build/%.aifc)
|
||||
|
||||
$(INS_SOUNDS): portal_pak_dir
|
||||
|
||||
portal_pak_dir/sound/music/%.wav: portal_pak_dir/sound/music/%.mp3
|
||||
|
||||
build/%.aifc: %.sox portal_pak_dir
|
||||
@mkdir -p $(@D)
|
||||
sox $(<:assets/%.sox=portal_pak_dir/%.wav) $(shell cat $<) $(@:%.aifc=%.wav)
|
||||
$(SFZ2N64) -o $@ $(@:%.aifc=%.wav)
|
||||
|
||||
build/%.aifc: %.msox portal_pak_dir
|
||||
@mkdir -p $(@D)
|
||||
mpg123 -w $(<:assets/%.msox=portal_pak_dir/%.wav) $(<:assets/%.msox=portal_pak_dir/%.mp3)
|
||||
sox $(<:assets/%.msox=portal_pak_dir/%.wav) $(shell cat $<) $(@:%.aifc=%.wav)
|
||||
$(SFZ2N64) -o $@ $(@:%.aifc=%.wav)
|
||||
|
||||
build/assets/sound/sounds.sounds build/assets/sound/sounds.sounds.tbl: $(SOUND_CLIPS)
|
||||
@mkdir -p $(@D)
|
||||
$(SFZ2N64) -o $@ $^
|
||||
|
@ -22,7 +22,7 @@ Install `vtf2png`, `sfz2n64` and `skeletool64`
|
||||
echo "deb [trusted=yes] https://lambertjamesd.github.io/apt/ ./" \
|
||||
| tee /etc/apt/sources.list.d/lambertjamesd.list
|
||||
|
||||
sudo apt install vtf2png sfz2n64 skeletool64
|
||||
sudo apt install vtf2png sfz2n64 skeletool64 mpg123
|
||||
```
|
||||
|
||||
<br />
|
||||
@ -92,3 +92,4 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
|
||||
- [ ] Cut holes in portal walls
|
||||
- [ ] Cube dispenser
|
||||
- [ ] NAN in overlap
|
||||
- [ ] Get an optimized build working
|
||||
|
1
assets/sound/music/portal_still_alive.msox
Normal file
1
assets/sound/music/portal_still_alive.msox
Normal file
@ -0,0 +1 @@
|
||||
-c 1 -r 22050
|
@ -169,6 +169,8 @@ std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition
|
||||
portalSurface->AddPrimitive(sideCount);
|
||||
// edgesCount
|
||||
portalSurface->AddPrimitive(edgeOrder.size());
|
||||
// vertexCount
|
||||
portalSurface->AddPrimitive(mesh.mMesh->mNumVertices);
|
||||
|
||||
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(quad.edgeA)));
|
||||
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(quad.edgeB)));
|
||||
|
30
src/math/vector2s16.c
Normal file
30
src/math/vector2s16.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include "vector2s16.h"
|
||||
|
||||
void vector2s16Add(struct Vector2s16* a, struct Vector2s16* b, struct Vector2s16* output) {
|
||||
output->x = a->x + b->x;
|
||||
output->y = a->y + b->y;
|
||||
}
|
||||
|
||||
void vector2s16Sub(struct Vector2s16* a, struct Vector2s16* b, struct Vector2s16* output) {
|
||||
output->x = a->x - b->x;
|
||||
output->y = a->y - b->y;
|
||||
}
|
||||
|
||||
int vector2s16Dot(struct Vector2s16* a, struct Vector2s16* b) {
|
||||
return (int)a->x * b->x + (int)a->y * b->y;
|
||||
}
|
||||
|
||||
int vector2s16Cross(struct Vector2s16* a, struct Vector2s16* b) {
|
||||
return (int)a->x * b->y - (int)a->y * b->x;
|
||||
}
|
||||
|
||||
int vector2s16MagSqr(struct Vector2s16* a) {
|
||||
return (int)a->x * a->x + (int)a->y * a->y;
|
||||
}
|
||||
|
||||
int vector2s16DistSqr(struct Vector2s16* a, struct Vector2s16* b) {
|
||||
int x = (int)a->x - (int)b->x;
|
||||
int y = (int)a->y - (int)b->y;
|
||||
|
||||
return x * x + y * y;
|
||||
}
|
25
src/math/vector2s16.h
Normal file
25
src/math/vector2s16.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __MATH_VECTOR2S16_H__
|
||||
#define __MATH_VECTOR2S16_H__
|
||||
|
||||
struct Vector2s16 {
|
||||
union {
|
||||
struct {
|
||||
short x;
|
||||
short y;
|
||||
};
|
||||
int equalTest;
|
||||
};
|
||||
};
|
||||
|
||||
void vector2s16Add(struct Vector2s16* a, struct Vector2s16* b, struct Vector2s16* output);
|
||||
void vector2s16Sub(struct Vector2s16* a, struct Vector2s16* b, struct Vector2s16* output);
|
||||
|
||||
int vector2s16Dot(struct Vector2s16* a, struct Vector2s16* b);
|
||||
|
||||
int vector2s16Cross(struct Vector2s16* a, struct Vector2s16* b);
|
||||
|
||||
int vector2s16MagSqr(struct Vector2s16* a);
|
||||
|
||||
int vector2s16DistSqr(struct Vector2s16* a, struct Vector2s16* b);
|
||||
|
||||
#endif
|
@ -4,9 +4,387 @@
|
||||
#include "math/mathf.h"
|
||||
#include "math/vector2.h"
|
||||
#include <math.h>
|
||||
#include "../util/memory.h"
|
||||
|
||||
#define NO_OVERLAP 0x10000
|
||||
|
||||
#define GET_NEXT_EDGE(surfaceEdge, isReverse) ((isReverse) ? (surfaceEdge)->nextEdgeReverse : (surfaceEdge)->nextEdge)
|
||||
#define GET_PREV_EDGE(surfaceEdge, isReverse) ((isReverse) ? (surfaceEdge)->prevEdgeReverse : (surfaceEdge)->prevEdge)
|
||||
|
||||
#define GET_CURRENT_POINT(surfaceEdge, isReverse) ((isReverse) ? (surfaceEdge)->bIndex : (surfaceEdge->aIndex))
|
||||
#define GET_NEXT_POINT(surfaceEdge, isReverse) ((isReverse) ? (surfaceEdge)->aIndex : (surfaceEdge->bIndex))
|
||||
|
||||
#define MAX_SEARCH_ITERATIONS 20
|
||||
|
||||
#define ADDITIONAL_EDGE_CAPACITY 32
|
||||
#define ADDITIONAL_VERTEX_CAPACITY 16
|
||||
|
||||
struct SurfaceEdgeWithSide {
|
||||
int edgeIndex;
|
||||
int isReverse;
|
||||
};
|
||||
|
||||
struct PortalSurfaceBuilder {
|
||||
struct PortalSurface* surface;
|
||||
struct Vector2s16* additionalVertices;
|
||||
struct SurfaceEdge* additionalEdges;
|
||||
short currentVertex;
|
||||
short currentEdge;
|
||||
|
||||
struct SurfaceEdgeWithSide edgeOnSearchLoop;
|
||||
union {
|
||||
// set when hasEdge is true
|
||||
struct SurfaceEdgeWithSide cuttingEdge;
|
||||
// set when hasEdge is false
|
||||
struct Vector2s16* startingPoint;
|
||||
};
|
||||
short hasEdge;
|
||||
short hasConnected;
|
||||
};
|
||||
|
||||
int portalSurfaceFindEnclosingFace(struct PortalSurface* surface, struct Vector2s16* aroundPoint, struct SurfaceEdgeWithSide* output) {
|
||||
struct SurfaceEdge* currentEdge = &surface->edges[0];
|
||||
int edgeDistanceSq = vector2s16DistSqr(&surface->vertices[surface->edges[0].aIndex], aroundPoint);
|
||||
|
||||
for (int i = 1; i < surface->sideCount; ++i) {
|
||||
int dist = vector2s16DistSqr(&surface->vertices[surface->edges[i].aIndex], aroundPoint);
|
||||
|
||||
if (dist < edgeDistanceSq) {
|
||||
edgeDistanceSq = dist;
|
||||
currentEdge = &surface->edges[i];
|
||||
}
|
||||
}
|
||||
|
||||
int isEdgeReverse = 0;
|
||||
int startEdgeIndex = currentEdge - surface->edges;
|
||||
|
||||
int nextEdgeIndex;
|
||||
|
||||
int currentIteration = 0;
|
||||
|
||||
while (currentIteration < MAX_SEARCH_ITERATIONS && (nextEdgeIndex = GET_NEXT_EDGE(currentEdge, isEdgeReverse)) != startEdgeIndex) {
|
||||
struct Vector2s16 edgeDir;
|
||||
struct Vector2s16 pointDir;
|
||||
|
||||
int anchorPoint = GET_CURRENT_POINT(currentEdge, isEdgeReverse);
|
||||
|
||||
vector2s16Sub(
|
||||
&surface->vertices[GET_NEXT_POINT(currentEdge, isEdgeReverse)],
|
||||
&surface->vertices[anchorPoint],
|
||||
&edgeDir
|
||||
);
|
||||
|
||||
vector2s16Sub(
|
||||
aroundPoint,
|
||||
&surface->vertices[anchorPoint],
|
||||
&pointDir
|
||||
);
|
||||
|
||||
if (vector2s16Cross(&edgeDir, &pointDir) < 0) {
|
||||
// the point is on the opposite side of this edge
|
||||
startEdgeIndex = surface->edges - currentEdge;
|
||||
isEdgeReverse = !isEdgeReverse;
|
||||
|
||||
nextEdgeIndex = GET_NEXT_EDGE(currentEdge, isEdgeReverse);
|
||||
|
||||
if (nextEdgeIndex == 0xFF) {
|
||||
// has no opposite edge
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int currentIndex = currentEdge - surface->edges;
|
||||
currentEdge = &surface->edges[nextEdgeIndex];
|
||||
isEdgeReverse = currentEdge->prevEdgeReverse == currentIndex;
|
||||
|
||||
++currentIteration;
|
||||
}
|
||||
|
||||
if (currentIteration == MAX_SEARCH_ITERATIONS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
output->edgeIndex = currentEdge - surface->edges;
|
||||
output->isReverse = isEdgeReverse;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct SurfaceEdge* portalSurfaceGetEdge(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex) {
|
||||
if (edgeIndex < surfaceBuilder->surface->edgeCount) {
|
||||
return &surfaceBuilder->surface->edges[edgeIndex];
|
||||
} else {
|
||||
return &surfaceBuilder->additionalEdges[edgeIndex - surfaceBuilder->surface->edgeCount];
|
||||
}
|
||||
}
|
||||
|
||||
struct Vector2s16* portalSurfaceGetPoint(struct PortalSurfaceBuilder* surfaceBuilder, int vertexIndex) {
|
||||
if (vertexIndex < surfaceBuilder->surface->vertexCount) {
|
||||
return &surfaceBuilder->surface->vertices[vertexIndex];
|
||||
} else {
|
||||
return &surfaceBuilder->additionalVertices[vertexIndex - surfaceBuilder->surface->vertexCount];
|
||||
}
|
||||
}
|
||||
|
||||
void portalSurfaceNextEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* currentEdge, struct SurfaceEdgeWithSide* nextEdge) {
|
||||
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge->edgeIndex);
|
||||
|
||||
nextEdge->edgeIndex = GET_NEXT_EDGE(edge, currentEdge->isReverse);
|
||||
nextEdge->isReverse = portalSurfaceGetEdge(surfaceBuilder, nextEdge->edgeIndex)->prevEdgeReverse == currentEdge->edgeIndex;
|
||||
}
|
||||
|
||||
void portalSurfacePrevEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* currentEdge, struct SurfaceEdgeWithSide* prevEdge) {
|
||||
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge->edgeIndex);
|
||||
|
||||
prevEdge->edgeIndex = GET_PREV_EDGE(edge, currentEdge->isReverse);
|
||||
prevEdge->isReverse = portalSurfaceGetEdge(surfaceBuilder, prevEdge->edgeIndex)->nextEdgeReverse == currentEdge->edgeIndex;
|
||||
}
|
||||
|
||||
#define MAX_INTERSECT_LOOPS 20
|
||||
|
||||
int portalSurfaceIsPointOnLine(struct Vector2s16* pointA, struct Vector2s16* edgeA, struct Vector2s16* edgeDir) {
|
||||
struct Vector2s16 originOffset;
|
||||
vector2s16Sub(&edgeA, &pointA, &originOffset);
|
||||
|
||||
s64 magProduct = (s64)vector2MagSqr(&edgeDir) * vector2MagSqr(&originOffset);
|
||||
s64 dotProduct = vector2Dot(&edgeDir, &originOffset);
|
||||
|
||||
return magProduct == dotProduct * dotProduct;
|
||||
}
|
||||
|
||||
enum IntersectionType {
|
||||
IntersectionTypeNone,
|
||||
IntersectionTypePoint,
|
||||
IntersectionTypeColinear
|
||||
};
|
||||
|
||||
enum IntersectionType portalSurfaceIntersect(struct Vector2s16* pointA, struct Vector2s16* pointDir, struct Vector2s16* edgeA, struct Vector2s16* edgeB, struct Vector2s16* intersection) {
|
||||
struct Vector2s16 edgeDir;
|
||||
vector2s16Sub(edgeB, edgeA, &edgeDir);
|
||||
|
||||
struct Vector2s16 originOffset;
|
||||
vector2s16Sub(&edgeA, &pointA, &originOffset);
|
||||
|
||||
int pointLerp = vector2s16Cross(&originOffset, &edgeDir);
|
||||
|
||||
if (pointLerp <= 0) {
|
||||
return IntersectionTypeNone;
|
||||
}
|
||||
|
||||
int denominator = vector2s16Cross(pointDir, &edgeDir);
|
||||
|
||||
if (denominator == 0) {
|
||||
if (!portalSurfaceIsPointOnLine(pointA, edgeA, &edgeDir)) {
|
||||
return IntersectionTypeNone;
|
||||
}
|
||||
|
||||
int directionDot = vector2s16Dot(pointDir, &edgeDir);
|
||||
|
||||
// find the point furthest in the direction of pointDir
|
||||
// that is on both line segments
|
||||
if (directionDot > 0) {
|
||||
// pointing towards b
|
||||
if (vector2DistSqr(edgeB, pointA) >= vector2MagSqr(pointDir)) {
|
||||
// edge ends first
|
||||
*intersection = *edgeB;
|
||||
} else {
|
||||
// point ends first
|
||||
vector2s16Add(pointA, pointDir, intersection);
|
||||
}
|
||||
} else {
|
||||
if (vector2MagSqr(originOffset) >= vector2MagSqr(pointDir)) {
|
||||
// edge ends first
|
||||
*intersection = *edgeA;
|
||||
} else {
|
||||
// point ends first
|
||||
vector2s16Add(pointA, pointDir, intersection);
|
||||
}
|
||||
}
|
||||
|
||||
// the lines are colinear
|
||||
return IntersectionTypeColinear;
|
||||
}
|
||||
|
||||
if (pointLerp > denominator || denominator == 0) {
|
||||
return IntersectionTypeNone;
|
||||
}
|
||||
|
||||
int edgeLerp = vector2s16Cross(pointDir, &originOffset);
|
||||
|
||||
if (edgeLerp < 0 || edgeLerp > denominator) {
|
||||
return IntersectionTypeNone;
|
||||
}
|
||||
|
||||
intersection->x = (short)((s64)pointDir->x * (s64)pointLerp / (s64)denominator) + pointA->x;
|
||||
intersection->y = (short)((s64)pointDir->y * (s64)pointLerp / (s64)denominator) + pointA->y;
|
||||
|
||||
return IntersectionTypePoint;
|
||||
}
|
||||
|
||||
void portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* pointA, struct Vector2s16* pointDir) {
|
||||
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
||||
|
||||
for (int iteration = 0; iteration < MAX_INTERSECT_LOOPS; ++iteration) {
|
||||
struct SurfaceEdgeWithSide nextEdge;
|
||||
|
||||
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge);
|
||||
|
||||
if (nextEdge.edgeIndex == surfaceBuilder->edgeOnSearchLoop.edgeIndex && nextEdge.isReverse == surfaceBuilder->edgeOnSearchLoop.isReverse) {
|
||||
// finished searching loop
|
||||
break;
|
||||
}
|
||||
|
||||
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex);
|
||||
|
||||
struct Vector2s16* edgeA = portalSurfaceGetPoint(surfaceBuilder, GET_CURRENT_POINT(edge, currentEdge.isReverse));
|
||||
struct Vector2s16* edgeB = portalSurfaceGetPoint(surfaceBuilder, GET_NEXT_POINT(edge, currentEdge.isReverse));
|
||||
|
||||
struct Vector2s16 intersectionPoint;
|
||||
|
||||
enum IntersectionType intersectType = portalSurfaceIntersect(pointA, pointDir, edgeA, edgeB, &intersectionPoint);
|
||||
|
||||
if (intersectType) {
|
||||
|
||||
}
|
||||
|
||||
currentEdge = nextEdge;
|
||||
}
|
||||
}
|
||||
|
||||
int portalSurfaceSplitEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* edge, struct Vector2s16* point) {
|
||||
if (surfaceBuilder->currentEdge == ADDITIONAL_EDGE_CAPACITY || surfaceBuilder->currentVertex == ADDITIONAL_VERTEX_CAPACITY) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
surfaceBuilder->additionalVertices[surfaceBuilder->currentVertex] = *point;
|
||||
int newVertexIndex = surfaceBuilder->currentVertex + surfaceBuilder->surface->vertexCount;
|
||||
++surfaceBuilder->currentVertex;
|
||||
|
||||
struct SurfaceEdge* existingEdge = portalSurfaceGetEdge(surfaceBuilder, edge->edgeIndex);
|
||||
|
||||
struct SurfaceEdgeWithSide nextEdge;
|
||||
struct SurfaceEdgeWithSide prevReverseEdge;
|
||||
|
||||
portalSurfaceNextEdge(surfaceBuilder, edge, &nextEdge);
|
||||
portalSurfacePrevEdge(surfaceBuilder, edge, &prevReverseEdge);
|
||||
|
||||
struct SurfaceEdge previousEdgeCopy = *existingEdge;
|
||||
|
||||
struct SurfaceEdge* newEdge = &surfaceBuilder->additionalEdges[surfaceBuilder->currentEdge];
|
||||
int newEdgeIndex = surfaceBuilder->currentEdge + surfaceBuilder->surface->edgeCount;
|
||||
++surfaceBuilder->currentEdge;
|
||||
|
||||
newEdge->bIndex = existingEdge->bIndex;
|
||||
newEdge->aIndex = newVertexIndex;
|
||||
newEdge->nextEdge = existingEdge->nextEdge;
|
||||
newEdge->prevEdge = edge->edgeIndex;
|
||||
newEdge->nextEdgeReverse = edge->edgeIndex;
|
||||
newEdge->prevEdgeReverse = existingEdge->prevEdgeReverse;
|
||||
|
||||
existingEdge->bIndex = newVertexIndex;
|
||||
existingEdge->nextEdge = newEdgeIndex;
|
||||
existingEdge->prevEdgeReverse = newVertexIndex;
|
||||
|
||||
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex);
|
||||
|
||||
if (nextEdge.isReverse) {
|
||||
nextEdgePtr->prevEdgeReverse = newEdgeIndex;
|
||||
} else {
|
||||
nextEdgePtr->prevEdge = newEdgeIndex;
|
||||
}
|
||||
|
||||
struct SurfaceEdge* prevEdgePtr = portalSurfaceGetEdge(surfaceBuilder, prevReverseEdge.edgeIndex);
|
||||
|
||||
if (prevReverseEdge.isReverse) {
|
||||
prevEdgePtr->nextEdgeReverse = newEdgeIndex;
|
||||
} else {
|
||||
prevEdgePtr->nextEdge = newEdgeIndex;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int portalSurfaceFindStartingPoint(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* point) {
|
||||
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
||||
|
||||
struct Vector2s16* edgeA = portalSurfaceGetPoint(surfaceBuilder, GET_CURRENT_POINT(edge, currentEdge.isReverse));
|
||||
|
||||
for (int iteration = 0; iteration < MAX_INTERSECT_LOOPS; ++iteration) {
|
||||
struct SurfaceEdgeWithSide nextEdge;
|
||||
|
||||
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge);
|
||||
|
||||
if (nextEdge.edgeIndex == surfaceBuilder->edgeOnSearchLoop.edgeIndex && nextEdge.isReverse == surfaceBuilder->edgeOnSearchLoop.isReverse) {
|
||||
// finished searching loop
|
||||
break;
|
||||
}
|
||||
|
||||
struct Vector2s16* edgeB = portalSurfaceGetPoint(surfaceBuilder, GET_NEXT_POINT(edge, currentEdge.isReverse));
|
||||
|
||||
struct Vector2s16 edgeDir;
|
||||
vector2s16Sub(edgeB, edgeA, &edgeDir);
|
||||
|
||||
if (portalSurfaceIsPointOnLine(point, edgeA, &edgeDir)) {
|
||||
surfaceBuilder->hasEdge = 1;
|
||||
surfaceBuilder->hasConnected = 1;
|
||||
|
||||
if (point->equalTest == edgeA->equalTest) {
|
||||
portalSurfacePrevEdge(surfaceBuilder, ¤tEdge, &surfaceBuilder->cuttingEdge);
|
||||
} else if (point->equalTest == edgeB->equalTest) {
|
||||
surfaceBuilder->cuttingEdge = currentEdge;
|
||||
} else {
|
||||
if (!portalSurfaceSplitEdge(surfaceBuilder, ¤tEdge, point)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
surfaceBuilder->cuttingEdge = currentEdge;
|
||||
}
|
||||
|
||||
surfaceBuilder->edgeOnSearchLoop = surfaceBuilder->cuttingEdge;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
edgeA = edgeB;
|
||||
currentEdge = nextEdge;
|
||||
}
|
||||
|
||||
surfaceBuilder->hasEdge = 0;
|
||||
surfaceBuilder->hasConnected = 0;
|
||||
surfaceBuilder->startingPoint = point;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct PortalSurface* portalSurfaceCutHole(struct PortalSurface* surface, struct Vector2s16* loop, int loopSize) {
|
||||
struct PortalSurfaceBuilder surfaceBuilder;
|
||||
|
||||
surfaceBuilder.additionalVertices = stackMalloc(sizeof(struct Vector2s16) * ADDITIONAL_VERTEX_CAPACITY);
|
||||
surfaceBuilder.currentVertex = 0;
|
||||
surfaceBuilder.additionalEdges = stackMalloc(sizeof(struct SurfaceEdge) * ADDITIONAL_EDGE_CAPACITY);
|
||||
surfaceBuilder.currentEdge = 0;
|
||||
|
||||
if (!portalSurfaceFindEnclosingFace(surface, &loop[0], &surfaceBuilder.edgeOnSearchLoop)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!portalSurfaceFindStartingPoint(surfaceBuilder, &loop[0])) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct Vector2s16* prev = &loop[0];
|
||||
|
||||
for (int i = 1; i < loopSize; ++i) {
|
||||
struct Vector2s16* next = &loop[0];
|
||||
struct Vector2s16 dir;
|
||||
|
||||
vector2s16Sub(next, prev, &dir);
|
||||
portalSurfaceIntersectEdgeWithLoop(surfaceBuilder, prev, &dir);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void portalSurface2DPoint(struct PortalSurface* surface, struct Vector3* at, struct Vector2s16* output) {
|
||||
struct Vector3 offset;
|
||||
vector3Sub(at, &surface->corner, &offset);
|
||||
@ -61,7 +439,9 @@ int portalSurfaceIsInside(struct PortalSurface* surface, struct Transform* porta
|
||||
return intersectionCount % 2;
|
||||
}
|
||||
|
||||
void portalSurfaceAdjustPosition(struct PortalSurface* surface, struct Transform* portalAt, struct Vector2s16* output, struct Vector2s16* outlineLoopOutput) {
|
||||
#define MAX_POS_ADJUST_ITERATIONS 3
|
||||
|
||||
int portalSurfaceAdjustPosition(struct PortalSurface* surface, struct Transform* portalAt, struct Vector2s16* output, struct Vector2s16* outlineLoopOutput) {
|
||||
struct Vector2s16 minPortal;
|
||||
struct Vector2s16 maxPortal;
|
||||
|
||||
@ -88,7 +468,9 @@ void portalSurfaceAdjustPosition(struct PortalSurface* surface, struct Transform
|
||||
halfSize.x = (maxPortal.x - minPortal.x) >> 1;
|
||||
halfSize.y = (maxPortal.y - minPortal.y) >> 1;
|
||||
|
||||
for (int interation = 0; interation < 2; ++interation) {
|
||||
int iteration = 0;
|
||||
|
||||
for (interation = 0; interation < MAX_POS_ADJUST_ITERATIONS; ++interation) {
|
||||
int minOverlap = NO_OVERLAP;
|
||||
struct Vector2s16 minOverlapOffset;
|
||||
|
||||
@ -171,6 +553,10 @@ void portalSurfaceAdjustPosition(struct PortalSurface* surface, struct Transform
|
||||
output->x += minOverlapOffset.x;
|
||||
output->y += minOverlapOffset.y;
|
||||
}
|
||||
|
||||
// running out of iterations is a sign there isn't enough
|
||||
// room for the portal
|
||||
return iteration != MAX_POS_ADJUST_ITERATIONS;
|
||||
}
|
||||
|
||||
int portalSurfaceGenerate(struct PortalSurface* surface, struct Transform* portalAt, Vtx* vertices, Gfx* triangles) {
|
||||
@ -181,7 +567,9 @@ int portalSurfaceGenerate(struct PortalSurface* surface, struct Transform* porta
|
||||
// find all portal edge intersections
|
||||
struct Vector2s16 correctPosition;
|
||||
struct Vector2s16 portalOutline[PORTAL_LOOP_SIZE];
|
||||
portalSurfaceAdjustPosition(surface, portalAt, &correctPosition, portalOutline);
|
||||
if (!portalSurfaceAdjustPosition(surface, portalAt, &correctPosition, portalOutline)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
portalSurfaceInverse(surface, &correctPosition, &portalAt->position);
|
||||
// TODO
|
||||
|
@ -5,17 +5,13 @@
|
||||
|
||||
#include "math/transform.h"
|
||||
#include "math/plane.h"
|
||||
#include "math/vector2s16.h"
|
||||
|
||||
#define FIXED_POINT_PRECISION 8
|
||||
#define FIXED_POINT_SCALAR (1 << FIXED_POINT_PRECISION)
|
||||
|
||||
#define VECTOR2s16_AS_ARRAY(vector) ((s16*)(vector))
|
||||
|
||||
struct Vector2s16 {
|
||||
s16 x;
|
||||
s16 y;
|
||||
};
|
||||
|
||||
struct SurfaceEdge {
|
||||
u8 aIndex;
|
||||
u8 bIndex;
|
||||
@ -32,6 +28,7 @@ struct PortalSurface {
|
||||
|
||||
u8 sideCount;
|
||||
u8 edgeCount;
|
||||
u8 vertexCount;
|
||||
|
||||
struct Vector3 right;
|
||||
struct Vector3 up;
|
||||
|
Loading…
Reference in New Issue
Block a user