FreeGlut MacOS Support

This commit is contained in:
Colton Staiduhar
2026-02-17 21:22:16 -05:00
parent a3bac40258
commit ad2175b9a6
2 changed files with 342 additions and 271 deletions

View File

@@ -10,6 +10,9 @@ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
# Declare Project where "GSM_TEMPLATE" is the project name
project(GSM_TEMPLATE LANGUAGES C CXX)
# Use FreeGlut on Macos (Requires X11 to be installed, but doesn't use it)
option(USE_FREEGLUT "Use FreeGLUT on Mac (ignored on Windows)" ON)
# Allow cmake to fetch web repositories
include(FetchContent)
@@ -41,13 +44,28 @@ FetchContent_MakeAvailable(stb_image)
# If using the Windows compiler
if (MSVC)
if (MSVC OR USE_FREEGLUT)
if (APPLE)
find_path(XQUARTZ_INCLUDE_DIR X11/Xlib.h
PATHS /opt/X11/include
NO_DEFAULT_PATH
)
if(NOT XQUARTZ_INCLUDE_DIR)
message(FATAL_ERROR "To use FreeGLUT on Mac, you need XQuartz installed. Please install it from https://www.xquartz.org/ or set the USE_FREEGLUT cache option to OFF")
endif()
endif()
set(CMAKE_POLICY_VERSION_MINIMUM 3.16)
# Download freeglut
FetchContent_Declare(
freeglut
GIT_REPOSITORY https://github.com/freeglut/freeglut.git
GIT_TAG "master"
GIT_TAG "v3.8.0"
GIT_SHALLOW TRUE
GIT_PROGRESS ON
)
@@ -56,6 +74,11 @@ if (MSVC)
set(FREEGLUT_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(FREEGLUT_BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE)
# Force Cocca on Mac
if(APPLE)
set(FREEGLUT_USE_X11 OFF CACHE BOOL "" FORCE)
set(FREEGLUT_COCOA ON CACHE BOOL "" FORCE)
endif()
FetchContent_MakeAvailable(freeglut)
@@ -76,8 +99,8 @@ endif()
# Tell Cmake to find the locations of libraries
find_package(OpenGL REQUIRED)
# Only require glut if on macos
if (APPLE)
# Only require glut if on macos and not using freeglut
if (APPLE AND NOT USE_FREEGLUT)
find_package(GLUT REQUIRED)
endif()
# Define MY_SOURCES to be a list of all the source files for my game
@@ -117,6 +140,37 @@ target_sources("${CMAKE_PROJECT_NAME}" PRIVATE ${MY_SOURCES})
# If on mac
if (APPLE)
# FreeGlut for mac
if (USE_FREEGLUT)
target_sources("${CMAKE_PROJECT_NAME}" PRIVATE "${glad_SOURCE_DIR}/src/glad.c")
target_include_directories("${CMAKE_PROJECT_NAME}" PUBLIC "${glad_SOURCE_DIR}/include")
# Add our include files
target_include_directories("${CMAKE_PROJECT_NAME}" PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include/"
"${freeglut_SOURCE_DIR}/include"
"${glad_SOURCE_DIR}/include"
)
target_compile_definitions("${CMAKE_PROJECT_NAME}" PUBLIC use_freeglut=TRUE)
target_link_libraries("${CMAKE_PROJECT_NAME}"
PRIVATE
OpenGL::GL
freeglut_static
"-framework Cocoa"
"-framework IOKit"
"-framework CoreVideo"
"-lpthread"
stb_image
miniaudio
)
# Native GLUT for Mac
else()
# Add our include files
target_include_directories("${CMAKE_PROJECT_NAME}" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/")
@@ -138,6 +192,7 @@ target_link_libraries("${CMAKE_PROJECT_NAME}"
stb_image
miniaudio
)
endif()
# If on windows

View File

@@ -48,8 +48,6 @@
// #
// #############################################################################
// Libraries
#if defined(use_freeglut)
#include <glad/glad.h>
@@ -61,8 +59,8 @@
#include <miniaudio.h>
// STD
#include <math.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
// Custom includes
@@ -76,14 +74,12 @@
void ProcessKeys(unsigned char, int, int);
void ProcessSpecialKeys(int, int, int);
void MainLoop();
void GlutLoopTimer(int);
// Extended Functionality
void UpdateViewPort();
void DrawSprite();
void LoadUserTextures();
// Miniaudio Engine Declaration
void CreateAudioEngine();
ma_engine engine; // Miniaudio engine
@@ -97,6 +93,25 @@ unsigned int texID;
ma_sound musicSound; // Miniaudio sound object
int lastWinW = 0, lastWinH = 0;
bool running = true;
void CloseCallBack()
{
running = false;
}
/**
* Main Loop Timer
* Wait 16.7ms then generate next frame (~60FPS)
*/
void GlutLoopTimer(int v)
{
// Runs the function specified in glutDisplayFunc
glutPostRedisplay();
// Call the timer again in 16.7 seconds ~ 60 times per second
glutTimerFunc(16.7, GlutLoopTimer, v); // Creates a frame delay that is counted in miliseconds
}
/**
* Main entry point of the application
*/
@@ -115,10 +130,11 @@ int main(int argc, char **argv)
// Setup then create the window
glutInitWindowSize(winW, winH); // window size
glutInitWindowPosition(0, 0);
glutCreateWindow("Transform Example");
glutCreateWindow("Transform Example - Using Native Glut");
// This line only needs to run when glad is in use
#if defined(use_freeglut)
glutSetWindowTitle("Transform Example - using FreeGLUT");
if (!gladLoadGL()) { }
#endif
@@ -147,33 +163,40 @@ int main(int argc, char **argv)
// Declare Special Keys Keyboard Interrupt
glutSpecialFunc(ProcessSpecialKeys);
#ifndef use_freeglut
// Setup a timer to run the main loop at an interval
// (This call will call the GlutLoopTimer() function immediately)
glutTimerFunc(0, GlutLoopTimer, 0);
#endif
std::cout << "Started";
std::cout << "Started" << std::endl;
fflush(stdout);
// Start the Glut Loop (Calls the funtions above repeatedly)
glutMainLoop();
std::cout << "exited";
#if defined(use_freeglut)
// FreeGlut allows for manual updating of the main loop
// So we can call the main loop in a while loop and tell the loop when to stop
// Tell FreeGlut to do nothing on window X press
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
// Run callback when window X is pressed
glutCloseFunc(CloseCallBack);
// Our loop, calls the funtion in glutDisplayFunc repeatedly until running = false
while (running)
glutMainLoopEvent();
#else
// Start the Glut Loop (Calls the funtions above repeatedly)
glutMainLoop();
#endif
std::cout << "exited" << std::endl;
fflush(stdout);
return 0;
}
/**
* Main Loop Timer
* Wait 16.7ms then generate next frame (~60FPS)
*/
void GlutLoopTimer(int v)
{
// Runs the function specified in glutDisplayFunc
glutPostRedisplay();
// Call the timer again in 16.7 seconds ~ 60 times per second
glutTimerFunc(16.7, GlutLoopTimer, v); // Creates a frame delay that is counted in miliseconds
}
/**
* Function to update the viewport to the size of the window
*/
@@ -202,26 +225,22 @@ void UpdateViewPort()
*/
void ProcessSpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_LEFT)
{
if (key == GLUT_KEY_LEFT) {
moveX = -10;
movePressed = true;
}
if (key == GLUT_KEY_RIGHT)
{
if (key == GLUT_KEY_RIGHT) {
moveX = 10;
movePressed = true;
}
if (key == GLUT_KEY_UP)
{
if (key == GLUT_KEY_UP) {
moveY = 10;
movePressed = true;
}
if (key == GLUT_KEY_DOWN)
{
if (key == GLUT_KEY_DOWN) {
moveY = -10;
movePressed = true;
}
@@ -233,8 +252,7 @@ void ProcessSpecialKeys(int key, int x, int y)
*/
void ProcessKeys(unsigned char key, int x, int y)
{
switch (key)
{
switch (key) {
case 'q':
rotX += 1;
break;
@@ -274,8 +292,7 @@ void ProcessKeys(unsigned char key, int x, int y)
void CreateAudioEngine()
{
ma_result result = ma_engine_init(NULL, &engine);
if (result != MA_SUCCESS)
{
if (result != MA_SUCCESS) {
std::cout << "Failed to setup the miniaudio engine\n";
fflush(stdout);
}
@@ -287,8 +304,7 @@ void CreateAudioEngine()
0,
NULL,
NULL,
&musicSound
);
&musicSound);
}
/**
@@ -302,8 +318,7 @@ void MainLoop()
int winH = glutGet(GLUT_WINDOW_HEIGHT);
// If Changed, update the view port
if (winW != lastWinW || winH != lastWinH)
{
if (winW != lastWinW || winH != lastWinH) {
UpdateViewPort();
}
@@ -313,16 +328,14 @@ void MainLoop()
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// If scale oneshot is set, scale the image
if (scalePressed)
{
if (scalePressed) {
glScalef(scale, scale, scale);
scalePressed = false;
scale = 1;
}
// If rotation oneshot is set, rotate the image
if (rotPressed)
{
if (rotPressed) {
glRotatef((GLfloat)rotX, 1.0, 0.0, 0.0);
glRotatef((GLfloat)rotY, 0.0, 1.0, 0.0);
glRotatef((GLfloat)rotZ, 0.0, 0.0, 1.0);
@@ -330,8 +343,7 @@ void MainLoop()
rotX = rotY = rotZ = 0;
}
// If move oneshot is set, move the image and set move back to 0
if (movePressed)
{
if (movePressed) {
glTranslatef(moveX, moveY, 0);
movePressed = false;
moveX = moveY = 0;
@@ -344,6 +356,11 @@ void MainLoop()
// Swap buffers to display the new frame
glutSwapBuffers();
// With freeglut, we can trigger screen update right after we are done
#if defined(use_freeglut)
glutPostRedisplay();
#endif
}
/**
@@ -364,7 +381,6 @@ void DrawSprite()
glBegin(GL_POLYGON);
{
glTexCoord2f(0.0, 0.0);
glVertex3f(-50, -50, 0);
glTexCoord2f(1.0, 0.0);