Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
collision.h File Reference

Go to the source code of this file.

Functions

s32 test_ray_zones (f32 startX, f32 startY, f32 startZ, f32 dirX, f32 dirY, f32 dirZ, f32 *hitX, f32 *hitY, f32 *hitZ, f32 *hitDepth, f32 *nx, f32 *ny, f32 *nz)
 
s32 test_ray_colliders (s32 ignoreFlags, f32 startX, f32 startY, f32 startZ, f32 dirX, f32 dirY, f32 dirZ, f32 *hitX, f32 *hitY, f32 *hitZ, f32 *hitDepth, f32 *hitNx, f32 *hitNy, f32 *hitNz)
 
s32 test_ray_entities (f32 startX, f32 startY, f32 startZ, f32 dirX, f32 dirY, f32 dirZ, f32 *hitX, f32 *hitY, f32 *hitZ, f32 *hitDepth, f32 *hitNx, f32 *hitNy, f32 *hitNz)
 Test a general ray from a given starting position and direction against all entities.
 

Function Documentation

◆ test_ray_zones()

s32 test_ray_zones ( f32 startX,
f32 startY,
f32 startZ,
f32 dirX,
f32 dirY,
f32 dirZ,
f32 * hitX,
f32 * hitY,
f32 * hitZ,
f32 * hitDepth,
f32 * nx,
f32 * ny,
f32 * nz )

Definition at line 866 of file collision.c.

867 {
868 Collider* collider;
869 CollisionData* collisionData;
870 ColliderTriangle* triangle;
871 s32 i, j;
872 s32 colliderID;
873
874 collisionData = &gZoneCollisionData;
875 gCollisionRayDirX = dirX;
876 gCollisionRayDirY = dirY;
877 gCollisionRayDirZ = dirZ;
878 gCollisionRayStartX = startX;
879 gCollisionRayStartY = startY;
880 gCollisionRayStartZ = startZ;
881 gCollisionRayLength = *hitDepth;
882 colliderID = NO_COLLIDER;
883
884 for (i = 0; i < collisionData->numColliders; i++) {
885 collider = &collisionData->colliderList[i];
886
887 if (collider->flags & COLLIDER_FLAG_IGNORE_PLAYER)
888 continue;
889
890 if (collider->numTriangles == 0 || collider->aabb == NULL)
891 continue;
892
893 triangle = collider->triangleTable;
894 for (j = 0; j < collider->numTriangles; j++) {
895 if (test_ray_triangle_down(triangle++, collisionData->vertices)) {
896 colliderID = i;
897 }
898 }
899 }
900
901 if (colliderID > NO_COLLIDER) {
902 *hitX = gCollisionPointX;
903 *hitY = gCollisionPointY;
904 *hitZ = gCollisionPointZ;
905 *hitDepth = gCollisionRayLength;
906 *hitNx = gCollisionNormalX;
907 *hitNy = gCollisionNormalY;
908 *hitNz = gCollisionNormalZ;
909 return colliderID;
910 } else {
911 return colliderID;
912 }
913}
BSS f32 gCollisionNormalY
Definition collision.c:49
BSS f32 gCollisionRayStartZ
Definition collision.c:40
BSS f32 gCollisionNormalX
Definition collision.c:48
CollisionData gZoneCollisionData
Definition collision.c:36
BSS f32 gCollisionNormalZ
Definition collision.c:50
BSS f32 gCollisionPointX
Definition collision.c:44
BSS f32 gCollisionPointZ
Definition collision.c:46
BSS f32 gCollisionRayStartY
Definition collision.c:39
BSS f32 gCollisionRayLength
Definition collision.c:47
BSS f32 gCollisionPointY
Definition collision.c:45
BSS f32 gCollisionRayDirX
Definition collision.c:41
s32 test_ray_triangle_down(ColliderTriangle *triangle, Vec3f *vertices)
Definition collision.c:602
BSS f32 gCollisionRayStartX
Definition collision.c:38
BSS f32 gCollisionRayDirZ
Definition collision.c:43
BSS f32 gCollisionRayDirY
Definition collision.c:42
Collider * colliderList
struct ColliderTriangle * triangleTable
@ COLLIDER_FLAG_IGNORE_PLAYER
Definition enums.h:4696
#define NO_COLLIDER
Definition macros.h:156

◆ test_ray_colliders()

s32 test_ray_colliders ( s32 ignoreFlags,
f32 startX,
f32 startY,
f32 startZ,
f32 dirX,
f32 dirY,
f32 dirZ,
f32 * hitX,
f32 * hitY,
f32 * hitZ,
f32 * hitDepth,
f32 * hitNx,
f32 * hitNy,
f32 * hitNz )

Definition at line 768 of file collision.c.

769 {
770 Collider* collider;
771 CollisionData* collisionData;
772 ColliderTriangle* triangle;
773 s32 i, j;
774 s32 colliderID;
775 f32 min_x, min_y, min_z, max_x, max_y, max_z;
776
777 if (dirX == 0 && dirY == 0 && dirZ == 0) {
778 return 0;
779 }
780
781 collisionData = &gCollisionData;
782 gCollisionRayDirX = dirX;
783 gCollisionRayDirY = dirY;
784 gCollisionRayDirZ = dirZ;
785 gCollisionRayStartX = startX;
786 gCollisionRayStartY = startY;
787 gCollisionRayStartZ = startZ;
788 gCollisionRayLength = *hitDepth;
789 colliderID = NO_COLLIDER;
790
791 if (dirX < 0) {
792 min_x = startX + dirX * gCollisionRayLength;
793 max_x = startX;
794 } else {
795 min_x = startX;
796 max_x = startX + dirX * gCollisionRayLength;
797 }
798
799 if (dirY < 0) {
800 min_y = startY + dirY * gCollisionRayLength;
801 max_y = startY;
802 } else {
803 min_y = startY;
804 max_y = startY + dirY * gCollisionRayLength;
805 }
806
807 if (dirZ < 0) {
808 min_z = startZ + dirZ * gCollisionRayLength;
809 max_z = startZ;
810 } else {
811 min_z = startZ;
812 max_z = startZ + dirZ * gCollisionRayLength;
813 }
814
815 for (i = 0; i < collisionData->numColliders; i++) {
816 collider = &collisionData->colliderList[i];
817
818 if ((collider->flags & ignoreFlags) ||
819 collider->numTriangles == 0 ||
820 max_x < collider->aabb->min.x ||
821 min_x > collider->aabb->max.x ||
822 max_z < collider->aabb->min.z ||
823 min_z > collider->aabb->max.z ||
824 max_y < collider->aabb->min.y ||
825 min_y > collider->aabb->max.y)
826 {
827 continue;
828 }
829
830 triangle = collider->triangleTable;
831 if (gCollisionRayDirX == 0 && gCollisionRayDirZ == 0 && gCollisionRayDirY == -1.0) {
832 for (j = 0; j < collider->numTriangles; j++) {
833 if (test_ray_triangle_down(triangle++, collisionData->vertices)) {
834 colliderID = i;
835 }
836 }
837 } else if (gCollisionRayDirY == 0) {
838 for (j = 0; j < collider->numTriangles; j++) {
839 if (test_ray_triangle_horizontal(triangle++, collisionData->vertices)) {
840 colliderID = i;
841 }
842 }
843 } else {
844 for (j = 0; j < collider->numTriangles; j++) {
845 if (test_ray_triangle_general(triangle++, collisionData->vertices)) {
846 colliderID = i;
847 }
848 }
849 }
850 }
851
852 if (colliderID > NO_COLLIDER) {
853 *hitX = gCollisionPointX;
854 *hitY = gCollisionPointY;
855 *hitZ = gCollisionPointZ;
856 *hitDepth = gCollisionRayLength;
857 *hitNx = gCollisionNormalX;
858 *hitNy = gCollisionNormalY;
859 *hitNz = gCollisionNormalZ;
860 return colliderID;
861 } else {
862 return colliderID;
863 }
864}
CollisionData gCollisionData
Definition collision.c:35
s32 test_ray_triangle_general(ColliderTriangle *triangle, Vec3f *vertices)
Definition collision.c:505
s32 test_ray_triangle_horizontal(ColliderTriangle *triangle, Vec3f *vertices)
Definition collision.c:675

◆ test_ray_entities()

s32 test_ray_entities ( f32 startX,
f32 startY,
f32 startZ,
f32 dirX,
f32 dirY,
f32 dirZ,
f32 * hitX,
f32 * hitY,
f32 * hitZ,
f32 * hitDepth,
f32 * hitNx,
f32 * hitNy,
f32 * hitNz )

Test a general ray from a given starting position and direction against all entities.

If one is hit, returns the position and normal of the hit and the length along the ray on the output params. All output params are invalid when a value of NO_COLLIDER is returned.

Parameters
startXorigin x position of the ray
startYorigin y position of the ray
startZorigin z position of the ray
dirXnormalized x direction of the ray
dirYnormalized y direction of the ray
dirZnormalized z direction of the ray
[out]hitXnormalized x position of the hit
[out]hitYnormalized y position of the hit
[out]hitZnormalized z position of the hit
[in,out]hitDepthas input, maximum length of the ray; as output, distance along the ray of the hit
[out]hitNxx normal direction of the hit
[out]hitNyy normal direction of the hit
[out]hitNzz normal direction of the hit
Returns
entity index or NO_COLLIDER is none is hit

Definition at line 947 of file collision.c.

948 {
949 f32 hitDepthDown, hitDepthHoriz;
950 s32 type;
951 s32 i, j;
952 Entity* entity;
953 Matrix4f tempMatrix1;
954 Matrix4f tempMatrix2;
955 Vec3f boxVertices[8];
956 ColliderTriangle entityTriangle;
957 s32 entityIndex;
958 f32 h;
959 f32 aabbX, aabbZ;
960 s32 hasCollision;
961 f32 dist, dist2;
962 ColliderTriangle *triangle = &entityTriangle;
963
964 enum {
965 ENTITY_TEST_ANY = 0,
966 ENTITY_TEST_DOWN = 1,
967 ENTITY_TEST_LATERAL = 2,
968 };
969
970 entityIndex = NO_COLLIDER;
971 type = ENTITY_TEST_ANY;
972 hitDepthDown = hitDepthHoriz = *hitDepth;
973
974 if (dirX == 0 && dirZ == 0 && dirY < 0) {
975 hitDepthHoriz = 0;
976 type = ENTITY_TEST_DOWN;
977 } else if (dirY == 0) {
978 hitDepthDown = 0;
979 type = ENTITY_TEST_LATERAL;
980 }
981
983 triangle->oneSided = TRUE;
984 for (i = 0; i < MAX_ENTITIES; i++) {
985 entity = get_entity_by_index(i);
986
987 if (entity == NULL || (entity->flags & (ENTITY_FLAG_SKIP_UPDATE | ENTITY_FLAG_DISABLE_COLLISION))) {
988 continue;
989 }
990
991 dist = hitDepthHoriz + entity->effectiveSize;
992 if (startX > entity->pos.x + dist || startX < entity->pos.x - dist) {
993 continue;
994 }
995
996 if (startZ > entity->pos.z + dist || startZ < entity->pos.z - dist) {
997 continue;
998 }
999
1000 switch (type) {
1001 case ENTITY_TEST_ANY:
1002 case ENTITY_TEST_DOWN:
1003 dist = entity->pos.y;
1004 dist2 = hitDepthDown + entity->effectiveSize * 2;
1005 if (dist + dist2 < startY || startY < dist - dist2) {
1006 continue;
1007 }
1008 break;
1009 case ENTITY_TEST_LATERAL:
1010 dist = entity->pos.y;
1011 dist2 = entity->effectiveSize * 2;
1012 if (dist + dist2 < startY || startY < dist - dist2) {
1013 continue;
1014 }
1015 break;
1016 }
1017
1018 aabbX = entity->aabb.x / 2;
1019 aabbZ = entity->aabb.z / 2;
1020
1021 boxVertices[1].x = boxVertices[2].x = boxVertices[5].x = boxVertices[6].x = -aabbX;
1022 boxVertices[0].x = boxVertices[3].x = boxVertices[4].x = boxVertices[7].x = aabbX;
1023 boxVertices[0].y = boxVertices[1].y = boxVertices[2].y = boxVertices[3].y = 0;
1024 boxVertices[4].y = boxVertices[5].y = boxVertices[6].y = boxVertices[7].y = entity->aabb.y;
1025 boxVertices[0].z = boxVertices[1].z = boxVertices[4].z = boxVertices[5].z = aabbZ;
1026 boxVertices[2].z = boxVertices[3].z = boxVertices[6].z = boxVertices[7].z = -aabbZ;
1027
1028 guMtxXFMF(entity->inverseTransformMatrix, dirX, dirY, dirZ, &gCollisionRayDirX, &gCollisionRayDirY, &gCollisionRayDirZ);
1029 guMtxXFMF(entity->inverseTransformMatrix, startX - entity->pos.x, startY - entity->pos.y,
1031
1032 for (j = 0; j < 12; j++) {
1033 Vec3f* v1 = triangle->v1 = &boxVertices[gEntityColliderFaces[j].x];
1034 Vec3f* v2 = triangle->v2 = &boxVertices[gEntityColliderFaces[j].y];
1035 Vec3f* v3 = triangle->v3 = &boxVertices[gEntityColliderFaces[j].z];
1036 triangle->e13.x = v3->x - v1->x;
1037 triangle->e13.y = v3->y - v1->y;
1038 triangle->e13.z = v3->z - v1->z;
1039 triangle->e21.x = v1->x - v2->x;
1040 triangle->e21.y = v1->y - v2->y;
1041 triangle->e21.z = v1->z - v2->z;
1042 triangle->e32.x = v2->x - v3->x;
1043 triangle->e32.y = v2->y - v3->y;
1044 triangle->e32.z = v2->z - v3->z;
1045 triangle->normal.x = gEntityColliderNormals[j].x;
1046 triangle->normal.y = gEntityColliderNormals[j].y;
1047 triangle->normal.z = gEntityColliderNormals[j].z;
1048
1049 if (hasCollision = test_ray_triangle_general(&entityTriangle, boxVertices)) {
1050 break;
1051 }
1052 }
1053
1054 if (hasCollision && gCollisionRayLength < *hitDepth) {
1055 entityIndex = i;
1056 *hitDepth = gCollisionRayLength;
1057
1058 switch (type) {
1059 case ENTITY_TEST_ANY:
1060 hitDepthDown = gCollisionRayLength;
1061 hitDepthHoriz = gCollisionRayLength;
1062 break;
1063 case ENTITY_TEST_DOWN:
1064 hitDepthDown = gCollisionRayLength;
1065 break;
1066 case ENTITY_TEST_LATERAL:
1067 hitDepthHoriz = gCollisionRayLength;
1068 break;
1069 }
1070
1071 guRotateF(tempMatrix1, entity->rot.x, 1.0f, 0.0f, 0.0f);
1072 guRotateF(tempMatrix2, entity->rot.z, 0.0f, 0.0f, 1.0f);
1073 guMtxCatF(tempMatrix1, tempMatrix2, tempMatrix1);
1074 guRotateF(tempMatrix2, entity->rot.y, 0.0f, 1.0f, 0.0f);
1075 guMtxCatF(tempMatrix1, tempMatrix2, tempMatrix1);
1076 guTranslateF(tempMatrix2, entity->pos.x, entity->pos.y, entity->pos.z);
1077 guMtxCatF(tempMatrix1, tempMatrix2, tempMatrix1);
1078 guMtxXFMF(tempMatrix1, gCollisionPointX, gCollisionPointY, gCollisionPointZ, hitX, hitY, hitZ);
1079
1081 *hitNx = gCollisionNormalX * h;
1082 *hitNy = gCollisionNormalY * h;
1083 *hitNz = gCollisionNormalZ * h;
1084 }
1085 }
1086
1087 return entityIndex;
1088}
Vec3f gEntityColliderNormals[]
Definition collision.c:63
Vec3s gEntityColliderFaces[]
Definition collision.c:54
f32 Matrix4f[4][4]
Vec3s pos
Definition demo_api.c:17
#define guRotateF
#define sqrtf
#define guTranslateF
#define guMtxCatF
@ ENTITY_FLAG_SKIP_UPDATE
Definition enums.h:2643
@ ENTITY_FLAG_DISABLE_COLLISION
Definition enums.h:2618
Entity * get_entity_by_index(s32 index)
Definition entity.c:530
#define MAX_ENTITIES
Definition macros.h:94
#define SQ(x)
Definition macros.h:166
Matrix4f inverseTransformMatrix
f32 effectiveSize