5555 dandistine
5656
5757 Changes:
58- v1.0 : Here we go, 3D stuff but fast! (ish)
58+ v1.00 : Here we go, 3D stuff but fast! (ish)
5959 +CreateCube() - Creates a 6-face fully defined cuboid of a set size (with optional offset)
60+ v1.01: +CreateSanityCube() - stops insanity
61+ +Rudimentary Camera
62+ +Made OBJ file loader convert to LH on load
6063*/
6164
6265
@@ -496,11 +499,11 @@ namespace olc
496499 identity ();
497500 auto & me = (*this );
498501 T invFOV = T (1 ) / tan (fov * T (0.5 ));
499- me (0 , 0 ) = ratio * invFOV ;
502+ me (0 , 0 ) = -invFOV / ratio ;
500503 me (1 , 1 ) = invFOV;
501- me (2 , 2 ) = farplane / (farplane - nearplane);
502- me (3 , 2 ) = (- farplane * nearplane) / (farplane - nearplane);
503- me (2 , 3 ) = T (1 );
504+ me (2 , 2 ) = - farplane / (farplane - nearplane);
505+ me (3 , 2 ) = -( farplane * nearplane) / (farplane - nearplane);
506+ me (2 , 3 ) = T (- 1 );
504507 me (3 , 3 ) = T (0 );
505508 }
506509
@@ -675,6 +678,62 @@ namespace olc::utils::hw3d
675678 olc::DecalStructure layout = olc::DecalStructure::LIST ;
676679 };
677680
681+
682+ olc::utils::hw3d::mesh CreateSanityCube ()
683+ {
684+ olc::utils::hw3d::mesh m;
685+
686+ // South
687+ m.pos .push_back ({ 0 ,0 ,0 }); m.norm .push_back ({ 0 , 0 , -1 , 0 }); m.uv .push_back ({ 0.25 , 0.5 }); m.col .push_back (olc::WHITE );
688+ m.pos .push_back ({ 1 ,0 ,0 }); m.norm .push_back ({ 0 , 0 , -1 , 0 }); m.uv .push_back ({ 0.5 , 0.5 }); m.col .push_back (olc::WHITE );
689+ m.pos .push_back ({ 1 ,1 ,0 }); m.norm .push_back ({ 0 , 0 , -1 , 0 }); m.uv .push_back ({ 0.5 , 0.25 }); m.col .push_back (olc::WHITE );
690+ m.pos .push_back ({ 0 ,0 ,0 }); m.norm .push_back ({ 0 , 0 , -1 , 0 }); m.uv .push_back ({ 0.25 , 0.5 }); m.col .push_back (olc::WHITE );
691+ m.pos .push_back ({ 1 ,1 ,0 }); m.norm .push_back ({ 0 , 0 , -1 , 0 }); m.uv .push_back ({ 0.5 , 0.25 }); m.col .push_back (olc::WHITE );
692+ m.pos .push_back ({ 0 ,1 ,0 }); m.norm .push_back ({ 0 , 0 , -1 , 0 }); m.uv .push_back ({ 0.25 , 0.25 }); m.col .push_back (olc::WHITE );
693+
694+ // East
695+ m.pos .push_back ({ 1 ,0 ,0 }); m.norm .push_back ({ 1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.5 }); m.col .push_back (olc::WHITE );
696+ m.pos .push_back ({ 1 ,0 ,1 }); m.norm .push_back ({ 1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.75 , 0.5 }); m.col .push_back (olc::WHITE );
697+ m.pos .push_back ({ 1 ,1 ,1 }); m.norm .push_back ({ 1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.75 , 0.25 }); m.col .push_back (olc::WHITE );
698+ m.pos .push_back ({ 1 ,0 ,0 }); m.norm .push_back ({ 1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.5 }); m.col .push_back (olc::WHITE );
699+ m.pos .push_back ({ 1 ,1 ,1 }); m.norm .push_back ({ 1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.75 , 0.25 }); m.col .push_back (olc::WHITE );
700+ m.pos .push_back ({ 1 ,1 ,0 }); m.norm .push_back ({ 1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.25 }); m.col .push_back (olc::WHITE );
701+
702+ // North
703+ m.pos .push_back ({ 1 ,0 ,1 }); m.norm .push_back ({ 0 , 0 , 1 , 0 }); m.uv .push_back ({ 0.75 , 0.5 }); m.col .push_back (olc::WHITE );
704+ m.pos .push_back ({ 0 ,0 ,1 }); m.norm .push_back ({ 0 , 0 , 1 , 0 }); m.uv .push_back ({ 1.0 , 0.5 }); m.col .push_back (olc::WHITE );
705+ m.pos .push_back ({ 0 ,1 ,1 }); m.norm .push_back ({ 0 , 0 , 1 , 0 }); m.uv .push_back ({ 1.0 , 0.25 }); m.col .push_back (olc::WHITE );
706+ m.pos .push_back ({ 1 ,0 ,1 }); m.norm .push_back ({ 0 , 0 , 1 , 0 }); m.uv .push_back ({ 0.75 , 0.5 }); m.col .push_back (olc::WHITE );
707+ m.pos .push_back ({ 0 ,1 ,1 }); m.norm .push_back ({ 0 , 0 , 1 , 0 }); m.uv .push_back ({ 1.0 , 0.25 }); m.col .push_back (olc::WHITE );
708+ m.pos .push_back ({ 1 ,1 ,1 }); m.norm .push_back ({ 0 , 0 , 1 , 0 }); m.uv .push_back ({ 0.75 , 0.25 }); m.col .push_back (olc::WHITE );
709+
710+ // West
711+ m.pos .push_back ({ 0 ,0 ,1 }); m.norm .push_back ({ -1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.0 , 0.5 }); m.col .push_back (olc::WHITE );
712+ m.pos .push_back ({ 0 ,0 ,0 }); m.norm .push_back ({ -1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.5 }); m.col .push_back (olc::WHITE );
713+ m.pos .push_back ({ 0 ,1 ,0 }); m.norm .push_back ({ -1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.25 }); m.col .push_back (olc::WHITE );
714+ m.pos .push_back ({ 0 ,0 ,1 }); m.norm .push_back ({ -1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.0 , 0.5 }); m.col .push_back (olc::WHITE );
715+ m.pos .push_back ({ 0 ,1 ,0 }); m.norm .push_back ({ -1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.25 }); m.col .push_back (olc::WHITE );
716+ m.pos .push_back ({ 0 ,1 ,1 }); m.norm .push_back ({ -1 , 0 , 0 , 0 }); m.uv .push_back ({ 0.0 , 0.25 }); m.col .push_back (olc::WHITE );
717+
718+ // Top
719+ m.pos .push_back ({ 0 ,1 ,0 }); m.norm .push_back ({ 0 , 1 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.25 }); m.col .push_back (olc::WHITE );
720+ m.pos .push_back ({ 1 ,1 ,0 }); m.norm .push_back ({ 0 , 1 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.25 }); m.col .push_back (olc::WHITE );
721+ m.pos .push_back ({ 1 ,1 ,1 }); m.norm .push_back ({ 0 , 1 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.0 }); m.col .push_back (olc::WHITE );
722+ m.pos .push_back ({ 0 ,1 ,0 }); m.norm .push_back ({ 0 , 1 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.25 }); m.col .push_back (olc::WHITE );
723+ m.pos .push_back ({ 1 ,1 ,1 }); m.norm .push_back ({ 0 , 1 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.0 }); m.col .push_back (olc::WHITE );
724+ m.pos .push_back ({ 0 ,1 ,1 }); m.norm .push_back ({ 0 , 1 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.0 }); m.col .push_back (olc::WHITE );
725+
726+ // Bottom
727+ m.pos .push_back ({ 0 ,0 ,1 }); m.norm .push_back ({ 0 , -1 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.75 }); m.col .push_back (olc::WHITE );
728+ m.pos .push_back ({ 1 ,0 ,1 }); m.norm .push_back ({ 0 , -1 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.75 }); m.col .push_back (olc::WHITE );
729+ m.pos .push_back ({ 1 ,0 ,0 }); m.norm .push_back ({ 0 , -1 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.5 }); m.col .push_back (olc::WHITE );
730+ m.pos .push_back ({ 0 ,0 ,1 }); m.norm .push_back ({ 0 , -1 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.75 }); m.col .push_back (olc::WHITE );
731+ m.pos .push_back ({ 1 ,0 ,0 }); m.norm .push_back ({ 0 , -1 , 0 , 0 }); m.uv .push_back ({ 0.5 , 0.5 }); m.col .push_back (olc::WHITE );
732+ m.pos .push_back ({ 0 ,0 ,0 }); m.norm .push_back ({ 0 , -1 , 0 , 0 }); m.uv .push_back ({ 0.25 , 0.5 }); m.col .push_back (olc::WHITE );
733+
734+ return m;
735+ }
736+
678737 olc::utils::hw3d::mesh CreateCube (const olc::vf3d& vSize, const olc::vf3d& vOffset = { 0 ,0 ,0 })
679738 {
680739 olc::utils::hw3d::mesh m;
@@ -782,13 +841,13 @@ namespace olc::utils::hw3d
782841 {
783842 // Line is a 3D normal
784843 s >> junk >> junk >> x >> y >> z;
785- norms.push_back ({ x, y, z });
844+ norms.push_back ({ - x, y, z });
786845 }
787846 else
788847 {
789848 // Line is a 3D vertex
790849 s >> junk >> x >> y >> z;
791- verts.push_back ({ x, y, z });
850+ verts.push_back ({ - x, y, z });
792851 }
793852 }
794853
@@ -829,10 +888,13 @@ namespace olc::utils::hw3d
829888 }
830889
831890 // Process into mesh
832- for (const auto & face : faces)
891+ for (auto & face : faces)
833892 {
834893 if (face.size () == 3 )
835894 {
895+
896+ // std::reverse(face.begin(), face.end());
897+
836898 // Triangle
837899 for (const auto & index : face)
838900 {
@@ -868,4 +930,174 @@ namespace olc::utils::hw3d
868930 return m;
869931 }
870932
933+
934+
935+ class Camera3D
936+ {
937+ public:
938+ Camera3D ()
939+ {
940+ vecPosition = &vecLocalPosition;
941+ vecTarget = &vecLocalTarget;
942+ RegenerateProjectionMatrix ();
943+ RegenerateViewMatrix ();
944+ }
945+
946+ protected:
947+
948+
949+
950+ olc::vf3d* vecPosition = nullptr ;
951+ olc::vf3d vecLocalPosition = { 0 ,0 ,0 };
952+ olc::vf3d* vecTarget = nullptr ;
953+ olc::vf3d vecLocalTarget = { 0 ,0 ,1 };
954+
955+ olc::mf4d matView;
956+ olc::vf3d vecViewUp;
957+ olc::vf3d vecViewForward;
958+ olc::vf3d vecViewRight;
959+
960+ olc::mf4d matProjection;
961+ float fProjection_FieldOfView = 3 .14159f ;
962+ float fProjection_AspectRatio = 1 .333333f ;
963+ float fProjection_NearPlane = 0 .1f ;
964+ float fProjection_FarPlane = 1000 .0f ;
965+
966+ void RegenerateProjectionMatrix ()
967+ {
968+ matProjection.projection (
969+ fProjection_FieldOfView ,
970+ fProjection_AspectRatio ,
971+ fProjection_NearPlane ,
972+ fProjection_FarPlane
973+ );
974+ }
975+
976+ void RegenerateViewMatrix ()
977+ {
978+ // Reframe Coordinate System
979+ const auto & pos = GetPosition ();
980+ vecViewForward = (GetTarget () - pos).norm ();
981+ vecViewUp = (olc::vf3d (0 .0f , 1 .0f , 0.0 ) - (olc::vf3d (0 .0f , 1 .0f , 0 .0f ).dot (vecViewForward) * vecViewForward)).norm ();
982+ vecViewRight = vecViewUp.cross (vecViewForward);
983+
984+ // Manual "Point-At" Matrix
985+ matView (0 ,0 ) = vecViewRight.x ; matView (0 ,1 ) = vecViewRight.y ; matView (0 ,2 ) = vecViewRight.z ; matView (0 ,3 ) = 0 .0f ;
986+ matView (1 ,0 ) = vecViewUp.x ; matView (1 ,1 ) = vecViewUp.y ; matView (1 ,2 ) = vecViewUp.z ; matView (1 ,3 ) = 0 .0f ;
987+ matView (2 ,0 ) = vecViewForward.x ; matView (2 ,1 ) = vecViewForward.y ; matView (2 ,2 ) = vecViewForward.z ; matView (2 ,3 ) = 0 .0f ;
988+ matView (3 ,0 ) = pos.x ; matView (3 ,1 ) = pos.y ; matView (3 ,2 ) = pos.z ; matView (3 ,3 ) = 1 .0f ;
989+
990+ // matView(0, 0) = vecViewRight.x; matView(1, 0) = vecViewRight.y; matView(2, 0) = vecViewRight.z; matView(3, 0) = 0.0f;
991+ // matView(0, 1) = vecViewUp.x; matView(1, 1) = vecViewUp.y; matView(2, 1) = vecViewUp.z; matView(3, 1) = 0.0f;
992+ // matView(0, 2) = vecViewForward.x; matView(1, 2) = vecViewForward.y; matView(2, 2) = vecViewForward.z; matView(3, 2) = 0.0f;
993+ // matView(0, 3) = pos.x; matView(1, 3) = pos.y; matView(2, 3) = pos.z; matView(3, 3) = 1.0f;
994+
995+
996+
997+ // "Look-At" Matrix
998+ matView = matView.quickinvert ();
999+ }
1000+
1001+ public:
1002+ const olc::mf4d& GetProjectionMatrix () const
1003+ {
1004+ return matProjection;
1005+ }
1006+
1007+ const olc::mf4d& GetViewMatrix () const
1008+ {
1009+ return matView;
1010+ }
1011+
1012+ const olc::vf3d& GetViewUp () const
1013+ {
1014+ return vecViewUp;
1015+ }
1016+
1017+ const olc::vf3d& GetViewRight () const
1018+ {
1019+ return vecViewRight;
1020+ }
1021+
1022+ const olc::vf3d& GetViewForward () const
1023+ {
1024+ return vecViewForward;
1025+ }
1026+
1027+ inline void SetPosition (olc::vf3d& vPosition)
1028+ {
1029+ vecPosition = &vPosition;
1030+ }
1031+
1032+ inline void SetPosition (const olc::vf3d&& vPosition)
1033+ {
1034+ vecLocalPosition = vPosition;
1035+ vecPosition = &vecLocalPosition;
1036+ }
1037+
1038+ inline void SetPosition (const float x, const float y, const float z)
1039+ {
1040+ SetPosition ({ x, y, z });
1041+ }
1042+
1043+ const olc::vf3d& GetPosition () const
1044+ {
1045+ return *vecPosition;
1046+ }
1047+
1048+
1049+ inline void SetTarget (olc::vf3d& vTarget)
1050+ {
1051+ vecTarget = &vTarget;
1052+ }
1053+
1054+ inline void SetTarget (const olc::vf3d&& vTarget)
1055+ {
1056+ vecLocalTarget = vTarget;
1057+ vecTarget = &vecLocalTarget;
1058+ }
1059+
1060+ inline void SetTarget (const float x, const float y, const float z)
1061+ {
1062+ SetTarget ({ x, y, z });
1063+ }
1064+
1065+ const olc::vf3d& GetTarget () const
1066+ {
1067+ return *vecTarget;
1068+ }
1069+
1070+ void Update ()
1071+ {
1072+ RegenerateViewMatrix ();
1073+ }
1074+
1075+
1076+
1077+ void SetFieldOfView (const float fTheta )
1078+ {
1079+ fProjection_FieldOfView = fTheta ;
1080+ RegenerateProjectionMatrix ();
1081+ }
1082+
1083+ void SetAspectRatio (const float fRatio )
1084+ {
1085+ fProjection_AspectRatio = fRatio ;
1086+ RegenerateProjectionMatrix ();
1087+ }
1088+
1089+ void SetClippingPlanes (const float fNear , const float fFar )
1090+ {
1091+ fProjection_NearPlane = fNear ;
1092+ fProjection_FarPlane = fFar ;
1093+ RegenerateProjectionMatrix ();
1094+ }
1095+
1096+
1097+
1098+
1099+ protected:
1100+
1101+ };
1102+
8711103}
0 commit comments