Просмотр исходного кода

add orthographic toggle and mesh cycling to prepare for branch to core_3d_camera_view simplification

pull/5320/head
iann 3 месяцев назад
Родитель
Сommit
e552a83ee9
3 измененных файлов: 352 добавлений и 91 удалений
  1. +157
    -91
      examples/core/core_3d_fixed_function_didactic.c
  2. +22
    -0
      examples/core/resources/models/unit_cube.obj
  3. +173
    -0
      examples/core/resources/models/unit_sphere.obj

+ 157
- 91
examples/core/core_3d_fixed_function_didactic.c Просмотреть файл

@ -21,7 +21,7 @@
*
********************************************************************************************/
// TODO list:
// 1. add proper clipping to the target meshes to show intuition there (e.g. move mesh out of clip planes or allow moving the main camera's target away from the meshes)
// 1. finish proper clipping toggle with some sort of visibility mask to geometry outside clip volume (also enable moving mesh out of clip planes more clear/allow moving the main camera's target away from the meshes)
// 2. improve didactic annotations (ideally with spatial labeling rather than simple flat screen overlay)
// 3. improve code didactic, code should read in order of fixed function staging... difficult but long term goal...
// 4. add scripted toggling/navigation of ordered fixed function staging visualization (a "play button"-like thing)
@ -53,15 +53,19 @@ typedef unsigned short Triangle[3];
enum Flags
{
FLAG_NDC = 1u<<0,
FLAG_REFLECT_Y = 1u<<1,
FLAG_ASPECT = 1u<<2,
FLAG_REFLECT_Y = 1u<<1, FLAG_ASPECT = 1u<<2,
FLAG_PERSPECTIVE_CORRECT = 1u<<3,
FLAG_PAUSE = 1u<<4,
FLAG_COLOR_MODE = 1u<<5,
FLAG_TEXTURE_MODE = 1u<<6
FLAG_COLOR_MODE = 1u<<5, FLAG_TEXTURE_MODE = 1u<<6,
FLAG_JUGEMU = 1u<<7,
FLAG_ORTHO = 1u<<8,
FLAG_CLIP = 1u<<9,
GEN_CUBE = 1u<<10, LOAD_CUBE = 1u<<11,
GEN_SPHERE = 1u<<12, LOAD_SPHERE = 1u<<13,
GEN_KNOT = 1u<<14
};
static unsigned int gflags = FLAG_ASPECT | FLAG_COLOR_MODE;
static unsigned int gflags = FLAG_ASPECT | FLAG_COLOR_MODE | FLAG_JUGEMU | GEN_CUBE;
#define NDC_SPACE() ((gflags & FLAG_NDC) != 0)
#define REFLECT_Y() ((gflags & FLAG_REFLECT_Y) != 0)
@ -70,11 +74,24 @@ static unsigned int gflags = FLAG_ASPECT | FLAG_COLOR_MODE;
#define PAUSED() ((gflags & FLAG_PAUSE) != 0)
#define COLOR_MODE() ((gflags & FLAG_COLOR_MODE) != 0)
#define TEXTURE_MODE() ((gflags & FLAG_TEXTURE_MODE) != 0)
#define JUGEMU_MODE() ((gflags & FLAG_JUGEMU) != 0)
#define ORTHO_MODE() ((gflags & FLAG_ORTHO) != 0)
#define CLIP_MODE() ((gflags & FLAG_CLIP) != 0)
#define TOGGLE(K, F) do { if (IsKeyPressed(K)) { gflags ^= (F); } } while (0)
static unsigned int targetMesh = 0;
#define NUM_MODELS 5
#define TARGET_GEN_CUBE() ((gflags & GEN_CUBE) != 0)
#define TARGET_LOAD_CUBE() ((gflags & LOAD_CUBE) != 0)
#define TARGET_GEN_SPHERE() ((gflags & GEN_SPHERE) != 0)
#define TARGET_LOAD_SPHERE() ((gflags & LOAD_SPHERE) != 0)
#define TARGET_GEN_KNOT() ((gflags & GEN_KNOT) != 0)
#define CYCLE_MESH(K, I, F) do { if (IsKeyPressed(K)) { targetMesh = (I); gflags = (gflags & ~(GEN_CUBE|LOAD_CUBE|GEN_SPHERE|LOAD_SPHERE|GEN_KNOT)) | (F); } } while (0)
static int fontSize = 20;
static float angularVelocity = 1.25f;
static float fovy = 60.0f;
static float fovyPerspective = 60.0f;
static float nearPlaneHeightOrthographic = 1.0f;
static float blendScalar = 5.0f;
static Vector3 yAxis = { 0.0f, 1.0f, 0.0f };
static Vector3 modelPos = { 0.0f, 0.0f, 0.0f };
@ -90,7 +107,7 @@ static void DrawModelWiresAndPoints(Model *model, float rotation);
static void DrawNearPlanePoints(Camera3D *main, float aspect, float near, Model *nearPlanePointsModel, Mesh *mesh, float rotation);
static void UpdateSpatialFrame(Camera3D *main, float aspect, float near, float far, Mesh *spatialFrame);
static void DrawSpatialFrame(Mesh spatialFrame);
static void DrawSpatialFrame(Mesh o">*spatialFrame);
static void PerspectiveIncorrectCapture(Camera3D *main, float aspect, float near, Mesh *mesh, Texture2D meshTexture, float rotation);
static void PerspectiveCorrectCapture(Camera3D *main, Model *model, Texture2D meshTexture, Texture2D *perspectiveCorrectTexture, float rotation);
@ -104,6 +121,7 @@ static Vector3 Intersect(Camera3D *main, float near, Vector3 worldCoord);
static float SpaceBlendFactor(float dt);
static float AspectBlendFactor(float dt);
static float ReflectBlendFactor(float dt);
static float OrthoBlendFactor(float dt);
//------------------------------------------------------------------------------------
// Program main entry point
@ -116,64 +134,87 @@ int main(void)
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - fixed function didactic");
float near = 1.0f;
float far = 3.0f;
float aspect = (float)GetScreenWidth()/(float)GetScreenHeight();
nearPlaneHeightOrthographic = 2.0f*near*tanf(DEG2RAD*fovyPerspective*0.5f);
float meshRotation = 0.0f;
Camera3D main = { 0 };
main.position = mainPos;
main.target = modelPos;
main.up = yAxis;
main.fovy = fovy;
main.projection = CAMERA_PERSPECTIVE;
main.projection = (ORTHO_MODE())? CAMERA_ORTHOGRAPHIC : CAMERA_PERSPECTIVE;
main.fovy = (ORTHO_MODE())? nearPlaneHeightOrthographic: fovyPerspective;
Camera3D jugemu = (Camera3D){ 0 };
jugemu.position = jugemuPosIso;
jugemu.target = modelPos;
jugemu.up = yAxis;
jugemu.fovy = fovy;
jugemu.fovy = fovyPerspective;
jugemu.projection = CAMERA_PERSPECTIVE;
o">// Model worldModel = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
o">// Image textureImage = GenImageChecked(4, 4, 1, 1, BLACK, WHITE);
o">// Model worldModel = LoadModelFromMesh(GenMeshSphere(0.5f, 8, 8));
o">// Image textureImage = GenImageChecked(16, 16, 1, 1, BLACK, WHITE);
n">Model worldModels[NUM_MODELS] = { 0 };
n">Model ndcModels[NUM_MODELS] = { 0 };
Model nearPlanePointsModels[NUM_MODELS] = { 0 };
n">Texture2D meshTextures[NUM_MODELS] = { 0 };
kt">int textureConfig[NUM_MODELS] = { 4, 4, 16, 16, 32 };
// Model worldModel = LoadModelFromMesh(GenMeshKnot(1.0f, 1.0f, 8, 64));
Model worldModel = LoadModelFromMesh(GenMeshKnot(1.0f, 1.0f, 16, 128));
Image textureImage = GenImageChecked(32, 32, 1, 1, BLACK, WHITE);
for (int i = 0; i < NUM_MODELS; i++)
{
if (i == 0) worldModels[0] = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
if (i == 1) worldModels[1] = LoadModel("resources/models/unit_cube.obj");
if (i == 2) worldModels[2] = LoadModelFromMesh(GenMeshSphere(0.5f, 8, 8));
if (i == 3) worldModels[3] = LoadModel("resources/models/unit_sphere.obj");
if (i == 4) worldModels[4] = LoadModelFromMesh(GenMeshKnot(1.0f, 1.0f, 16, 128));
Texture2D meshTexture = LoadTextureFromImage(textureImage);
UnloadImage(textureImage);
Mesh *worldMesh = &worldModels[i].meshes[0];
if (!worldModel.meshes[0].indices)
{
worldModel.meshes[0].indices = RL_CALLOC(worldModel.meshes[0].vertexCount, sizeof(unsigned short));
for (int i = 0; i < worldModel.meshes[0].vertexCount; i++) worldModel.meshes[0].indices[i] = (unsigned short)i;
worldModel.meshes[0].triangleCount = worldModel.meshes[0].vertexCount/3;
if (!worldMesh->indices)
{
worldMesh->indices = RL_CALLOC(worldMesh->vertexCount, sizeof(unsigned short));
for (int j = 0; j < worldMesh->vertexCount; j++) worldMesh->indices[j] = (unsigned short)j;
worldMesh->triangleCount = worldMesh->vertexCount/3;
}
if (!worldMesh->texcoords)
{
worldMesh->texcoords = (float *)MemAlloc(sizeof(float)*worldMesh->vertexCount*2);
// Demonstrate planar mapping ("reasonable" default): https://en.wikipedia.org/wiki/Planar_projection.
BoundingBox bounds = GetMeshBoundingBox(*worldMesh);
Vector3 extents = Vector3Subtract(bounds.max, bounds.min);
for (int j = 0; j < worldMesh->vertexCount; j++)
{
float x = ((Vector3 *)worldMesh->vertices)[j].x;
float y = ((Vector3 *)worldMesh->vertices)[j].y;
((Vector2 *)worldMesh->texcoords)[j].x = (x - bounds.min.x)/extents.x;
((Vector2 *)worldMesh->texcoords)[j].y = (y - bounds.min.y)/extents.y;
}
}
FillVertexColors(worldMesh);
Image textureImage = GenImageChecked(textureConfig[i], textureConfig[i], 1, 1, BLACK, WHITE);
meshTextures[i] = LoadTextureFromImage(textureImage);
UnloadImage(textureImage);
worldModels[i].materials[0].maps[MATERIAL_MAP_ALBEDO].texture = meshTextures[i];
Mesh ndcMesh = (Mesh){ 0 };
ndcMesh.vertexCount = worldMesh->vertexCount;
ndcMesh.triangleCount = worldMesh->triangleCount;
ndcMesh.vertices = RL_CALLOC(ndcMesh.vertexCount, sizeof(Vector3));
ndcMesh.texcoords = RL_CALLOC(ndcMesh.vertexCount, sizeof(Vector2));
ndcMesh.indices = RL_CALLOC(ndcMesh.triangleCount, sizeof(Triangle));
ndcMesh.colors = RL_CALLOC(ndcMesh.vertexCount, sizeof(Color));
memcpy(ndcMesh.colors, worldMesh->colors, ndcMesh.vertexCount*sizeof(Color));
memcpy(ndcMesh.texcoords, worldMesh->texcoords, ndcMesh.vertexCount*sizeof(Vector2));
memcpy(ndcMesh.indices, worldMesh->indices, ndcMesh.triangleCount*sizeof(Triangle));
ndcModels[i] = LoadModelFromMesh(ndcMesh);
ndcModels[i].materials[0].maps[MATERIAL_MAP_ALBEDO].texture = meshTextures[i];
Mesh nearPlanePoints = (Mesh){ 0 };
nearPlanePoints.vertexCount = worldMesh->triangleCount*3;
nearPlanePoints.vertices = RL_CALLOC(nearPlanePoints.vertexCount, sizeof(Vector3));
nearPlanePointsModels[i] = LoadModelFromMesh(nearPlanePoints);
}
FillVertexColors(&worldModel.meshes[0]);
Mesh ndcMesh = (Mesh){ 0 };
ndcMesh.vertexCount = worldModel.meshes[0].vertexCount;
ndcMesh.triangleCount = worldModel.meshes[0].triangleCount;
ndcMesh.vertices = RL_CALLOC(ndcMesh.vertexCount, sizeof(Vector3));
ndcMesh.texcoords = RL_CALLOC(ndcMesh.vertexCount, sizeof(Vector2));
ndcMesh.indices = RL_CALLOC(ndcMesh.triangleCount, sizeof(Triangle));
ndcMesh.colors = RL_CALLOC(ndcMesh.vertexCount, sizeof(Color));
memcpy(ndcMesh.colors, worldModel.meshes[0].colors, ndcMesh.vertexCount*sizeof(Color));
memcpy(ndcMesh.texcoords, worldModel.meshes[0].texcoords, ndcMesh.vertexCount*sizeof(Vector2));
memcpy(ndcMesh.indices, worldModel.meshes[0].indices, ndcMesh.triangleCount*sizeof(Triangle));
Model ndcModel = LoadModelFromMesh(ndcMesh);
Mesh nearPlanePoints = (Mesh){ 0 };
nearPlanePoints.vertexCount = worldModel.meshes[0].triangleCount*3;
nearPlanePoints.vertices = RL_CALLOC(nearPlanePoints.vertexCount, sizeof(Vector3));
Model nearPlanePointsModel = LoadModelFromMesh(nearPlanePoints);
worldModel.materials[0].maps[MATERIAL_MAP_ALBEDO].texture = meshTexture;
ndcModel.materials[0].maps[MATERIAL_MAP_ALBEDO].texture = meshTexture;
Texture2D perspectiveCorrectTexture = (Texture2D){ 0 };
Mesh spatialFrame = GenMeshCube(1.0f, 1.0f, 1.0f);
@ -189,8 +230,6 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
float far = 3.0f;
float near = 1.0f;
aspect = (float)GetScreenWidth()/(float)GetScreenHeight();
TOGGLE(KEY_N, FLAG_NDC);
if (NDC_SPACE()) TOGGLE(KEY_F, FLAG_REFLECT_Y);
@ -199,32 +238,42 @@ int main(void)
TOGGLE(KEY_SPACE, FLAG_PAUSE);
TOGGLE(KEY_C, FLAG_COLOR_MODE);
TOGGLE(KEY_T, FLAG_TEXTURE_MODE);
TOGGLE(KEY_J, FLAG_JUGEMU);
TOGGLE(KEY_O, FLAG_ORTHO);
TOGGLE(KEY_X, FLAG_CLIP);
CYCLE_MESH(KEY_ONE, 0, GEN_CUBE);
CYCLE_MESH(KEY_TWO, 1, LOAD_CUBE);
CYCLE_MESH(KEY_THREE, 2, GEN_SPHERE);
CYCLE_MESH(KEY_FOUR, 3, LOAD_SPHERE);
CYCLE_MESH(KEY_FIVE, 4, GEN_KNOT);
float sBlend = SpaceBlendFactor(GetFrameTime());
AspectBlendFactor(GetFrameTime());
ReflectBlendFactor(GetFrameTime());
OrthoBlendFactor(GetFrameTime());
if (!PAUSED()) meshRotation -= angularVelocity*GetFrameTime();
OrbitSpace(&jugemu, GetFrameTime());
main.projection = (ORTHO_MODE())? CAMERA_ORTHOGRAPHIC : CAMERA_PERSPECTIVE;
main.fovy = (ORTHO_MODE())? nearPlaneHeightOrthographic : fovyPerspective;
WorldToNDCSpace(&main, aspect, near, far, &worldModels[targetMesh], &ndcModels[targetMesh], meshRotation);
WorldToNDCSpace(&main, aspect, near, far, &worldModel, &ndcModel, meshRotation);
for (int i = 0; i < ndcModel.meshes[0].vertexCount; i++)
for (int i = 0; i < ndcModels[targetMesh].meshes[0].vertexCount; i++)
{
Vector3 *worldVertices = (Vector3 *)worldModel.meshes[0].vertices;
Vector3 *ndcVertices = (Vector3 *)ndcModel.meshes[0].vertices;
Vector3 *worldVertices = (Vector3 *)worldModels[targetMesh].meshes[0].vertices;
Vector3 *ndcVertices = (Vector3 *)ndcModels[targetMesh].meshes[0].vertices;
ndcVertices[i].x = Lerp(worldVertices[i].x, ndcVertices[i].x, sBlend);
ndcVertices[i].y = Lerp(worldVertices[i].y, ndcVertices[i].y, sBlend);
ndcVertices[i].z = Lerp(worldVertices[i].z, ndcVertices[i].z, sBlend);
}
Model *displayModel = &ndcModel;
Mesh *displayMesh = &ndcModel.meshes[0];
Model *displayModel = &ndcModels[targetMesh];
Mesh *displayMesh = &ndcModels[targetMesh].meshes[0];
if (PERSPECTIVE_CORRECT() && TEXTURE_MODE())
{
PerspectiveCorrectCapture(&main, displayModel, meshTexture, &perspectiveCorrectTexture, meshRotation);
PerspectiveCorrectCapture(&main, displayModel, meshTextures[targetMesh], &perspectiveCorrectTexture, meshRotation);
}
UpdateSpatialFrame(&main, aspect, near, far, &spatialFrame);
@ -235,8 +284,7 @@ int main(void)
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(jugemu);
if (JUGEMU_MODE()) BeginMode3D(jugemu); else BeginMode3D(main);
Vector3 depth, right, up;
BasisVector(&main, &depth, &right, &up);
@ -244,26 +292,30 @@ int main(void)
DrawLine3D(main.position, Vector3Add(main.position, up), LILAC);
DrawLine3D(main.position, Vector3Add(main.position, depth), MARINER);
DrawSpatialFrame(spatialFrame);
k">if (JUGEMU_MODE()) DrawSpatialFrame(&spatialFrame);
DrawModelFilled(displayModel, meshTexture, meshRotation);
DrawModelFilled(displayModel, meshTextures[targetMesh], meshRotation);
DrawModelWiresAndPoints(displayModel, meshRotation);
DrawNearPlanePoints(&main, aspect, near, &nearPlanePointsModel, displayMesh, meshRotation);
k">if (JUGEMU_MODE()) DrawNearPlanePoints(&main, aspect, near, &nearPlanePointsModels[targetMesh], displayMesh, meshRotation);
if (PERSPECTIVE_CORRECT() && TEXTURE_MODE())
{
spatialFrameModel.materials[0].maps[MATERIAL_MAP_ALBEDO].texture = perspectiveCorrectTexture;
DrawModel(spatialFrameModel, modelPos, 1.0f, WHITE);
k">if (JUGEMU_MODE()) DrawModel(spatialFrameModel, modelPos, 1.0f, WHITE);
}
else
{
PerspectiveIncorrectCapture(&main, aspect, near, displayMesh, meshTexture, meshRotation);
k">if (JUGEMU_MODE()) PerspectiveIncorrectCapture(&main, aspect, near, displayMesh, meshTextures[targetMesh], meshRotation);
}
EndMode3D();
DrawText("ARROWS: MOVE | SPACEBAR: PAUSE", 12, 12, fontSize, NEON_CARROT);
DrawText("W A : ZOOM", 12, 38, fontSize, NEON_CARROT);
DrawText("[1-2]: CUBE [3-4]: SPHERE [5]: KNOT", 12, 12, fontSize, NEON_CARROT);
DrawText("ARROWS: MOVE | SPACEBAR: PAUSE", 12, 38, fontSize, NEON_CARROT);
DrawText("W A : ZOOM ", 12, 64, fontSize, NEON_CARROT);
DrawText("CLIP [ X ]:", 12, 94, fontSize, SUNFLOWER);
DrawText((CLIP_MODE())? "ON" : "OFF", 120, 94, fontSize, (CLIP_MODE())? BAHAMA_BLUE : ANAKIWA);
DrawText((targetMesh == 0)? "GEN_CUBE" : (targetMesh == 1)? "LOAD_CUBE" : (targetMesh == 2)? "GEN_SPHERE" : (targetMesh == 3)? "LOAD_SPHERE" : "GEN_KNOT", 12, 205, fontSize, NEON_CARROT);
DrawText("TEXTURE [ T ]:", 570, 12, fontSize, SUNFLOWER);
DrawText((TEXTURE_MODE())? "ON" : "OFF", 740, 12, fontSize, (TEXTURE_MODE())? ANAKIWA : CHESTNUT_ROSE);
DrawText("COLORS [ C ]:", 570, 38, fontSize, SUNFLOWER);
@ -272,8 +324,10 @@ int main(void)
DrawText((ASPECT_CORRECT())? "CORRECT" : "INCORRECT", 230, 392, fontSize, (ASPECT_CORRECT())? ANAKIWA : CHESTNUT_ROSE);
DrawText("PERSPECTIVE [ P ]:", 12, 418, fontSize, SUNFLOWER);
DrawText((PERSPECTIVE_CORRECT())? "CORRECT" : "INCORRECT", 230, 418, fontSize, (PERSPECTIVE_CORRECT())? ANAKIWA : CHESTNUT_ROSE);
DrawText("SPACE [ N ]:", 530, 392, fontSize, SUNFLOWER);
DrawText((NDC_SPACE())? "NDC" : "WORLD", 665, 392, fontSize, (NDC_SPACE())? BAHAMA_BLUE : ANAKIWA);
DrawText("LENS [ O ]:", 510, 366, fontSize, SUNFLOWER);
DrawText((ORTHO_MODE())? "ORTHOGRAPHIC" : "PERSPECTIVE", 630, 366, fontSize, (ORTHO_MODE())? BAHAMA_BLUE : ANAKIWA);
DrawText("SPACE [ N ]:", 520, 392, fontSize, SUNFLOWER);
DrawText((NDC_SPACE())? "NDC" : "WORLD", 655, 392, fontSize, (NDC_SPACE())? BAHAMA_BLUE : ANAKIWA);
if (NDC_SPACE())
{
DrawText("REFLECT [ F ]:", 530, 418, fontSize, SUNFLOWER);
@ -286,11 +340,14 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(worldModel);
UnloadModel(ndcModel);
UnloadModel(nearPlanePointsModel);
for (int i = 0; i < NUM_MODELS; i++)
{
UnloadModel(worldModels[i]);
UnloadModel(ndcModels[i]);
UnloadModel(nearPlanePointsModels[i]);
if (meshTextures[i].id) UnloadTexture(meshTextures[i]);
}
UnloadModel(spatialFrameModel);
UnloadTexture(meshTexture);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
@ -312,9 +369,9 @@ static void WorldToNDCSpace(Camera3D *main, float aspect, float near, float far,
{
Vector3 depth, right, up;
BasisVector(main, &depth, &right, &up);
float halfHNear = near*tanf(DEG2RAD*main->fovy*0.5f);
float halfHNear = Lerp(near*tanf(DEG2RAD*fovyPerspective*0.5f), 0.5f*nearPlaneHeightOrthographic, OrthoBlendFactor(0.0f));
float halfWNear = Lerp(halfHNear, halfHNear*aspect, AspectBlendFactor(0.0f));
float halfDepthNDC = Lerp(halfHNear, 0.5f*(far - near), AspectBlendFactor(0.0f));
float halfDepthNDC = Lerp(halfHNear, 0.5f*(far - near), Lerp(AspectBlendFactor(0.0f), 0.0f, OrthoBlendFactor(0.0f)));
Vector3 centerNearPlane = Vector3Add(main->position, Vector3Scale(depth, near));
Vector3 centerNDCCube = Vector3Add(centerNearPlane, Vector3Scale(depth, halfDepthNDC));
@ -326,7 +383,7 @@ static void WorldToNDCSpace(Camera3D *main, float aspect, float near, float far,
Vector3 clipPlaneVector = Vector3Subtract(intersectionCoord, centerNearPlane);
float xNDC = Vector3DotProduct(clipPlaneVector, right)/halfWNear;
float yNDC = Vector3DotProduct(clipPlaneVector, up)/halfHNear;
float zNDC = (far + near - 2.0f*far*near/signedDepth)/(far - near);
float zNDC = n">Lerp((far + near - 2.0f*far*near/signedDepth)/(far - near), 2.0f*(signedDepth - near)/(far - near) - 1.0f, OrthoBlendFactor(0.0f));
Vector3 scaledRight = Vector3Scale(right, xNDC*halfWNear);
Vector3 scaledUp = Vector3Scale(up, yNDC*halfHNear);
Vector3 scaledDepth = Vector3Scale(depth, zNDC*halfDepthNDC);
@ -341,7 +398,6 @@ static void DrawModelFilled(Model *model, Texture2D texture, float rotation)
if (!(COLOR_MODE() || TEXTURE_MODE())) return;
Color *cacheColors = (Color *)model->meshes[0].colors;
if (TEXTURE_MODE() && !COLOR_MODE()) model->meshes[0].colors = NULL;
model->materials[0].maps[MATERIAL_MAP_ALBEDO].texture.id = (TEXTURE_MODE())? texture.id : 0;
DrawModelEx(*model, modelPos, yAxis, RAD2DEG*rotation, modelScale, WHITE);
model->materials[0].maps[MATERIAL_MAP_ALBEDO].texture.id = 0;
@ -353,9 +409,8 @@ static void DrawModelWiresAndPoints(Model *model, float rotation)
{
Color *cacheColors = (Color *)model->meshes[0].colors;
unsigned int cacheID = model->materials[0].maps[MATERIAL_MAP_ALBEDO].texture.id;
model->meshes[0].colors = NULL;
k">if (!CLIP_MODE()) model->meshes[0].colors = NULL;
model->materials[0].maps[MATERIAL_MAP_ALBEDO].texture.id = 0;
DrawModelWiresEx(*model, modelPos, yAxis, RAD2DEG*rotation, modelScale, MARINER);
rlSetPointSize(4.0f);
DrawModelPointsEx(*model, modelPos, yAxis, RAD2DEG*rotation, modelScale, LILAC);
@ -368,11 +423,11 @@ static void UpdateSpatialFrame(Camera3D *main, float aspect, float near, float f
{
Vector3 depth, right, up;
BasisVector(main, &depth, &right, &up);
float halfHNear = near*tanf(DEG2RAD*main->fovy*0.5f);
float halfHNear = Lerp(near*tanf(DEG2RAD*fovyPerspective*0.5f), 0.5f*nearPlaneHeightOrthographic, OrthoBlendFactor(0.0f));
float halfWNear = Lerp(halfHNear, halfHNear*aspect, AspectBlendFactor(0.0f));
float halfHFar = far*tanf(DEG2RAD*main->fovy*0.5f);
float halfHFar = Lerp(far*tanf(DEG2RAD*fovyPerspective*0.5f), 0.5f*nearPlaneHeightOrthographic, OrthoBlendFactor(0.0f));
float halfWFar = Lerp(halfHFar, halfHFar*aspect, AspectBlendFactor(0.0f));
float halfDepthNdc = Lerp(halfHNear, 0.5f*(far - near), AspectBlendFactor(0.0f));
float halfDepthNdc = Lerp(halfHNear, 0.5f*(far - near), Lerp(AspectBlendFactor(0.0f), 0.0f, OrthoBlendFactor(0.0f)));
float halfDepth = Lerp(0.5f*(far - near), halfDepthNdc, SpaceBlendFactor(0.0f));
float farHalfW = Lerp(halfWFar, halfWNear, SpaceBlendFactor(0.0f));
float farHalfH = Lerp(halfHFar, halfHNear, SpaceBlendFactor(0.0f));
@ -391,7 +446,7 @@ static void UpdateSpatialFrame(Camera3D *main, float aspect, float near, float f
}
}
static void DrawSpatialFrame(Mesh spatialFrame)
static void DrawSpatialFrame(Mesh o">*spatialFrame)
{
static int frontFaces[4][2] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 } };
static int backFaces[4][2] = { { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 } };
@ -401,8 +456,8 @@ static void DrawSpatialFrame(Mesh spatialFrame)
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
{
Vector3 startPosition = ((Vector3 *)spatialFramep">.vertices)[faces[i][j][0]];
Vector3 endPosition = ((Vector3 *)spatialFramep">.vertices)[faces[i][j][1]];
Vector3 startPosition = ((Vector3 *)spatialFrameo">->vertices)[faces[i][j][0]];
Vector3 endPosition = ((Vector3 *)spatialFrameo">->vertices)[faces[i][j][1]];
DrawLine3D(startPosition, endPosition, (i == 0)? NEON_CARROT : (i == 1)? EGGPLANT : HOPBUSH);
}
}
@ -552,12 +607,12 @@ static void OrbitSpace(Camera3D *jugemu, float dt)
float azimuth = atan2f(jugemu->position.z, jugemu->position.x);
float horizontalRadius = sqrtf(jugemu->position.x*jugemu->position.x + jugemu->position.z*jugemu->position.z);
float elevation = atan2f(jugemu->position.y, horizontalRadius);
if (IsKeyDown(KEY_LEFT)) azimuth += 1.5f*dt;
if (IsKeyDown(KEY_RIGHT)) azimuth -= 1.5f*dt;
if (IsKeyDown(KEY_LEFT)) azimuth += 1.0f*dt;
if (IsKeyDown(KEY_RIGHT)) azimuth -= 1.0f*dt;
if (IsKeyDown(KEY_UP)) elevation += 1.0f*dt;
if (IsKeyDown(KEY_DOWN)) elevation -= 1.0f*dt;
if (IsKeyDown(KEY_W)) radius -= 2.0f*dt;
if (IsKeyDown(KEY_S)) radius += 2.0f*dt;
if (IsKeyDown(KEY_W)) radius -= 1.0f*dt;
if (IsKeyDown(KEY_S)) radius += 1.0f*dt;
elevation = Clamp(elevation, -M_PI_2 + 0.1f, M_PI_2 - 0.1f);
jugemu->position.x = Clamp(radius, 0.25f, 10.0f)*cosf(elevation)*cosf(azimuth);
jugemu->position.y = Clamp(radius, 0.25f, 10.0f)*sinf(elevation);
@ -614,9 +669,13 @@ static Vector3 Intersect(Camera3D *main, float near, Vector3 worldCoord)
Vector3 viewDir = Vector3Normalize(Vector3Subtract(main->target, main->position));
Vector3 mainCameraToPoint = Vector3Subtract(worldCoord, main->position);
float depthAlongView = Vector3DotProduct(mainCameraToPoint, viewDir);
if (depthAlongView <= 0.0f) return Vector3Add(main->position, Vector3Scale(viewDir, near));
Vector3 centerNearPlane = Vector3Add(main->position, Vector3Scale(viewDir, near));
if (depthAlongView <= 0.0f) return centerNearPlane;
float scaleToNear = near/depthAlongView;
return Vector3Add(main->position, Vector3Scale(mainCameraToPoint, scaleToNear));
Vector3 resultPerspective = Vector3Add(main->position, Vector3Scale(mainCameraToPoint, scaleToNear));
Vector3 resultOrtho = Vector3Add(worldCoord, Vector3Scale(viewDir, Vector3DotProduct(Vector3Subtract(centerNearPlane, worldCoord), viewDir)));
Vector3 result = Vector3Lerp(resultPerspective,resultOrtho, OrthoBlendFactor(0.0f));
return result;
}
static float SpaceBlendFactor(float dt)
@ -644,3 +703,10 @@ static float ReflectBlendFactor(float dt)
}
return blend;
}
static float OrthoBlendFactor(float dt)
{
static float blend = 0.0f;
if (dt > 0.0f) blend = Clamp(blend + ((ORTHO_MODE())? 1.0f : -1.0f)*blendScalar*dt, 0.0f, 1.0f);
return blend;
}

+ 22
- 0
examples/core/resources/models/unit_cube.obj Просмотреть файл

@ -0,0 +1,22 @@
o unit_cube
v -0.5 -0.5 -0.5
v 0.5 -0.5 -0.5
v 0.5 0.5 -0.5
v -0.5 0.5 -0.5
v -0.5 -0.5 0.5
v 0.5 -0.5 0.5
v 0.5 0.5 0.5
v -0.5 0.5 0.5
s off
f 1 4 3
f 1 3 2
f 5 6 7
f 5 7 8
f 1 5 8
f 1 8 4
f 2 3 7
f 2 7 6
f 4 8 7
f 4 7 3
f 1 2 6
f 1 6 5

+ 173
- 0
examples/core/resources/models/unit_sphere.obj Просмотреть файл

@ -0,0 +1,173 @@
o sphere_unit_minimal
o sphere_unit_box_scaled
v 0.0000 0.5000 0.0000
v 0.1913 0.4619 0.0000
v 0.1353 0.4619 0.1353
v 0.0000 0.4619 0.1913
v -0.1353 0.4619 0.1353
v -0.1913 0.4619 0.0000
v -0.1353 0.4619 -0.1353
v -0.0000 0.4619 -0.1913
v 0.1353 0.4619 -0.1353
v 0.3536 0.3536 0.0000
v 0.2500 0.3536 0.2500
v 0.0000 0.3536 0.3536
v -0.2500 0.3536 0.2500
v -0.3536 0.3536 0.0000
v -0.2500 0.3536 -0.2500
v -0.0000 0.3536 -0.3536
v 0.2500 0.3536 -0.2500
v 0.4619 0.1913 0.0000
v 0.3266 0.1913 0.3266
v 0.0000 0.1913 0.4619
v -0.3266 0.1913 0.3266
v -0.4619 0.1913 0.0000
v -0.3266 0.1913 -0.3266
v -0.0000 0.1913 -0.4619
v 0.3266 0.1913 -0.3266
v 0.5000 0.0000 0.0000
v 0.3536 0.0000 0.3536
v 0.0000 0.0000 0.5000
v -0.3536 0.0000 0.3536
v -0.5000 0.0000 0.0000
v -0.3536 0.0000 -0.3536
v -0.0000 0.0000 -0.5000
v 0.3536 0.0000 -0.3536
v 0.4619 -0.1913 0.0000
v 0.3266 -0.1913 0.3266
v 0.0000 -0.1913 0.4619
v -0.3266 -0.1913 0.3266
v -0.4619 -0.1913 0.0000
v -0.3266 -0.1913 -0.3266
v -0.0000 -0.1913 -0.4619
v 0.3266 -0.1913 -0.3266
v 0.3536 -0.3536 0.0000
v 0.2500 -0.3536 0.2500
v 0.0000 -0.3536 0.3536
v -0.2500 -0.3536 0.2500
v -0.3536 -0.3536 0.0000
v -0.2500 -0.3536 -0.2500
v -0.0000 -0.3536 -0.3536
v 0.2500 -0.3536 -0.2500
v 0.1913 -0.4619 0.0000
v 0.1353 -0.4619 0.1353
v 0.0000 -0.4619 0.1913
v -0.1353 -0.4619 0.1353
v -0.1913 -0.4619 0.0000
v -0.1353 -0.4619 -0.1353
v -0.0000 -0.4619 -0.1913
v 0.1353 -0.4619 -0.1353
v 0.0000 -0.5000 0.0000
s off
f 1 3 2
f 1 4 3
f 1 5 4
f 1 6 5
f 1 7 6
f 1 8 7
f 1 9 8
f 1 2 9
f 2 3 10
f 3 11 10
f 3 4 11
f 4 12 11
f 4 5 12
f 5 13 12
f 5 6 13
f 6 14 13
f 6 7 14
f 7 15 14
f 7 8 15
f 8 16 15
f 8 9 16
f 9 17 16
f 9 2 17
f 2 10 17
f 10 11 18
f 11 19 18
f 11 12 19
f 12 20 19
f 12 13 20
f 13 21 20
f 13 14 21
f 14 22 21
f 14 15 22
f 15 23 22
f 15 16 23
f 16 24 23
f 16 17 24
f 17 25 24
f 17 10 25
f 10 18 25
f 18 19 26
f 19 27 26
f 19 20 27
f 20 28 27
f 20 21 28
f 21 29 28
f 21 22 29
f 22 30 29
f 22 23 30
f 23 31 30
f 23 24 31
f 24 32 31
f 24 25 32
f 25 33 32
f 25 18 33
f 18 26 33
f 26 27 34
f 27 35 34
f 27 28 35
f 28 36 35
f 28 29 36
f 29 37 36
f 29 30 37
f 30 38 37
f 30 31 38
f 31 39 38
f 31 32 39
f 32 40 39
f 32 33 40
f 33 41 40
f 33 26 41
f 26 34 41
f 34 35 42
f 35 43 42
f 35 36 43
f 36 44 43
f 36 37 44
f 37 45 44
f 37 38 45
f 38 46 45
f 38 39 46
f 39 47 46
f 39 40 47
f 40 48 47
f 40 41 48
f 41 49 48
f 41 34 49
f 34 42 49
f 42 43 50
f 43 51 50
f 43 44 51
f 44 52 51
f 44 45 52
f 45 53 52
f 45 46 53
f 46 54 53
f 46 47 54
f 47 55 54
f 47 48 55
f 48 56 55
f 48 49 56
f 49 57 56
f 49 42 57
f 42 50 57
f 58 50 51
f 58 51 52
f 58 52 53
f 58 53 54
f 58 54 55
f 58 55 56
f 58 56 57
f 58 57 50

Загрузка…
Отмена
Сохранить