Skip to content

Commit 7e7939e

Browse files
sinofthetaIan Band
andauthored
Add DrawCapsule(Wires) (#2761)
* Add DrawCapsule & DrawCapsuleWires * Add DrawCapsule & DrawCapsuleWires to example Co-authored-by: Ian Band <ian.r.band@gmail.com>
1 parent c5e8924 commit 7e7939e

File tree

4 files changed

+283
-0
lines changed

4 files changed

+283
-0
lines changed

examples/models/models_geometric_shapes.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ int main(void)
6666
DrawCylinder((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, GOLD);
6767
DrawCylinderWires((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, PINK);
6868

69+
DrawCapsule ((Vector3){-3.0f, 1.5f, -4.0f}, (Vector3){-4.0f, -1.0f, -4.0f}, 1.2f, 8, 8, VIOLET);
70+
DrawCapsuleWires((Vector3){-3.0f, 1.5f, -4.0f}, (Vector3){-4.0f, -1.0f, -4.0f}, 1.2f, 8, 8, PURPLE);
71+
6972
DrawGrid(10, 1.0f); // Draw a grid
7073

7174
EndMode3D();
-11.3 KB
Loading

src/raylib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,8 @@ RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, f
14231423
RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos
14241424
RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
14251425
RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos
1426+
RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos
1427+
RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos
14261428
RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ
14271429
RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
14281430
RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))

src/rmodels.c

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,284 @@ void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, fl
817817
rlEnd();
818818
}
819819

820+
// Draw a capsule with the center of its sphere caps at startPos and endPos
821+
void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)
822+
{
823+
if (slices < 3) slices = 3;
824+
825+
Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
826+
827+
// draw a sphere if start and end points are the same
828+
bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);
829+
if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};
830+
831+
// Construct a basis of the base and the caps:
832+
Vector3 b0 = Vector3Normalize(direction);
833+
Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));
834+
Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));
835+
Vector3 capCenter = endPos;
836+
837+
float baseSliceAngle = (2.0f*PI)/slices;
838+
float baseRingAngle = PI * 0.5 / rings;
839+
840+
rlBegin(RL_TRIANGLES);
841+
rlColor4ub(color.r, color.g, color.b, color.a);
842+
843+
// render both caps
844+
for (int c = 0; c < 2; c++)
845+
{
846+
for (int i = 0; i < rings; i++)
847+
{
848+
for (int j = 0; j < slices; j++)
849+
{
850+
851+
// we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier
852+
853+
// as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))
854+
// as we iterate through the rings they must get smaller by the cos(angle(i))
855+
856+
// compute the four vertices
857+
float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));
858+
float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));
859+
Vector3 w1 = (Vector3){
860+
capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x) * radius,
861+
capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius,
862+
capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z) * radius
863+
};
864+
float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));
865+
float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));
866+
Vector3 w2 = (Vector3){
867+
capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius,
868+
capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius,
869+
capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius
870+
};
871+
872+
float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));
873+
float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));
874+
Vector3 w3 = (Vector3){
875+
capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius,
876+
capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius,
877+
capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius
878+
};
879+
float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));
880+
float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));
881+
Vector3 w4 = (Vector3){
882+
capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius,
883+
capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius,
884+
capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius
885+
};
886+
887+
// make sure cap triangle normals are facing outwards
888+
if(c == 0)
889+
{
890+
rlVertex3f(w1.x, w1.y, w1.z);
891+
rlVertex3f(w2.x, w2.y, w2.z);
892+
rlVertex3f(w3.x, w3.y, w3.z);
893+
894+
rlVertex3f(w2.x, w2.y, w2.z);
895+
rlVertex3f(w4.x, w4.y, w4.z);
896+
rlVertex3f(w3.x, w3.y, w3.z);
897+
}
898+
else
899+
{
900+
rlVertex3f(w1.x, w1.y, w1.z);
901+
rlVertex3f(w3.x, w3.y, w3.z);
902+
rlVertex3f(w2.x, w2.y, w2.z);
903+
904+
rlVertex3f(w2.x, w2.y, w2.z);
905+
rlVertex3f(w3.x, w3.y, w3.z);
906+
rlVertex3f(w4.x, w4.y, w4.z);
907+
}
908+
}
909+
}
910+
capCenter = startPos;
911+
b0 = Vector3Scale(b0, -1.0f);
912+
}
913+
// render middle
914+
if (!sphereCase)
915+
{
916+
for (int j = 0; j < slices; j++)
917+
{
918+
// compute the four vertices
919+
float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;
920+
float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;
921+
Vector3 w1 = {
922+
startPos.x + ringSin1*b1.x + ringCos1*b2.x,
923+
startPos.y + ringSin1*b1.y + ringCos1*b2.y,
924+
startPos.z + ringSin1*b1.z + ringCos1*b2.z
925+
};
926+
float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;
927+
float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;
928+
Vector3 w2 = {
929+
startPos.x + ringSin2*b1.x + ringCos2*b2.x,
930+
startPos.y + ringSin2*b1.y + ringCos2*b2.y,
931+
startPos.z + ringSin2*b1.z + ringCos2*b2.z
932+
};
933+
934+
float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;
935+
float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;
936+
Vector3 w3 = {
937+
endPos.x + ringSin3*b1.x + ringCos3*b2.x,
938+
endPos.y + ringSin3*b1.y + ringCos3*b2.y,
939+
endPos.z + ringSin3*b1.z + ringCos3*b2.z
940+
};
941+
float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;
942+
float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;
943+
Vector3 w4 = {
944+
endPos.x + ringSin4*b1.x + ringCos4*b2.x,
945+
endPos.y + ringSin4*b1.y + ringCos4*b2.y,
946+
endPos.z + ringSin4*b1.z + ringCos4*b2.z
947+
};
948+
// w2 x.-----------x startPos
949+
rlVertex3f(w1.x, w1.y, w1.z); // | |\'. T0 /
950+
rlVertex3f(w2.x, w2.y, w2.z); // T1 | \ '. /
951+
rlVertex3f(w3.x, w3.y, w3.z); // | |T \ '. /
952+
// | 2 \ T 'x w1
953+
rlVertex3f(w2.x, w2.y, w2.z); // | w4 x.---\-1-|---x endPos
954+
rlVertex3f(w4.x, w4.y, w4.z); // T2 '. \ |T3/
955+
rlVertex3f(w3.x, w3.y, w3.z); // | '. \ | /
956+
// '.\|/
957+
// 'x w3
958+
}
959+
}
960+
rlEnd();
961+
}
962+
963+
// Draw capsule wires with the center of its sphere caps at startPos and endPos
964+
void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)
965+
{
966+
if (slices < 3) slices = 3;
967+
968+
Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
969+
970+
// draw a sphere if start and end points are the same
971+
bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);
972+
if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};
973+
974+
// Construct a basis of the base and the caps:
975+
Vector3 b0 = Vector3Normalize(direction);
976+
Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));
977+
Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));
978+
Vector3 capCenter = endPos;
979+
980+
float baseSliceAngle = (2.0f*PI)/slices;
981+
float baseRingAngle = PI * 0.5 / rings;
982+
983+
rlBegin(RL_LINES);
984+
rlColor4ub(color.r, color.g, color.b, color.a);
985+
986+
// render both caps
987+
for (int c = 0; c < 2; c++)
988+
{
989+
for (int i = 0; i < rings; i++)
990+
{
991+
for (int j = 0; j < slices; j++)
992+
{
993+
994+
// we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier
995+
996+
// as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))
997+
// as we iterate through the rings they must get smaller by the cos(angle(i))
998+
999+
// compute the four vertices
1000+
float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));
1001+
float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));
1002+
Vector3 w1 = (Vector3){
1003+
capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x) * radius,
1004+
capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius,
1005+
capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z) * radius
1006+
};
1007+
float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));
1008+
float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));
1009+
Vector3 w2 = (Vector3){
1010+
capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius,
1011+
capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius,
1012+
capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius
1013+
};
1014+
1015+
float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));
1016+
float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));
1017+
Vector3 w3 = (Vector3){
1018+
capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius,
1019+
capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius,
1020+
capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius
1021+
};
1022+
float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));
1023+
float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));
1024+
Vector3 w4 = (Vector3){
1025+
capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius,
1026+
capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius,
1027+
capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius
1028+
};
1029+
1030+
rlVertex3f(w1.x, w1.y, w1.z);
1031+
rlVertex3f(w2.x, w2.y, w2.z);
1032+
1033+
rlVertex3f(w2.x, w2.y, w2.z);
1034+
rlVertex3f(w3.x, w3.y, w3.z);
1035+
1036+
rlVertex3f(w1.x, w1.y, w1.z);
1037+
rlVertex3f(w3.x, w3.y, w3.z);
1038+
1039+
rlVertex3f(w2.x, w2.y, w2.z);
1040+
rlVertex3f(w4.x, w4.y, w4.z);
1041+
1042+
rlVertex3f(w3.x, w3.y, w3.z);
1043+
rlVertex3f(w4.x, w4.y, w4.z);
1044+
}
1045+
}
1046+
capCenter = startPos;
1047+
b0 = Vector3Scale(b0, -1.0f);
1048+
}
1049+
// render middle
1050+
if (!sphereCase)
1051+
{
1052+
for (int j = 0; j < slices; j++)
1053+
{
1054+
// compute the four vertices
1055+
float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;
1056+
float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;
1057+
Vector3 w1 = {
1058+
startPos.x + ringSin1*b1.x + ringCos1*b2.x,
1059+
startPos.y + ringSin1*b1.y + ringCos1*b2.y,
1060+
startPos.z + ringSin1*b1.z + ringCos1*b2.z
1061+
};
1062+
float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;
1063+
float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;
1064+
Vector3 w2 = {
1065+
startPos.x + ringSin2*b1.x + ringCos2*b2.x,
1066+
startPos.y + ringSin2*b1.y + ringCos2*b2.y,
1067+
startPos.z + ringSin2*b1.z + ringCos2*b2.z
1068+
};
1069+
1070+
float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;
1071+
float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;
1072+
Vector3 w3 = {
1073+
endPos.x + ringSin3*b1.x + ringCos3*b2.x,
1074+
endPos.y + ringSin3*b1.y + ringCos3*b2.y,
1075+
endPos.z + ringSin3*b1.z + ringCos3*b2.z
1076+
};
1077+
float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;
1078+
float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;
1079+
Vector3 w4 = {
1080+
endPos.x + ringSin4*b1.x + ringCos4*b2.x,
1081+
endPos.y + ringSin4*b1.y + ringCos4*b2.y,
1082+
endPos.z + ringSin4*b1.z + ringCos4*b2.z
1083+
};
1084+
1085+
rlVertex3f(w1.x, w1.y, w1.z);
1086+
rlVertex3f(w3.x, w3.y, w3.z);
1087+
1088+
rlVertex3f(w2.x, w2.y, w2.z);
1089+
rlVertex3f(w4.x, w4.y, w4.z);
1090+
1091+
rlVertex3f(w2.x, w2.y, w2.z);
1092+
rlVertex3f(w3.x, w3.y, w3.z);
1093+
}
1094+
}
1095+
rlEnd();
1096+
}
1097+
8201098
// Draw a plane
8211099
void DrawPlane(Vector3 centerPos, Vector2 size, Color color)
8221100
{

0 commit comments

Comments
 (0)