Merge pull request #513 from autious/master
Add orthographic 3d rendering mode
This commit is contained in:
commit
564baa22d6
3 changed files with 183 additions and 11 deletions
112
examples/models/models_orthographic_projection.c
Normal file
112
examples/models/models_orthographic_projection.c
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [models] example - Show the difference between perspective and orthographic projection
|
||||||
|
*
|
||||||
|
* This program is heavily based on the geometric objects example
|
||||||
|
*
|
||||||
|
* This example has been created using raylib 1.0 (www.raylib.com)
|
||||||
|
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#define FOVY_PERSPECTIVE 45.0f
|
||||||
|
#define WIDTH_ORTHOGRAPHIC 10.0f
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
int screenWidth = 800;
|
||||||
|
int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes");
|
||||||
|
|
||||||
|
// Define the camera to look into our 3d world
|
||||||
|
Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, FOVY_PERSPECTIVE, CAMERA_PERSPECTIVE };
|
||||||
|
|
||||||
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// TODO: Update your variables here
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
// Input
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
if(IsKeyPressed(KEY_SPACE))
|
||||||
|
{
|
||||||
|
if(camera.type == CAMERA_PERSPECTIVE)
|
||||||
|
{
|
||||||
|
camera.fovy = WIDTH_ORTHOGRAPHIC;
|
||||||
|
camera.type = CAMERA_ORTHOGRAPHIC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
camera.fovy = FOVY_PERSPECTIVE;
|
||||||
|
camera.type = CAMERA_PERSPECTIVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
Begin3dMode(camera);
|
||||||
|
|
||||||
|
DrawCube((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, RED);
|
||||||
|
DrawCubeWires((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, GOLD);
|
||||||
|
DrawCubeWires((Vector3){-4.0f, 0.0f, -2.0f}, 3.0f, 6.0f, 2.0f, MAROON);
|
||||||
|
|
||||||
|
DrawSphere((Vector3){-1.0f, 0.0f, -2.0f}, 1.0f, GREEN);
|
||||||
|
DrawSphereWires((Vector3){1.0f, 0.0f, 2.0f}, 2.0f, 16, 16, LIME);
|
||||||
|
|
||||||
|
DrawCylinder((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, SKYBLUE);
|
||||||
|
DrawCylinderWires((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, DARKBLUE);
|
||||||
|
DrawCylinderWires((Vector3){4.5f, -1.0f, 2.0f}, 1.0f, 1.0f, 2.0f, 6, BROWN);
|
||||||
|
|
||||||
|
DrawCylinder((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, GOLD);
|
||||||
|
DrawCylinderWires((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, PINK);
|
||||||
|
|
||||||
|
DrawGrid(10, 1.0f); // Draw a grid
|
||||||
|
|
||||||
|
End3dMode();
|
||||||
|
|
||||||
|
DrawFPS(10, 10);
|
||||||
|
|
||||||
|
DrawText("Press Spacebar to switch camera type", 10, 40, 24, BLACK);
|
||||||
|
|
||||||
|
if(camera.type == CAMERA_ORTHOGRAPHIC)
|
||||||
|
{
|
||||||
|
DrawText("Orthographic", 10, 65, 24, BLACK);
|
||||||
|
}
|
||||||
|
else if(camera.type == CAMERA_PERSPECTIVE)
|
||||||
|
{
|
||||||
|
DrawText("Perspective", 10, 65, 24, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
71
src/core.c
71
src/core.c
|
@ -919,13 +919,26 @@ void Begin3dMode(Camera camera)
|
||||||
rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
|
rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
|
||||||
rlLoadIdentity(); // Reset current matrix (PROJECTION)
|
rlLoadIdentity(); // Reset current matrix (PROJECTION)
|
||||||
|
|
||||||
// Setup perspective projection
|
|
||||||
float aspect = (float)screenWidth/(float)screenHeight;
|
float aspect = (float)screenWidth/(float)screenHeight;
|
||||||
double top = 0.01*tan(camera.fovy*0.5*DEG2RAD);
|
|
||||||
double right = top*aspect;
|
if(camera.type == CAMERA_PERSPECTIVE)
|
||||||
|
{
|
||||||
|
// Setup perspective projection
|
||||||
|
double top = 0.01*tan(camera.fovy*0.5*DEG2RAD);
|
||||||
|
double right = top*aspect;
|
||||||
|
|
||||||
|
rlFrustum(-right, right, -top, top, 0.01, 1000.0);
|
||||||
|
}
|
||||||
|
else if(camera.type == CAMERA_ORTHOGRAPHIC)
|
||||||
|
{
|
||||||
|
// Setup orthographic projection
|
||||||
|
double top = camera.fovy/2.0;
|
||||||
|
double right = top*aspect;
|
||||||
|
|
||||||
|
rlOrtho(-right,right,-top,top, 0.01, 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: zNear and zFar values are important when computing depth buffer values
|
// NOTE: zNear and zFar values are important when computing depth buffer values
|
||||||
rlFrustum(-right, right, -top, top, 0.01, 1000.0);
|
|
||||||
|
|
||||||
rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
|
rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
|
||||||
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||||
|
@ -1013,22 +1026,48 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||||
|
|
||||||
TraceLog(LOG_DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z);
|
TraceLog(LOG_DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z);
|
||||||
|
|
||||||
// Calculate projection matrix from perspective
|
|
||||||
Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0);
|
|
||||||
|
|
||||||
// Calculate view matrix from camera look at
|
// Calculate view matrix from camera look at
|
||||||
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
|
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
|
||||||
|
|
||||||
|
Matrix matProj;
|
||||||
|
|
||||||
|
if(camera.type == CAMERA_PERSPECTIVE)
|
||||||
|
{
|
||||||
|
// Calculate projection matrix from perspective
|
||||||
|
matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0);
|
||||||
|
}
|
||||||
|
else if(camera.type == CAMERA_ORTHOGRAPHIC)
|
||||||
|
{
|
||||||
|
float aspect = (float)screenWidth/(float)screenHeight;
|
||||||
|
double top = camera.fovy/2.0;
|
||||||
|
double right = top*aspect;
|
||||||
|
// Calculate projection matrix from orthographic
|
||||||
|
matProj = MatrixOrtho(-right, right, -top, top, 0.01, 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
// Unproject far/near points
|
// Unproject far/near points
|
||||||
Vector3 nearPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView);
|
Vector3 nearPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView);
|
||||||
Vector3 farPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
|
Vector3 farPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
|
||||||
|
|
||||||
|
// Unproject the mouse cursor in the near plane.
|
||||||
|
// We need this as the source position because orthographic projects, compared to perspect doesn't have a
|
||||||
|
// convergence point, meaning that the "eye" of the camera is more like a plane than a point.
|
||||||
|
Vector3 cameraPlanePointerPos = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, -1.0f }, matProj, matView);
|
||||||
|
|
||||||
// Calculate normalized direction vector
|
// Calculate normalized direction vector
|
||||||
Vector3 direction = Vector3Subtract(farPoint, nearPoint);
|
Vector3 direction = Vector3Subtract(farPoint, nearPoint);
|
||||||
direction = Vector3Normalize(direction);
|
direction = Vector3Normalize(direction);
|
||||||
|
|
||||||
|
if(camera.type == CAMERA_PERSPECTIVE)
|
||||||
|
{
|
||||||
|
ray.position = camera.position;
|
||||||
|
}
|
||||||
|
else if(camera.type == CAMERA_ORTHOGRAPHIC)
|
||||||
|
{
|
||||||
|
ray.position = cameraPlanePointerPos;
|
||||||
|
}
|
||||||
|
|
||||||
// Apply calculated vectors to ray
|
// Apply calculated vectors to ray
|
||||||
ray.position = camera.position;
|
|
||||||
ray.direction = direction;
|
ray.direction = direction;
|
||||||
|
|
||||||
return ray;
|
return ray;
|
||||||
|
@ -1038,7 +1077,21 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||||
Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
||||||
{
|
{
|
||||||
// Calculate projection matrix (from perspective instead of frustum
|
// Calculate projection matrix (from perspective instead of frustum
|
||||||
Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0);
|
Matrix matProj;
|
||||||
|
|
||||||
|
if(camera.type == CAMERA_PERSPECTIVE)
|
||||||
|
{
|
||||||
|
// Calculate projection matrix from perspective
|
||||||
|
matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0);
|
||||||
|
}
|
||||||
|
else if(camera.type == CAMERA_ORTHOGRAPHIC)
|
||||||
|
{
|
||||||
|
float aspect = (float)screenWidth/(float)screenHeight;
|
||||||
|
double top = camera.fovy/2.0;
|
||||||
|
double right = top*aspect;
|
||||||
|
// Calculate projection matrix from orthographic
|
||||||
|
matProj = MatrixOrtho(-right, right, -top, top, 0.01, 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate view matrix from camera look at (and transpose it)
|
// Calculate view matrix from camera look at (and transpose it)
|
||||||
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
|
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
|
||||||
|
|
11
src/raylib.h
11
src/raylib.h
|
@ -398,12 +398,19 @@ typedef struct SpriteFont {
|
||||||
CharInfo *chars; // Characters info data
|
CharInfo *chars; // Characters info data
|
||||||
} SpriteFont;
|
} SpriteFont;
|
||||||
|
|
||||||
|
// Camera projection modes
|
||||||
|
typedef enum {
|
||||||
|
CAMERA_PERSPECTIVE = 0,
|
||||||
|
CAMERA_ORTHOGRAPHIC
|
||||||
|
} CameraType;
|
||||||
|
|
||||||
// Camera type, defines a camera position/orientation in 3d space
|
// Camera type, defines a camera position/orientation in 3d space
|
||||||
typedef struct Camera {
|
typedef struct Camera {
|
||||||
Vector3 position; // Camera position
|
Vector3 position; // Camera position
|
||||||
Vector3 target; // Camera target it looks-at
|
Vector3 target; // Camera target it looks-at
|
||||||
Vector3 up; // Camera up vector (rotation over its axis)
|
Vector3 up; // Camera up vector (rotation over its axis)
|
||||||
float fovy; // Camera field-of-view apperture in Y (degrees)
|
float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic
|
||||||
|
CameraType type; // Camera type, controlling projection type, either CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC.
|
||||||
} Camera;
|
} Camera;
|
||||||
|
|
||||||
// Camera2D type, defines a 2d camera
|
// Camera2D type, defines a 2d camera
|
||||||
|
@ -726,7 +733,7 @@ RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes
|
||||||
RLAPI void EndTextureMode(void); // Ends drawing to render texture
|
RLAPI void EndTextureMode(void); // Ends drawing to render texture
|
||||||
|
|
||||||
// Screen-space-related functions
|
// Screen-space-related functions
|
||||||
RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
|
RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
|
||||||
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position for a 3d world space position
|
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position for a 3d world space position
|
||||||
RLAPI Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix)
|
RLAPI Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue