@ -0,0 +1,538 @@ | |||
/******************************************************************************************* | |||
* | |||
* raylib [core] example - Oculus Rift CV1 | |||
* | |||
* Compile example using: | |||
* gcc -o $(NAME_PART).exe $(FILE_NAME) -I..\src\external -I..\src\external\OculusSDK\LibOVR\Include / | |||
* -L. -L..\src\external\OculusSDK\LibOVR -lLibOVRRT32_1 -lraylib -lglfw3 -lopengl32 -lgdi32 -std=c99 / | |||
* -Wl,-allow-multiple-definition | |||
* | |||
* #define SUPPORT_OCULUS_RIFT_CV1 / RLGL_OCULUS_SUPPORT | |||
* Enable Oculus Rift CV1 functionality | |||
* | |||
* This example has been created using raylib 1.5 (www.raylib.com) | |||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) | |||
* | |||
* Copyright (c) 2016 Ramon Santamaria (@raysan5) | |||
* | |||
********************************************************************************************/ | |||
#include "raylib.h" | |||
#include "glad.h" // Required for: OpenGL types and functions declarations | |||
#include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality | |||
#include <string.h> // Required for: memset() | |||
#include <stdlib.h> // Required for: exit() | |||
#include <stdio.h> // required for: vfprintf() | |||
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() | |||
#define RLGL_OCULUS_SUPPORT // Enable Oculus Rift code | |||
#if defined(RLGL_OCULUS_SUPPORT) | |||
#include "OVR_CAPI_GL.h" // Oculus SDK for OpenGL | |||
#endif | |||
//---------------------------------------------------------------------------------- | |||
// Defines and Macros | |||
//---------------------------------------------------------------------------------- | |||
// ... | |||
//---------------------------------------------------------------------------------- | |||
// Types and Structures Definition | |||
//---------------------------------------------------------------------------------- | |||
// TraceLog message types | |||
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; | |||
#if defined(RLGL_OCULUS_SUPPORT) | |||
// Oculus buffer type | |||
typedef struct OculusBuffer { | |||
ovrTextureSwapChain textureChain; | |||
GLuint depthId; | |||
GLuint fboId; | |||
int width; | |||
int height; | |||
} OculusBuffer; | |||
// Oculus mirror texture type | |||
typedef struct OculusMirror { | |||
ovrMirrorTexture texture; | |||
GLuint fboId; | |||
int width; | |||
int height; | |||
} OculusMirror; | |||
// Oculus layer type | |||
typedef struct OculusLayer { | |||
ovrViewScaleDesc viewScaleDesc; | |||
ovrLayerEyeFov eyeLayer; // layer 0 | |||
//ovrLayerQuad quadLayer; // TODO: layer 1: '2D' quad for GUI | |||
Matrix eyeProjections[2]; | |||
int width; | |||
int height; | |||
} OculusLayer; | |||
#endif | |||
//---------------------------------------------------------------------------------- | |||
// Global Variables Definition | |||
//---------------------------------------------------------------------------------- | |||
#if defined(RLGL_OCULUS_SUPPORT) | |||
// OVR device variables | |||
static ovrSession session; // Oculus session (pointer to ovrHmdStruct) | |||
static ovrHmdDesc hmdDesc; // Oculus device descriptor parameters | |||
static ovrGraphicsLuid luid; // Oculus locally unique identifier for the program (64 bit) | |||
static OculusLayer layer; // Oculus drawing layer (similar to photoshop) | |||
static OculusBuffer buffer; // Oculus internal buffers (texture chain and fbo) | |||
static OculusMirror mirror; // Oculus mirror texture and fbo | |||
static unsigned int frameIndex = 0; // Oculus frames counter, used to discard frames from chain | |||
#endif | |||
//---------------------------------------------------------------------------------- | |||
// Module specific Functions Declaration | |||
//---------------------------------------------------------------------------------- | |||
#if defined(RLGL_OCULUS_SUPPORT) | |||
static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) | |||
static void CloseOculusDevice(void); // Close Oculus device | |||
static void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking | |||
static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing | |||
static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror | |||
static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers | |||
static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer); // Unload texture required buffers | |||
static OculusMirror LoadOculusMirror(ovrSession session, int width, int height); // Load Oculus mirror buffers | |||
static void UnloadOculusMirror(ovrSession session, OculusMirror mirror); // Unload Oculus mirror buffers | |||
static void BlitOculusMirror(ovrSession session, OculusMirror mirror); // Copy Oculus screen buffer to mirror texture | |||
static OculusLayer InitOculusLayer(ovrSession session); // Init Oculus layer (similar to photoshop) | |||
static Matrix FromOvrMatrix(ovrMatrix4f ovrM); // Convert from Oculus ovrMatrix4f struct to raymath Matrix struct | |||
#endif | |||
static void TraceLog(int msgType, const char *text, ...); | |||
int main() | |||
{ | |||
// Initialization | |||
//-------------------------------------------------------------------------------------- | |||
int screenWidth = 1080; | |||
int screenHeight = 600; | |||
// NOTE: screenWidth/screenHeight should match VR device aspect ratio | |||
InitWindow(screenWidth, screenHeight, "raylib [core] example - oculus rift"); | |||
bool vrDeviceReady = InitOculusDevice(); // Init VR device Oculus Rift CV1 | |||
if (!vrDeviceReady) InitVrSimulator(HMD_OCULUS_RIFT_CV1); // Init VR simulator if device fails | |||
// Define the camera to look into our 3d world | |||
Camera camera; | |||
camera.position = (Vector3){ 5.0f, 2.0f, 5.0f }; // Camera position | |||
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point | |||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) | |||
camera.fovy = 60.0f; // Camera field-of-view Y | |||
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; | |||
SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set first person camera mode | |||
SetTargetFPS(90); // Set our game to run at 90 frames-per-second | |||
//-------------------------------------------------------------------------------------- | |||
// Main game loop | |||
while (!WindowShouldClose()) // Detect window close button or ESC key | |||
{ | |||
// Update | |||
//---------------------------------------------------------------------------------- | |||
if (!vrDeviceReady) UpdateCamera(&camera); // Update camera (simulator mode) | |||
else UpdateOculusTracking(&camera); // Update camera with device tracking data | |||
if (IsKeyPressed(KEY_SPACE)) ToggleVrMode(); // Toggle VR mode | |||
//---------------------------------------------------------------------------------- | |||
// Draw | |||
//---------------------------------------------------------------------------------- | |||
BeginDrawing(); | |||
ClearBackground(RAYWHITE); | |||
if (vrDeviceReady) BeginOculusDrawing(); | |||
else BeginVrDrawing(); | |||
Begin3dMode(camera); | |||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); | |||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); | |||
DrawGrid(40, 1.0f); | |||
End3dMode(); | |||
if (vrDeviceReady) EndOculusDrawing(); | |||
else EndVrDrawing(); | |||
DrawFPS(10, 10); | |||
EndDrawing(); | |||
//---------------------------------------------------------------------------------- | |||
} | |||
// De-Initialization | |||
//-------------------------------------------------------------------------------------- | |||
if (vrDeviceReady) CloseOculusDevice(); | |||
else CloseVrSimulator(); | |||
CloseWindow(); // Close window and OpenGL context | |||
//-------------------------------------------------------------------------------------- | |||
return 0; | |||
} | |||
//---------------------------------------------------------------------------------- | |||
// Module specific Functions Definition | |||
//---------------------------------------------------------------------------------- | |||
#if defined(RLGL_OCULUS_SUPPORT) | |||
// Set internal projection and modelview matrix depending on eyes tracking data | |||
static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) | |||
{ | |||
Matrix eyeProjection = matProjection; | |||
Matrix eyeModelView = matModelView; | |||
glViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, | |||
layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h); | |||
Quaternion eyeRenderPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x, | |||
layer.eyeLayer.RenderPose[eye].Orientation.y, | |||
layer.eyeLayer.RenderPose[eye].Orientation.z, | |||
layer.eyeLayer.RenderPose[eye].Orientation.w }; | |||
QuaternionInvert(&eyeRenderPose); | |||
Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose); | |||
Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, | |||
-layer.eyeLayer.RenderPose[eye].Position.y, | |||
-layer.eyeLayer.RenderPose[eye].Position.z); | |||
Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement | |||
eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement | |||
eyeProjection = layer.eyeProjections[eye]; | |||
} | |||
// Initialize Oculus device (returns true if success) | |||
static bool InitOculusDevice(void) | |||
{ | |||
bool oculusReady = false; | |||
ovrResult result = ovr_Initialize(NULL); | |||
if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device"); | |||
else | |||
{ | |||
result = ovr_Create(&session, &luid); | |||
if (OVR_FAILURE(result)) | |||
{ | |||
TraceLog(WARNING, "OVR: Could not create Oculus session"); | |||
ovr_Shutdown(); | |||
} | |||
else | |||
{ | |||
hmdDesc = ovr_GetHmdDesc(session); | |||
TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName); | |||
TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer); | |||
TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId); | |||
TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type); | |||
//TraceLog(INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber); | |||
TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); | |||
// NOTE: Oculus mirror is set to defined screenWidth and screenHeight... | |||
// ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2) | |||
// Initialize Oculus Buffers | |||
layer = InitOculusLayer(session); | |||
buffer = LoadOculusBuffer(session, layer.width, layer.height); | |||
mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); // NOTE: hardcoded... | |||
layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain); | |||
// Recenter OVR tracking origin | |||
ovr_RecenterTrackingOrigin(session); | |||
oculusReady = true; | |||
} | |||
} | |||
return oculusReady; | |||
} | |||
// Close Oculus device (and unload buffers) | |||
static void CloseOculusDevice(void) | |||
{ | |||
UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer | |||
UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers | |||
ovr_Destroy(session); // Free Oculus session data | |||
ovr_Shutdown(); // Close Oculus device connection | |||
} | |||
// Update Oculus head position-orientation tracking | |||
static void UpdateOculusTracking(Camera *camera) | |||
{ | |||
frameIndex++; | |||
ovrPosef eyePoses[2]; | |||
ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime); | |||
layer.eyeLayer.RenderPose[0] = eyePoses[0]; | |||
layer.eyeLayer.RenderPose[1] = eyePoses[1]; | |||
// TODO: Update external camera with eyePoses data (position, orientation) | |||
// NOTE: We can simplify to simple camera if we consider IPD and HMD device configuration again later | |||
// it will be useful for the user to draw, lets say, billboards oriented to camera | |||
// Get session status information | |||
ovrSessionStatus sessionStatus; | |||
ovr_GetSessionStatus(session, &sessionStatus); | |||
if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit..."); | |||
if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session); | |||
//if (sessionStatus.HmdPresent) // HMD is present. | |||
//if (sessionStatus.DisplayLost) // HMD was unplugged or the display driver was manually disabled or encountered a TDR. | |||
//if (sessionStatus.HmdMounted) // HMD is on the user's head. | |||
//if (sessionStatus.IsVisible) // the game or experience has VR focus and is visible in the HMD. | |||
} | |||
// Setup Oculus buffers for drawing | |||
static void BeginOculusDrawing(void) | |||
{ | |||
GLuint currentTexId; | |||
int currentIndex; | |||
ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, ¤tIndex); | |||
ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, ¤tTexId); | |||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId); | |||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentTexId, 0); | |||
//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer.depthId, 0); // Already binded | |||
} | |||
// Finish Oculus drawing and blit framebuffer to mirror | |||
static void EndOculusDrawing(void) | |||
{ | |||
// Unbind current framebuffer (Oculus buffer) | |||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | |||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | |||
ovr_CommitTextureSwapChain(session, buffer.textureChain); | |||
ovrLayerHeader *layers = &layer.eyeLayer.Header; | |||
ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1); | |||
// Blit mirror texture to back buffer | |||
BlitOculusMirror(session, mirror); | |||
} | |||
// Load Oculus required buffers: texture-swap-chain, fbo, texture-depth | |||
static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) | |||
{ | |||
OculusBuffer buffer; | |||
buffer.width = width; | |||
buffer.height = height; | |||
// Create OVR texture chain | |||
ovrTextureSwapChainDesc desc = {}; | |||
desc.Type = ovrTexture_2D; | |||
desc.ArraySize = 1; | |||
desc.Width = width; | |||
desc.Height = height; | |||
desc.MipLevels = 1; | |||
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; // Requires glEnable(GL_FRAMEBUFFER_SRGB); | |||
desc.SampleCount = 1; | |||
desc.StaticImage = ovrFalse; | |||
ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain); | |||
if (!OVR_SUCCESS(result)) TraceLog(WARNING, "OVR: Failed to create swap textures buffer"); | |||
int textureCount = 0; | |||
ovr_GetTextureSwapChainLength(session, buffer.textureChain, &textureCount); | |||
if (!OVR_SUCCESS(result) || !textureCount) TraceLog(WARNING, "OVR: Unable to count swap chain textures"); | |||
for (int i = 0; i < textureCount; ++i) | |||
{ | |||
GLuint chainTexId; | |||
ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, i, &chainTexId); | |||
glBindTexture(GL_TEXTURE_2D, chainTexId); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |||
} | |||
glBindTexture(GL_TEXTURE_2D, 0); | |||
/* | |||
// Setup framebuffer object (using depth texture) | |||
glGenFramebuffers(1, &buffer.fboId); | |||
glGenTextures(1, &buffer.depthId); | |||
glBindTexture(GL_TEXTURE_2D, buffer.depthId); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); | |||
*/ | |||
// Setup framebuffer object (using depth renderbuffer) | |||
glGenFramebuffers(1, &buffer.fboId); | |||
glGenRenderbuffers(1, &buffer.depthId); | |||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId); | |||
glBindRenderbuffer(GL_RENDERBUFFER, buffer.depthId); | |||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, buffer.width, buffer.height); | |||
glBindRenderbuffer(GL_RENDERBUFFER, 0); | |||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer.depthId); | |||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | |||
return buffer; | |||
} | |||
// Unload texture required buffers | |||
static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer) | |||
{ | |||
if (buffer.textureChain) | |||
{ | |||
ovr_DestroyTextureSwapChain(session, buffer.textureChain); | |||
buffer.textureChain = NULL; | |||
} | |||
if (buffer.depthId != 0) glDeleteTextures(1, &buffer.depthId); | |||
if (buffer.fboId != 0) glDeleteFramebuffers(1, &buffer.fboId); | |||
} | |||
// Load Oculus mirror buffers | |||
static OculusMirror LoadOculusMirror(ovrSession session, int width, int height) | |||
{ | |||
OculusMirror mirror; | |||
mirror.width = width; | |||
mirror.height = height; | |||
ovrMirrorTextureDesc mirrorDesc; | |||
memset(&mirrorDesc, 0, sizeof(mirrorDesc)); | |||
mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; | |||
mirrorDesc.Width = mirror.width; | |||
mirrorDesc.Height = mirror.height; | |||
if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(WARNING, "Could not create mirror texture"); | |||
glGenFramebuffers(1, &mirror.fboId); | |||
return mirror; | |||
} | |||
// Unload Oculus mirror buffers | |||
static void UnloadOculusMirror(ovrSession session, OculusMirror mirror) | |||
{ | |||
if (mirror.fboId != 0) glDeleteFramebuffers(1, &mirror.fboId); | |||
if (mirror.texture) ovr_DestroyMirrorTexture(session, mirror.texture); | |||
} | |||
// Copy Oculus screen buffer to mirror texture | |||
static void BlitOculusMirror(ovrSession session, OculusMirror mirror) | |||
{ | |||
GLuint mirrorTextureId; | |||
ovr_GetMirrorTextureBufferGL(session, mirror.texture, &mirrorTextureId); | |||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mirror.fboId); | |||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0); | |||
#if defined(GRAPHICS_API_OPENGL_33) | |||
// NOTE: glBlitFramebuffer() requires extension: GL_EXT_framebuffer_blit (not available in OpenGL ES 2.0) | |||
glBlitFramebuffer(0, 0, mirror.width, mirror.height, 0, mirror.height, mirror.width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); | |||
#endif | |||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); | |||
} | |||
// Init Oculus layer (similar to photoshop) | |||
static OculusLayer InitOculusLayer(ovrSession session) | |||
{ | |||
OculusLayer layer = { 0 }; | |||
layer.viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; | |||
memset(&layer.eyeLayer, 0, sizeof(ovrLayerEyeFov)); | |||
layer.eyeLayer.Header.Type = ovrLayerType_EyeFov; | |||
layer.eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; | |||
ovrEyeRenderDesc eyeRenderDescs[2]; | |||
for (int eye = 0; eye < 2; eye++) | |||
{ | |||
eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]); | |||
ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(eyeRenderDescs[eye].Fov, 0.01f, 10000.0f, ovrProjection_None); //ovrProjection_ClipRangeOpenGL); | |||
layer.eyeProjections[eye] = FromOvrMatrix(ovrPerspectiveProjection); // NOTE: struct ovrMatrix4f { float M[4][4] } --> struct Matrix | |||
layer.viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset; | |||
layer.eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov; | |||
ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, layer.eyeLayer.Fov[eye], 1.0f); | |||
layer.eyeLayer.Viewport[eye].Size = eyeSize; | |||
layer.eyeLayer.Viewport[eye].Pos.x = layer.width; | |||
layer.eyeLayer.Viewport[eye].Pos.y = 0; | |||
layer.height = eyeSize.h; //std::max(renderTargetSize.y, (uint32_t)eyeSize.h); | |||
layer.width += eyeSize.w; | |||
} | |||
return layer; | |||
} | |||
// Convert from Oculus ovrMatrix4f struct to raymath Matrix struct | |||
static Matrix FromOvrMatrix(ovrMatrix4f ovrmat) | |||
{ | |||
Matrix rmat; | |||
rmat.m0 = ovrmat.M[0][0]; | |||
rmat.m1 = ovrmat.M[1][0]; | |||
rmat.m2 = ovrmat.M[2][0]; | |||
rmat.m3 = ovrmat.M[3][0]; | |||
rmat.m4 = ovrmat.M[0][1]; | |||
rmat.m5 = ovrmat.M[1][1]; | |||
rmat.m6 = ovrmat.M[2][1]; | |||
rmat.m7 = ovrmat.M[3][1]; | |||
rmat.m8 = ovrmat.M[0][2]; | |||
rmat.m9 = ovrmat.M[1][2]; | |||
rmat.m10 = ovrmat.M[2][2]; | |||
rmat.m11 = ovrmat.M[3][2]; | |||
rmat.m12 = ovrmat.M[0][3]; | |||
rmat.m13 = ovrmat.M[1][3]; | |||
rmat.m14 = ovrmat.M[2][3]; | |||
rmat.m15 = ovrmat.M[3][3]; | |||
MatrixTranspose(&rmat); | |||
return rmat; | |||
} | |||
#endif | |||
// Output a trace log message | |||
// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning | |||
static void TraceLog(int msgType, const char *text, ...) | |||
{ | |||
va_list args; | |||
va_start(args, text); | |||
switch (msgType) | |||
{ | |||
case INFO: fprintf(stdout, "INFO: "); break; | |||
case ERROR: fprintf(stdout, "ERROR: "); break; | |||
case WARNING: fprintf(stdout, "WARNING: "); break; | |||
case DEBUG: fprintf(stdout, "DEBUG: "); break; | |||
default: break; | |||
} | |||
vfprintf(stdout, text, args); | |||
fprintf(stdout, "\n"); | |||
va_end(args); | |||
if (msgType == ERROR) exit(1); | |||
} | |||
@ -1,393 +0,0 @@ | |||
/******************************************************************************************* | |||
* | |||
* raylib [rlgl] example - Oculus minimum sample | |||
* | |||
* NOTE: This example requires OpenGL 3.3 or ES2 versions for shaders support, | |||
* OpenGL 1.1 does not support shaders but it can also be used. | |||
* | |||
* Compile rlgl module using: | |||
* gcc -c rlgl.c -Wall -std=c99 -DRLGL_STANDALONE -DRAYMATH_IMPLEMENTATION -DGRAPHICS_API_OPENGL_33 -DRLGL_OCULUS_SUPPORT | |||
* | |||
* NOTE 1: rlgl module requires the following header-only files: | |||
* external/glad.h - OpenGL extensions loader (stripped to only required extensions) | |||
* shader_standard.h - Standard shader for materials and lighting | |||
* shader_distortion.h - Distortion shader for VR | |||
* raymath.h - Vector and matrix math functions | |||
* | |||
* NOTE 2: rlgl requires LibOVR (Oculus PC SDK) to support Oculus Rift CV1 | |||
* | |||
* Compile example using: | |||
* gcc -o rlgl_oculus_rift.exe rlgl_oculus_rift.c rlgl.o -L. -lLibOVRRT32_1 -lglfw3 -lopengl32 -lgdi32 -std=c99 | |||
* | |||
* NOTE: Example must be linked against LibOVRRT32_1.dll that comes with Oculus Rift runtime. | |||
* | |||
* This example has been created using raylib 1.5 (www.raylib.com) | |||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) | |||
* | |||
* Copyright (c) 2015 Ramon Santamaria (@raysan5) | |||
* | |||
********************************************************************************************/ | |||
#include <stdlib.h> | |||
#include <stdarg.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <math.h> | |||
#include <GLFW/glfw3.h> // Windows/Context and inputs management | |||
#define RLGL_STANDALONE | |||
#include "rlgl.h" // rlgl library: OpenGL 1.1 immediate-mode style coding | |||
#define RED (Color){ 230, 41, 55, 255 } // Red | |||
#define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo) | |||
#define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray | |||
//---------------------------------------------------------------------------------- | |||
// Module specific Functions Declaration | |||
//---------------------------------------------------------------------------------- | |||
static void ErrorCallback(int error, const char* description); | |||
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); | |||
// Drawing functions (uses rlgl functionality) | |||
static void DrawGrid(int slices, float spacing); | |||
static void DrawCube(Vector3 position, float width, float height, float length, Color color); | |||
static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); | |||
static void DrawRectangleV(Vector2 position, Vector2 size, Color color); | |||
//---------------------------------------------------------------------------------- | |||
// Main Entry point | |||
//---------------------------------------------------------------------------------- | |||
int main(void) | |||
{ | |||
// Initialization | |||
//-------------------------------------------------------------------------------------- | |||
int screenWidth = 1080; // Mirror screen width (set to hmdDesc.Resolution.w/2) | |||
int screenHeight = 600; // Mirror screen height (set to hmdDesc.Resolution.h/2) | |||
// NOTE: Mirror screen size can be set to any desired resolution! | |||
// GLFW3 Initialization + OpenGL 3.3 Context + Extensions | |||
//-------------------------------------------------------- | |||
glfwSetErrorCallback(ErrorCallback); | |||
if (!glfwInit()) | |||
{ | |||
TraceLog(WARNING, "GLFW3: Can not initialize GLFW"); | |||
return 1; | |||
} | |||
else TraceLog(INFO, "GLFW3: GLFW initialized successfully"); | |||
glfwWindowHint(GLFW_SAMPLES, 4); | |||
glfwWindowHint(GLFW_DEPTH_BITS, 16); | |||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | |||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | |||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | |||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); | |||
GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl oculus rift", NULL, NULL); | |||
if (!window) | |||
{ | |||
glfwTerminate(); | |||
return 2; | |||
} | |||
else TraceLog(INFO, "GLFW3: Window created successfully"); | |||
glfwSetKeyCallback(window, KeyCallback); | |||
glfwMakeContextCurrent(window); | |||
glfwSwapInterval(0); | |||
// Load OpenGL 3.3 supported extensions | |||
rlglLoadExtensions(glfwGetProcAddress); | |||
//-------------------------------------------------------- | |||
// Initialize OpenGL context (states and resources) | |||
rlglInit(screenWidth, screenHeight); | |||
rlClearColor(245, 245, 245, 255); // Define clear color | |||
rlEnableDepthTest(); // Enable DEPTH_TEST for 3D | |||
// Define custom camera to initialize projection and view matrices | |||
Camera camera; | |||
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position | |||
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point | |||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) | |||
camera.fovy = 45.0f; // Camera field-of-view Y | |||
// Initialize viewport and internal projection/modelview matrices | |||
rlViewport(0, 0, screenWidth, screenHeight); | |||
rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix | |||
rlLoadIdentity(); // Reset current matrix (PROJECTION) | |||
// Setup perspective projection | |||
float aspect = (float)screenWidth/(float)screenHeight; | |||
double top = 0.01*tan(camera.fovy*PI/360.0); | |||
double right = top*aspect; | |||
rlFrustum(-right, right, -top, top, 0.01, 1000.0); | |||
rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix | |||
rlLoadIdentity(); // Reset current matrix (MODELVIEW) | |||
// Setup Camera view | |||
Matrix cameraView = MatrixLookAt(camera.position, camera.target, camera.up); | |||
rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera) | |||
InitOculusDevice(); // Initialize Oculus Rift CV1 | |||
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; | |||
//-------------------------------------------------------------------------------------- | |||
// Main game loop | |||
while (!glfwWindowShouldClose(window)) | |||
{ | |||
// Update | |||
//---------------------------------------------------------------------------------- | |||
UpdateOculusTracking(&camera); | |||
//---------------------------------------------------------------------------------- | |||
// Draw | |||
//---------------------------------------------------------------------------------- | |||
BeginOculusDrawing(); | |||
rlClearScreenBuffers(); // Clear current framebuffer(s) | |||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); | |||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, RAYWHITE); | |||
DrawGrid(10, 1.0f); | |||
// NOTE: Internal buffers drawing (3D data) | |||
rlglDraw(); | |||
EndOculusDrawing(); | |||
glfwSwapBuffers(window); | |||
glfwPollEvents(); | |||
//---------------------------------------------------------------------------------- | |||
} | |||
// De-Initialization | |||
//-------------------------------------------------------------------------------------- | |||
CloseOculusDevice(); // Close Oculus device and clear resources | |||
rlglClose(); // Unload rlgl internal buffers and default shader/texture | |||
glfwDestroyWindow(window); // Close window | |||
glfwTerminate(); // Free GLFW3 resources | |||
//-------------------------------------------------------------------------------------- | |||
return 0; | |||
} | |||
//---------------------------------------------------------------------------------- | |||
// Module specific Functions Definitions | |||
//---------------------------------------------------------------------------------- | |||
// GLFW3: Error callback | |||
static void ErrorCallback(int error, const char* description) | |||
{ | |||
TraceLog(ERROR, description); | |||
} | |||
// GLFW3: Keyboard callback | |||
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) | |||
{ | |||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) | |||
{ | |||
glfwSetWindowShouldClose(window, GL_TRUE); | |||
} | |||
} | |||
// Draw rectangle using rlgl OpenGL 1.1 style coding (translated to OpenGL 3.3 internally) | |||
static void DrawRectangleV(Vector2 position, Vector2 size, Color color) | |||
{ | |||
rlBegin(RL_TRIANGLES); | |||
rlColor4ub(color.r, color.g, color.b, color.a); | |||
rlVertex2i(position.x, position.y); | |||
rlVertex2i(position.x, position.y + size.y); | |||
rlVertex2i(position.x + size.x, position.y + size.y); | |||
rlVertex2i(position.x, position.y); | |||
rlVertex2i(position.x + size.x, position.y + size.y); | |||
rlVertex2i(position.x + size.x, position.y); | |||
rlEnd(); | |||
} | |||
// Draw a grid centered at (0, 0, 0) | |||
static void DrawGrid(int slices, float spacing) | |||
{ | |||
int halfSlices = slices / 2; | |||
rlBegin(RL_LINES); | |||
for(int i = -halfSlices; i <= halfSlices; i++) | |||
{ | |||
if (i == 0) | |||
{ | |||
rlColor3f(0.5f, 0.5f, 0.5f); | |||
rlColor3f(0.5f, 0.5f, 0.5f); | |||
rlColor3f(0.5f, 0.5f, 0.5f); | |||
rlColor3f(0.5f, 0.5f, 0.5f); | |||
} | |||
else | |||
{ | |||
rlColor3f(0.75f, 0.75f, 0.75f); | |||
rlColor3f(0.75f, 0.75f, 0.75f); | |||
rlColor3f(0.75f, 0.75f, 0.75f); | |||
rlColor3f(0.75f, 0.75f, 0.75f); | |||
} | |||
rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing); | |||
rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing); | |||
rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing); | |||
rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing); | |||
} | |||
rlEnd(); | |||
} | |||
// Draw cube | |||
// NOTE: Cube position is the center position | |||
void DrawCube(Vector3 position, float width, float height, float length, Color color) | |||
{ | |||
float x = 0.0f; | |||
float y = 0.0f; | |||
float z = 0.0f; | |||
rlPushMatrix(); | |||
// NOTE: Be careful! Function order matters (rotate -> scale -> translate) | |||
rlTranslatef(position.x, position.y, position.z); | |||
//rlScalef(2.0f, 2.0f, 2.0f); | |||
//rlRotatef(45, 0, 1, 0); | |||
rlBegin(RL_TRIANGLES); | |||
rlColor4ub(color.r, color.g, color.b, color.a); | |||
// Front Face ----------------------------------------------------- | |||
rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left | |||
rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right | |||
rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left | |||
rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right | |||
rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left | |||
rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right | |||
// Back Face ------------------------------------------------------ | |||
rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left | |||
rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left | |||
rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right | |||
rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right | |||
rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right | |||
rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left | |||
// Top Face ------------------------------------------------------- | |||
rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left | |||
rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left | |||
rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right | |||
rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right | |||
rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left | |||
rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right | |||
// Bottom Face ---------------------------------------------------- | |||
rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left | |||
rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right | |||
rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left | |||
rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right | |||
rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right | |||
rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left | |||
// Right face ----------------------------------------------------- | |||
rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right | |||
rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right | |||
rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left | |||
rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left | |||
rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right | |||
rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left | |||
// Left Face ------------------------------------------------------ | |||
rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right | |||
rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left | |||
rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right | |||
rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left | |||
rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left | |||
rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right | |||
rlEnd(); | |||
rlPopMatrix(); | |||
} | |||
// Draw cube wires | |||
void DrawCubeWires(Vector3 position, float width, float height, float length, Color color) | |||
{ | |||
float x = 0.0f; | |||
float y = 0.0f; | |||
float z = 0.0f; | |||
rlPushMatrix(); | |||
rlTranslatef(position.x, position.y, position.z); | |||
//rlRotatef(45, 0, 1, 0); | |||
rlBegin(RL_LINES); | |||
rlColor4ub(color.r, color.g, color.b, color.a); | |||
// Front Face ----------------------------------------------------- | |||
// Bottom Line | |||
rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left | |||
rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right | |||
// Left Line | |||
rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right | |||
rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right | |||
// Top Line | |||
rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right | |||
rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left | |||
// Right Line | |||
rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left | |||
rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left | |||
// Back Face ------------------------------------------------------ | |||
// Bottom Line | |||
rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left | |||
rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right | |||
// Left Line | |||
rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right | |||
rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right | |||
// Top Line | |||
rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right | |||
rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left | |||
// Right Line | |||
rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left | |||
rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left | |||
// Top Face ------------------------------------------------------- | |||
// Left Line | |||
rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Front | |||
rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Back | |||
// Right Line | |||
rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Front | |||
rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Back | |||
// Bottom Face --------------------------------------------------- | |||
// Left Line | |||
rlVertex3f(x-width/2, y-height/2, z+length/2); // Top Left Front | |||
rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left Back | |||
// Right Line | |||
rlVertex3f(x+width/2, y-height/2, z+length/2); // Top Right Front | |||
rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right Back | |||
rlEnd(); | |||
rlPopMatrix(); | |||
} |
@ -1,456 +0,0 @@ | |||
# Blender v2.78 (sub 0) OBJ File: 'lowpoly-tower.blend' | |||
# www.blender.org | |||
o Grid | |||
v -4.000000 0.000000 4.000000 | |||
v -2.327363 0.000000 4.654725 | |||
v 0.000000 0.000000 4.654725 | |||
v 2.327363 0.000000 4.654725 | |||
v 4.000000 0.000000 4.000000 | |||
v -4.654725 0.955085 2.327363 | |||
v -2.000000 0.815050 2.000000 | |||
v 0.000000 0.476341 2.423448 | |||
v 2.000000 0.476341 2.000000 | |||
v 4.654725 0.000000 2.327363 | |||
v -4.654725 1.649076 0.000000 | |||
v -2.423448 1.092402 0.000000 | |||
v 2.423448 0.198579 0.000000 | |||
v 4.654725 0.000000 0.000000 | |||
v -4.654725 1.649076 -2.327363 | |||
v -2.000000 1.092402 -2.000000 | |||
v 0.000000 0.476341 -2.423448 | |||
v 2.000000 -0.012791 -2.000000 | |||
v 4.654725 0.000000 -2.612731 | |||
v -4.000000 0.955085 -4.000000 | |||
v -2.327363 0.955085 -4.654725 | |||
v 0.000000 0.955085 -4.654725 | |||
v 2.327363 0.000000 -4.654725 | |||
v 4.000000 0.000000 -4.000000 | |||
v 2.423448 0.682825 0.000000 | |||
v 2.000000 0.565423 -2.000000 | |||
v -4.654725 -0.020560 2.327363 | |||
v -4.654725 0.000000 0.000000 | |||
v -4.654725 0.000000 -2.327363 | |||
v -4.000000 0.000000 -4.000000 | |||
v -2.327363 0.000000 -4.654725 | |||
v 0.000000 -0.020560 -4.654725 | |||
v 0.000000 0.709880 -1.230535 | |||
v -0.000000 7.395413 0.000000 | |||
v 0.962071 0.709880 -0.767226 | |||
v -0.533909 0.709880 1.108674 | |||
v -1.199683 0.709880 0.273820 | |||
v -0.962071 0.709880 -0.767226 | |||
v 1.506076 0.859071 1.325337 | |||
v 1.199683 0.709880 0.273820 | |||
v 0.533909 0.709880 1.108674 | |||
v 0.000000 1.875340 -1.177842 | |||
v -0.000000 2.293973 -0.649884 | |||
v -0.000000 4.365648 -0.627970 | |||
v 0.000000 6.167194 -0.942957 | |||
v 0.000000 6.232434 -1.708677 | |||
v 1.335898 6.232434 -1.065343 | |||
v 0.737233 6.167195 -0.587924 | |||
v 0.490966 4.365648 -0.391533 | |||
v 0.508100 2.293973 -0.405196 | |||
v 0.920874 1.875340 -0.734372 | |||
v -0.741367 6.232434 1.539465 | |||
v -0.409133 6.167195 0.849574 | |||
v -0.272466 4.365648 0.565781 | |||
v -0.281974 2.293973 0.585526 | |||
v -0.511047 1.875340 1.061199 | |||
v -1.665837 6.232434 0.380217 | |||
v -0.919314 6.167195 0.209828 | |||
v -0.612225 4.365648 0.139736 | |||
v -0.633590 2.293973 0.144613 | |||
v -1.148311 1.875340 0.262095 | |||
v -1.335898 6.232434 -1.065343 | |||
v -0.737233 6.167195 -0.587924 | |||
v -0.490967 4.365648 -0.391533 | |||
v -0.508100 2.293973 -0.405196 | |||
v -0.920874 1.875340 -0.734372 | |||
v 1.665837 6.232434 0.380216 | |||
v 0.919315 6.167195 0.209828 | |||
v 0.612225 4.365648 0.139736 | |||
v 0.633590 2.293973 0.144613 | |||
v 1.148311 1.875340 0.262095 | |||
v 0.741367 6.232434 1.539465 | |||
v 0.409133 6.167195 0.849575 | |||
v 0.272466 4.365648 0.565781 | |||
v 0.281974 2.293973 0.585526 | |||
v 0.511046 1.875340 1.061199 | |||
v 0.000000 5.012550 -0.969733 | |||
v 0.758168 5.012550 -0.604618 | |||
v -0.420751 5.012550 0.873699 | |||
v -0.945419 5.012550 0.215786 | |||
v -0.758168 5.012550 -0.604618 | |||
v 0.945419 5.012550 0.215786 | |||
v 0.420751 5.012550 0.873699 | |||
vt 0.0523 0.5444 | |||
vt 0.1817 0.4284 | |||
vt 0.1641 0.5859 | |||
vt 0.0177 0.4451 | |||
vt 0.1526 0.3090 | |||
vt 0.0189 0.1737 | |||
vt 0.0188 0.3088 | |||
vt 0.0561 0.0762 | |||
vt 0.1757 0.1924 | |||
vt 0.3024 0.4534 | |||
vt 0.3071 0.5902 | |||
vt 0.3413 0.2459 | |||
vt 0.2906 0.1614 | |||
vt 0.4116 0.1801 | |||
vt 0.2834 0.3774 | |||
vt 0.1526 0.0362 | |||
vt 0.2917 0.1622 | |||
vt 0.4446 0.5865 | |||
vt 0.4443 0.2989 | |||
vt 0.3711 0.3021 | |||
vt 0.4396 0.0275 | |||
vt 0.4094 0.1829 | |||
vt 0.4219 0.4255 | |||
vt 0.5474 0.5381 | |||
vt 0.5811 0.4376 | |||
vt 0.5715 0.1505 | |||
vt 0.5811 0.2997 | |||
vt 0.5272 0.0533 | |||
vt 0.2208 0.2194 | |||
vt 0.3456 0.3610 | |||
vt 0.2878 0.0321 | |||
vt 0.2321 0.3392 | |||
vt 0.4432 0.0177 | |||
vt 0.7347 0.7934 | |||
vt 0.7382 0.7595 | |||
vt 0.8982 0.7768 | |||
vt 0.6169 0.7595 | |||
vt 0.6139 0.7879 | |||
vt 0.4951 0.7634 | |||
vt 0.1551 0.6832 | |||
vt 0.2925 0.6268 | |||
vt 0.2925 0.6832 | |||
vt 0.7795 0.6832 | |||
vt 0.6421 0.6268 | |||
vt 0.7795 0.6255 | |||
vt 0.5046 0.7241 | |||
vt 0.6421 0.7241 | |||
vt 0.3986 0.6268 | |||
vt 0.3986 0.6832 | |||
vt 0.5046 0.6268 | |||
vt 0.0177 0.6268 | |||
vt 0.1551 0.6255 | |||
vt 0.8856 0.6268 | |||
vt 0.1899 0.9579 | |||
vt 0.1194 0.8696 | |||
vt 0.2324 0.8696 | |||
vt 0.1899 0.7813 | |||
vt 0.0943 0.7595 | |||
vt 0.0177 0.8206 | |||
vt 0.0177 0.9186 | |||
vt 0.0943 0.9797 | |||
vt 0.2793 0.2349 | |||
vt 0.2304 0.2758 | |||
vt 0.6597 0.0177 | |||
vt 0.6954 0.0993 | |||
vt 0.6367 0.0768 | |||
vt 0.7558 0.0777 | |||
vt 0.7238 0.0440 | |||
vt 0.8840 0.1330 | |||
vt 0.7385 0.1141 | |||
vt 0.9157 0.0886 | |||
vt 0.9781 0.1232 | |||
vt 0.9224 0.1276 | |||
vt 0.2677 0.8141 | |||
vt 0.3463 0.8037 | |||
vt 0.3086 0.8339 | |||
vt 0.6387 0.3550 | |||
vt 0.7130 0.3801 | |||
vt 0.6596 0.4053 | |||
vt 0.7245 0.3245 | |||
vt 0.6919 0.3383 | |||
vt 0.8655 0.3566 | |||
vt 0.7351 0.3577 | |||
vt 0.9770 0.3365 | |||
vt 0.9078 0.3751 | |||
vt 0.9174 0.3282 | |||
vt 0.2677 0.9018 | |||
vt 0.3086 0.8821 | |||
vt 0.6803 0.2948 | |||
vt 0.6251 0.3035 | |||
vt 0.7194 0.2854 | |||
vt 0.8764 0.2832 | |||
vt 0.9221 0.2861 | |||
vt 0.3363 0.9565 | |||
vt 0.3464 0.9122 | |||
vt 0.6751 0.2482 | |||
vt 0.6178 0.2499 | |||
vt 0.7179 0.2431 | |||
vt 0.9823 0.2484 | |||
vt 0.9247 0.2452 | |||
vt 0.3935 0.9014 | |||
vt 0.6755 0.1996 | |||
vt 0.6164 0.1941 | |||
vt 0.7201 0.1992 | |||
vt 0.8793 0.2446 | |||
vt 0.9823 0.2060 | |||
vt 0.9257 0.2051 | |||
vt 0.4598 0.8580 | |||
vt 0.4144 0.8579 | |||
vt 0.6819 0.1498 | |||
vt 0.6222 0.1361 | |||
vt 0.7266 0.1555 | |||
vt 0.8831 0.1684 | |||
vt 0.9252 0.1659 | |||
vt 0.4218 0.7790 | |||
vt 0.3934 0.8145 | |||
vt 0.3363 0.7595 | |||
vt 0.8815 0.2060 | |||
vt 0.8720 0.3208 | |||
vt 0.8825 0.1012 | |||
vt 0.9735 0.0816 | |||
vt 0.9718 0.3817 | |||
vt 0.9807 0.2918 | |||
vt 0.4218 0.9370 | |||
vt 0.9810 0.1644 | |||
vn 0.1035 0.8806 0.4623 | |||
vn 0.0964 0.9481 0.3030 | |||
vn 0.0000 0.9780 0.2088 | |||
vn 0.0659 0.9835 0.1683 | |||
vn 0.2325 0.9320 0.2779 | |||
vn 0.0553 0.9960 -0.0702 | |||
vn 0.2827 0.9564 0.0728 | |||
vn 0.1873 0.9776 -0.0961 | |||
vn 0.2421 0.9703 0.0000 | |||
vn 0.0921 0.9772 -0.1913 | |||
vn -0.0277 0.9947 -0.0993 | |||
vn 0.2308 0.9274 -0.2944 | |||
vn 0.2771 0.9572 -0.0837 | |||
vn 0.3724 0.9074 0.1947 | |||
vn 0.0777 0.9770 -0.1985 | |||
vn -0.1094 0.9539 0.2794 | |||
vn 0.0364 0.9844 0.1721 | |||
vn 0.1683 0.9835 0.0659 | |||
vn 0.0674 0.9901 0.1230 | |||
vn 0.4338 0.8823 0.1829 | |||
vn 0.2845 0.9565 0.0649 | |||
vn 0.0886 0.9961 0.0000 | |||
vn 0.2000 0.9789 0.0424 | |||
vn 0.1417 0.9830 0.1171 | |||
vn 0.3021 0.9524 0.0412 | |||
vn -0.0193 0.9986 -0.0493 | |||
vn 0.0000 0.9777 0.2098 | |||
vn 0.0005 0.9781 -0.2083 | |||
vn 0.1879 0.9782 -0.0887 | |||
vn 0.2249 0.0000 0.9744 | |||
vn 0.9783 0.0000 -0.2071 | |||
vn 0.9783 0.0000 0.2071 | |||
vn 0.0000 0.0000 -1.0000 | |||
vn -1.0000 0.0000 0.0000 | |||
vn -0.3645 0.0000 -0.9312 | |||
vn -0.9312 0.0000 -0.3645 | |||
vn -0.9312 0.0000 0.3645 | |||
vn 0.2615 0.7979 -0.5431 | |||
vn 0.5877 0.7979 -0.1341 | |||
vn 0.4713 0.7979 0.3758 | |||
vn -0.0000 0.7979 0.6028 | |||
vn -0.4713 0.7979 0.3758 | |||
vn -0.5877 0.7979 -0.1341 | |||
vn -0.2615 0.7979 -0.5431 | |||
vn -0.1285 0.9864 -0.1025 | |||
vn 0.0929 0.8937 0.4389 | |||
vn -0.4335 0.0407 -0.9002 | |||
vn -0.2867 0.7507 -0.5952 | |||
vn -0.4339 0.0095 -0.9009 | |||
vn -0.4338 0.0209 -0.9008 | |||
vn -0.0408 -0.9956 -0.0848 | |||
vn -0.9741 0.0407 -0.2223 | |||
vn -0.6441 0.7507 -0.1470 | |||
vn -0.9749 0.0095 -0.2225 | |||
vn -0.9747 0.0209 -0.2225 | |||
vn -0.0918 -0.9956 -0.0209 | |||
vn -0.7812 0.0407 0.6230 | |||
vn -0.5165 0.7507 0.4119 | |||
vn -0.7818 0.0095 0.6235 | |||
vn -0.7817 0.0209 0.6234 | |||
vn -0.0736 -0.9956 0.0587 | |||
vn -0.0000 0.0407 0.9992 | |||
vn 0.0000 0.7507 0.6607 | |||
vn 0.0000 0.0095 1.0000 | |||
vn -0.0000 0.0209 0.9998 | |||
vn -0.0000 -0.9956 0.0941 | |||
vn 0.7812 0.0407 0.6230 | |||
vn 0.5165 0.7507 0.4119 | |||
vn 0.7818 0.0095 0.6235 | |||
vn 0.7817 0.0209 0.6234 | |||
vn 0.0736 -0.9956 0.0587 | |||
vn 0.9741 0.0407 -0.2223 | |||
vn 0.6441 0.7507 -0.1470 | |||
vn 0.9749 0.0095 -0.2225 | |||
vn 0.9747 0.0209 -0.2225 | |||
vn 0.0918 -0.9956 -0.0209 | |||
vn 0.4335 0.0407 -0.9002 | |||
vn 0.2867 0.7507 -0.5952 | |||
vn 0.4339 0.0095 -0.9009 | |||
vn 0.4338 0.0209 -0.9008 | |||
vn 0.0408 -0.9956 -0.0848 | |||
vn 0.3918 -0.4298 -0.8135 | |||
vn 0.8803 -0.4298 -0.2009 | |||
vn 0.7059 -0.4298 0.5630 | |||
vn -0.0000 -0.4298 0.9029 | |||
vn -0.7059 -0.4298 0.5630 | |||
vn -0.8803 -0.4298 -0.2009 | |||
vn -0.3918 -0.4298 -0.8135 | |||
vn 0.0210 0.9998 -0.0048 | |||
vn 0.0482 0.9981 -0.0385 | |||
vn -0.0166 0.9914 -0.1301 | |||
vn -0.0090 0.9904 -0.1379 | |||
vn 0.2820 0.9576 0.0597 | |||
vn -0.0000 0.9846 0.1749 | |||
vn -0.0921 0.9772 -0.1913 | |||
vn -0.1734 0.9794 0.1036 | |||
s off | |||
f 1/1/1 7/2/1 6/3/1 | |||
f 2/4/2 8/5/2 7/2/2 | |||
f 4/6/3 8/5/3 3/7/3 | |||
f 5/8/4 9/9/4 4/6/4 | |||
f 6/3/5 12/10/5 11/11/5 | |||
f 35/12/6 25/13/6 26/14/6 | |||
f 7/2/7 37/15/7 12/10/7 | |||
f 10/16/8 13/17/8 9/9/8 | |||
f 12/10/9 15/18/9 11/11/9 | |||
f 35/12/10 17/19/10 33/20/10 | |||
f 13/17/11 19/21/11 18/22/11 | |||
f 16/23/12 20/24/12 15/18/12 | |||
f 17/19/13 21/25/13 16/23/13 | |||
f 17/19/14 23/26/14 22/27/14 | |||
f 26/14/15 24/28/15 23/26/15 | |||
f 1/1/16 2/4/16 7/2/16 | |||
f 2/4/3 3/7/3 8/5/3 | |||
f 4/6/17 9/9/17 8/5/17 | |||
f 5/8/18 10/16/18 9/9/18 | |||
f 6/3/19 7/2/19 12/10/19 | |||
f 25/13/20 39/29/20 9/9/20 | |||
f 38/30/21 12/10/21 37/15/21 | |||
f 10/16/22 14/31/22 13/17/22 | |||
f 12/10/23 16/23/23 15/18/23 | |||
f 8/5/24 36/32/24 7/2/24 | |||
f 38/30/25 17/19/25 16/23/25 | |||
f 13/17/22 14/31/22 19/21/22 | |||
f 16/23/26 21/25/26 20/24/26 | |||
f 17/19/27 22/27/27 21/25/27 | |||
f 17/19/28 26/14/28 23/26/28 | |||
f 26/14/29 19/33/29 24/28/29 | |||
f 26/34/30 18/35/30 19/36/30 | |||
f 26/34/31 13/37/31 18/35/31 | |||
f 25/38/32 9/39/32 13/37/32 | |||
f 22/40/33 31/41/33 21/42/33 | |||
f 6/43/34 28/44/34 27/45/34 | |||
f 15/46/34 28/44/34 11/47/34 | |||
f 21/42/35 30/48/35 20/49/35 | |||
f 20/49/36 29/50/36 15/46/36 | |||
f 22/40/33 23/51/33 32/52/33 | |||
f 6/43/37 27/45/37 1/53/37 | |||
f 46/54/38 34/55/38 47/56/38 | |||
f 47/56/39 34/55/39 67/57/39 | |||
f 67/57/40 34/55/40 72/58/40 | |||
f 72/58/41 34/55/41 52/59/41 | |||
f 52/59/42 34/55/42 57/60/42 | |||
f 57/60/43 34/55/43 62/61/43 | |||
f 62/61/44 34/55/44 46/54/44 | |||
f 40/62/45 41/63/45 39/29/45 | |||
f 39/29/46 8/5/46 9/9/46 | |||
f 38/64/47 42/65/47 33/66/47 | |||
f 65/67/48 42/65/48 66/68/48 | |||
f 65/67/49 44/69/49 43/70/49 | |||
f 81/71/50 45/72/50 77/73/50 | |||
f 62/74/51 45/75/51 63/76/51 | |||
f 37/77/52 66/78/52 38/79/52 | |||
f 60/80/53 66/78/53 61/81/53 | |||
f 60/80/54 64/82/54 65/83/54 | |||
f 58/84/55 81/85/55 80/86/55 | |||
f 57/87/56 63/76/56 58/88/56 | |||
f 56/89/57 37/77/57 36/90/57 | |||
f 55/91/58 61/81/58 56/89/58 | |||
f 54/92/59 60/80/59 55/91/59 | |||
f 79/93/60 58/84/60 80/86/60 | |||
f 52/94/61 58/88/61 53/95/61 | |||
f 76/96/62 36/90/62 41/97/62 | |||
f 75/98/63 56/89/63 76/96/63 | |||
f 75/98/64 54/92/64 55/91/64 | |||
f 73/99/65 79/93/65 83/100/65 | |||
f 73/101/66 52/94/66 53/95/66 | |||
f 71/102/67 41/97/67 40/103/67 | |||
f 70/104/68 76/96/68 71/102/68 | |||
f 70/104/69 74/105/69 75/98/69 | |||
f 68/106/70 83/100/70 82/107/70 | |||
f 67/108/71 73/101/71 68/109/71 | |||
f 51/110/72 40/103/72 35/111/72 | |||
f 50/112/73 71/102/73 51/110/73 | |||
f 49/113/74 70/104/74 50/112/74 | |||
f 78/114/75 68/106/75 82/107/75 | |||
f 47/115/76 68/109/76 48/116/76 | |||
f 42/65/77 35/111/77 33/66/77 | |||
f 43/70/78 51/110/78 42/65/78 | |||
f 44/69/79 50/112/79 43/70/79 | |||
f 45/72/80 78/114/80 77/73/80 | |||
f 46/117/81 48/116/81 45/75/81 | |||
f 44/69/82 78/114/82 49/113/82 | |||
f 49/113/83 82/107/83 69/118/83 | |||
f 82/107/84 74/105/84 69/118/84 | |||
f 83/100/85 54/92/85 74/105/85 | |||
f 79/93/86 59/119/86 54/92/86 | |||
f 80/86/87 64/82/87 59/119/87 | |||
f 64/120/88 77/73/88 44/69/88 | |||
f 35/12/89 40/62/89 25/13/89 | |||
f 7/2/90 36/32/90 37/15/90 | |||
f 35/12/91 26/14/91 17/19/91 | |||
f 25/13/92 40/62/92 39/29/92 | |||
f 38/30/93 16/23/93 12/10/93 | |||
f 8/5/94 41/63/94 36/32/94 | |||
f 38/30/95 33/20/95 17/19/95 | |||
f 26/34/31 25/38/31 13/37/31 | |||
f 22/40/33 32/52/33 31/41/33 | |||
f 6/43/34 11/47/34 28/44/34 | |||
f 15/46/34 29/50/34 28/44/34 | |||
f 21/42/35 31/41/35 30/48/35 | |||
f 20/49/36 30/48/36 29/50/36 | |||
f 39/29/96 41/63/96 8/5/96 | |||
f 38/64/47 66/68/47 42/65/47 | |||
f 65/67/48 43/70/48 42/65/48 | |||
f 65/67/49 64/120/49 44/69/49 | |||
f 81/71/50 63/121/50 45/72/50 | |||
f 62/74/51 46/117/51 45/75/51 | |||
f 37/77/52 61/81/52 66/78/52 | |||
f 60/80/53 65/83/53 66/78/53 | |||
f 60/80/54 59/119/54 64/82/54 | |||
f 58/84/55 63/122/55 81/85/55 | |||
f 57/87/56 62/74/56 63/76/56 | |||
f 56/89/57 61/81/57 37/77/57 | |||
f 55/91/58 60/80/58 61/81/58 | |||
f 54/92/59 59/119/59 60/80/59 | |||
f 79/93/60 53/123/60 58/84/60 | |||
f 52/94/61 57/87/61 58/88/61 | |||
f 76/96/62 56/89/62 36/90/62 | |||
f 75/98/63 55/91/63 56/89/63 | |||
f 75/98/64 74/105/64 54/92/64 | |||
f 73/99/65 53/123/65 79/93/65 | |||
f 73/101/66 72/124/66 52/94/66 | |||
f 71/102/67 76/96/67 41/97/67 | |||
f 70/104/68 75/98/68 76/96/68 | |||
f 70/104/69 69/118/69 74/105/69 | |||
f 68/106/70 73/99/70 83/100/70 | |||
f 67/108/71 72/124/71 73/101/71 | |||
f 51/110/72 71/102/72 40/103/72 | |||
f 50/112/73 70/104/73 71/102/73 | |||
f 49/113/74 69/118/74 70/104/74 | |||
f 78/114/75 48/125/75 68/106/75 | |||
f 47/115/76 67/108/76 68/109/76 | |||
f 42/65/77 51/110/77 35/111/77 | |||
f 43/70/78 50/112/78 51/110/78 | |||
f 44/69/79 49/113/79 50/112/79 | |||
f 45/72/80 48/125/80 78/114/80 | |||
f 46/117/81 47/115/81 48/116/81 | |||
f 44/69/82 77/73/82 78/114/82 | |||
f 49/113/83 78/114/83 82/107/83 | |||
f 82/107/84 83/100/84 74/105/84 | |||
f 83/100/85 79/93/85 54/92/85 | |||
f 79/93/86 80/86/86 59/119/86 | |||
f 80/86/87 81/85/87 64/82/87 | |||
f 64/120/88 81/71/88 77/73/88 |