work on cylinder collider

This commit is contained in:
James Lambert 2022-05-29 16:10:50 -06:00
parent 4956892ae1
commit 7c240a8393
9 changed files with 189 additions and 15 deletions

View file

@ -207,7 +207,6 @@ materials:
siz: G_IM_SIZ_4b
fmt: G_IM_FMT_I
gDPSetRenderMode: G_RM_ZB_OPA_DECAL
gSPGeometryMode:
clear: [G_LIGHTING]
set: [G_SHADE]
@ -225,7 +224,6 @@ materials:
siz: G_IM_SIZ_4b
fmt: G_IM_FMT_I
gDPSetRenderMode: G_RM_ZB_OPA_DECAL
gSPGeometryMode:
clear: [G_LIGHTING]
set: [G_SHADE]
@ -243,7 +241,6 @@ materials:
siz: G_IM_SIZ_4b
fmt: G_IM_FMT_I
gDPSetRenderMode: G_RM_ZB_OPA_DECAL
gSPGeometryMode:
clear: [G_LIGHTING]
set: [G_SHADE]
@ -261,7 +258,6 @@ materials:
siz: G_IM_SIZ_4b
fmt: G_IM_FMT_I
gDPSetRenderMode: G_RM_ZB_OPA_DECAL
gSPGeometryMode:
clear: [G_LIGHTING]
set: [G_SHADE]

Binary file not shown.

View file

@ -432,7 +432,7 @@ void LevelGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition&
levelDef->AddPrimitive("triggerCount", mTriggerOutput.triggers.size());
levelDef->AddPrimitive("locationCount", mRoomOutput.namedLocations.size());
levelDef->AddPrimitive("doorCount", mRoomOutput.doors.size());
levelDef->AddPrimitive("startLocation", mRoomOutput.FindLocationRoom("start"));
levelDef->AddPrimitive("startLocation", mRoomOutput.FindLocationIndex("start"));
fileDefinition.AddDefinition(std::unique_ptr<FileDefinition>(new DataFileDefinition("struct LevelDefinition", fileDefinition.GetUniqueName("level"), false, "_geo", std::move(levelDef))));
}

View file

@ -26,6 +26,10 @@ void StaticGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition&
std::vector<RenderChunk> renderChunks;
MeshDefinitionGenerator::AppendRenderChunks(scene, *node, fileDefinition, mSettings, renderChunks);
if (std::string((*node)->mName.C_Str()) == "@static_wall_00.013") {
std::cout << "Here" << std::endl;
}
for (auto& chunk : renderChunks) {
StaticContentElement element;
@ -70,7 +74,7 @@ void StaticGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition&
std::unique_ptr<StructureDataChunk> singleMapping(new StructureDataChunk());
int currentIndex = prevIndex;
while (currentIndex < (int)mIncludedNodes.size() && mRoomMapping.roomIndexMapping[mIncludedNodes[currentIndex]] <= roomIndex) {
while (currentIndex < (int)mOutput.staticRooms.size() && mOutput.staticRooms[currentIndex] <= roomIndex) {
++currentIndex;
}

View file

@ -54,9 +54,6 @@ void graphicsCreateTask(struct GraphicsTask* targetTask, GraphicsCallback callba
gDPPipeSync(renderState->dl++);
gDPSetColorImage(renderState->dl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WD, osVirtualToPhysical(targetTask->framebuffer));
gDPSetFillColor(renderState->dl++, (CLEAR_COLOR << 16 |
CLEAR_COLOR));
gDPFillRectangle(renderState->dl++, 0, 0, SCREEN_WD-1, SCREEN_HT-1);
gDPPipeSync(renderState->dl++);
gDPSetCycleType(renderState->dl++, G_CYC_1CYCLE);

View file

@ -4,6 +4,7 @@
#include "contact_solver.h"
#include "collision_quad.h"
#include "raycasting.h"
#include "line.h"
struct ColliderCallbacks gCollisionCylinderCallbacks = {
NULL,
@ -141,6 +142,149 @@ int _collisionCylinderPerpendicular(struct CollisionCylinder* cylinder, struct T
return edgesToCheck;
}
#define EDGE_LERP_BIAS 0.00001f
void collisionCylinderSingleCap(struct CollisionCylinder* cylinder, struct Transform* cylinderTransform, struct Vector3* centerAxis, float capDistance, float invDot, int idOffset, struct CollisionEdge* edge, struct Vector3* edgeDirection, struct ContactConstraintState* output) {
float dOffset = vector3Dot(&cylinderTransform->position, centerAxis);
float lineDot = vector3Dot(&edge->origin, centerAxis);
float distance = -(lineDot - (dOffset + capDistance)) * invDot;
if (distance < EDGE_LERP_BIAS || distance > edge->length + EDGE_LERP_BIAS) {
return;
}
struct ContactState* contact = &output->contacts[output->contactCount];
vector3AddScaled(&cylinderTransform->position, centerAxis, capDistance, &contact->rb);
vector3AddScaled(&edge->origin, &edge->direction, distance, &contact->ra);
struct Vector3 offset;
vector3Sub(&contact->rb, &contact->ra, &offset);
float offsetSqrd = vector3MagSqrd(&offset);
if (offsetSqrd > cylinder->radius * cylinder->radius) {
return;
}
if (vector3Dot(&offset, edgeDirection) < 0.0f) {
return;
}
if (output->contactCount == 0) {
if (offsetSqrd < 0.00001f) {
vector3Cross(centerAxis, edgeDirection, &output->normal);
} else {
vector3Sub(&contact->ra, &contact->ra, &output->normal);
}
vector3Normalize(&output->normal, &output->normal);
output->tangentVectors[0] = *centerAxis;
vector3Cross(&output->normal, &output->tangentVectors[0], &output->tangentVectors[1]);
output->restitution = 0.0f;
output->friction = 1.0f;
}
vector3AddScaled(&contact->rb, &output->normal, -cylinder->radius, &contact->rb);
contact->penetration = vector3Dot(&contact->ra, &output->normal) - vector3Dot(&contact->rb, &output-> normal);
if (contact->penetration >= NEGATIVE_PENETRATION_BIAS) {
return;
}
contact->id = idOffset;
contact->bias = 0;
contact->normalMass = 0;
contact->tangentMass[0] = 0.0f;
contact->tangentMass[1] = 0.0f;
contact->normalImpulse = 0.0f;
contact->tangentImpulse[0] = 0.0f;
contact->tangentImpulse[1] = 0.0f;
++output->contactCount;
}
int collisionCylinderCap(struct CollisionCylinder* cylinder, struct Transform* cylinderTransform, struct Vector3* centerAxis, float normalDotProduct, int idOffset, struct CollisionEdge* edge, struct Vector3* edgeDirection, struct ContactConstraintState* output) {
if (fabsf(normalDotProduct) < 0.00001f) {
return 0;
}
float invDot = 1.0f / normalDotProduct;
collisionCylinderSingleCap(cylinder, cylinderTransform, centerAxis, cylinder->halfHeight, invDot, idOffset + 1, edge, edgeDirection, output);
collisionCylinderSingleCap(cylinder, cylinderTransform, centerAxis, -cylinder->halfHeight, invDot, idOffset + 2, edge, edgeDirection, output);
return output->contactCount > 0;
}
int collisionCylinderEdge(struct CollisionCylinder* cylinder, struct Transform* cylinderTransform, struct Vector3* centerAxis, float normalDotProduct, int idOffset, struct CollisionEdge* edge, struct Vector3* edgeDirection, struct ContactConstraintState* output) {
float cylinderLerp;
float edgeLerp;
if (!lineNearestApproach(&cylinderTransform->position, centerAxis, &edge->origin, &edge->direction, &cylinderLerp, &edgeLerp)) {
return collisionCylinderCap(cylinder, cylinderTransform, centerAxis, normalDotProduct, idOffset, edge, edgeDirection, output);
}
struct ContactState* contact = &output->contacts[output->contactCount];
vector3AddScaled(&cylinderTransform->position, centerAxis, cylinderLerp, &contact->rb);
vector3AddScaled(&edge->origin, &edge->direction, edgeLerp, &contact->ra);
struct Vector3 offset;
vector3Sub(&contact->rb, &contact->ra, &offset);
float offsetSqrd = vector3MagSqrd(&offset);
if (offsetSqrd > cylinder->radius * cylinder->radius) {
return 0;
}
if (cylinderLerp > -cylinder->halfHeight - EDGE_LERP_BIAS && cylinderLerp < cylinder->halfHeight + EDGE_LERP_BIAS &&
edgeLerp > -EDGE_LERP_BIAS && edgeLerp < edge->length + EDGE_LERP_BIAS) {
if (vector3Dot(&offset, edgeDirection) < 0.0f) {
return 0;
}
struct Vector3 offsetNormalized;
if (offsetSqrd < 0.00001f) {
vector3Cross(centerAxis, &edge->direction, &offsetNormalized);
vector3Normalize(&offsetNormalized, &offsetNormalized);
} else {
vector3Scale(&offset, &offsetNormalized, 1.0f / sqrtf(offsetSqrd));
}
if (output->contactCount == 0) {
output->normal = offsetNormalized;
output->tangentVectors[0] = *centerAxis;
vector3Cross(&output->normal, &output->tangentVectors[0], &output->tangentVectors[1]);
output->restitution = 0.0f;
output->friction = 1.0f;
}
vector3AddScaled(&contact->rb, &offsetNormalized, -cylinder->radius, &contact->rb);
contact->penetration = vector3Dot(&contact->ra, &output->normal) - vector3Dot(&contact->rb, &output-> normal);
if (contact->penetration >= NEGATIVE_PENETRATION_BIAS) {
return 0;
}
contact->id = idOffset;
contact->bias = 0;
contact->normalMass = 0;
contact->tangentMass[0] = 0.0f;
contact->tangentMass[1] = 0.0f;
contact->normalImpulse = 0.0f;
contact->tangentImpulse[0] = 0.0f;
contact->tangentImpulse[1] = 0.0f;
++output->contactCount;
return 1;
}
return collisionCylinderCap(cylinder, cylinderTransform, centerAxis, normalDotProduct, idOffset, edge, edgeDirection, output);
}
int collisionCylinderCollideQuad(void* data, struct Transform* cylinderTransform, struct CollisionQuad* quad, struct ContactConstraintState* output) {
struct Vector3 centerAxis;
quatMultVector(&cylinderTransform->rotation, &gUp, &centerAxis);
@ -182,6 +326,39 @@ int collisionCylinderCollideQuad(void* data, struct Transform* cylinderTransform
return output->contactCount > 0;
}
struct CollisionEdge edge;
struct Vector3 edgeDirection;
if (edgesToCheck & (1 << 0)) {
edge.origin = quad->corner;
edge.direction = quad->edgeB;
edge.length = quad->edgeBLength;
vector3Negate(&quad->edgeA, &edgeDirection);
collisionCylinderEdge(cylinder, cylinderTransform, &centerAxis, normalDotProduct, 5, &edge, &edgeDirection, output);
}
if (edgesToCheck & (1 << 1)) {
edge.origin = quad->corner;
edge.direction = quad->edgeA;
edge.length = quad->edgeALength;
vector3Negate(&quad->edgeB, &edgeDirection);
collisionCylinderEdge(cylinder, cylinderTransform, &centerAxis, normalDotProduct, 8, &edge, &edgeDirection, output);
}
if (edgesToCheck & (1 << 2)) {
vector3AddScaled(&quad->corner, &quad->edgeA, quad->edgeALength, &edge.origin);
edge.direction = quad->edgeB;
edge.length = quad->edgeBLength;
collisionCylinderEdge(cylinder, cylinderTransform, &centerAxis, normalDotProduct, 11, &edge, &edgeDirection, output);
}
if (edgesToCheck & (1 << 3)) {
vector3AddScaled(&quad->corner, &quad->edgeB, quad->edgeBLength, &edge.origin);
edge.direction = quad->edgeA;
edge.length = quad->edgeALength;
collisionCylinderEdge(cylinder, cylinderTransform, &centerAxis, normalDotProduct, 14, &edge, &edgeDirection, output);
}
// TODO check edges and points of quad
return 0;

View file

@ -107,12 +107,6 @@ char secondOtherAxis[] = {
#define ID_FROM_AXIS_DIRS(positiveX, positiveY, positiveZ) (((positiveX) ? 1 : 0) | ((positiveY) ? 2 : 0) | ((positiveZ) ? 4 : 0))
#define ID_SEGEMENT_FROM_AXIS(axisNumber, isPositive) ((isPositive) ? 0 : (1 << axisNumber))
struct CollisionEdge {
struct Vector3 origin;
struct Vector3 direction;
float length;
};
// contactPoint(Pa, Da, Pb, Db)
// offset = Pa - Pb
// Dota = Da * offset

View file

@ -8,6 +8,12 @@
#define POINT_NO_OVERLAP -1
struct CollisionEdge {
struct Vector3 origin;
struct Vector3 direction;
float length;
};
struct CollisionQuad {
struct Vector3 corner;
struct Vector3 edgeA;