Import Upstream version 3.4.0
This commit is contained in:
commit
abf2402fc1
|
@ -0,0 +1,35 @@
|
||||||
|
name: GNU/Linux (X11) build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install libgl-dev libglu1-mesa-dev libx11-dev libxrandr-dev libxi-dev
|
||||||
|
|
||||||
|
- name: generate makefile
|
||||||
|
run: cmake -DCMAKE_BUILD_TYPE=Release .
|
||||||
|
|
||||||
|
- name: build freeglut
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: stage install
|
||||||
|
run: DESTDIR=freeglut-instdir make install
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: freeglut-instdir
|
||||||
|
path: freeglut-instdir
|
||||||
|
|
||||||
|
# vi:ts=2 sts=2 sw=2 expandtab:
|
|
@ -0,0 +1,34 @@
|
||||||
|
name: MacOS X (X11) build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: install dependencies
|
||||||
|
run: |
|
||||||
|
brew install libx11 libxi libxrandr libxxf86vm pkg-config mesa
|
||||||
|
|
||||||
|
- name: generate makefile
|
||||||
|
run: cmake -DCMAKE_BUILD_TYPE=Release -DFREEGLUT_BUILD_DEMOS=OFF -DOPENGL_gl_LIBRARY=/usr/local/lib/libGL.dylib .
|
||||||
|
|
||||||
|
- name: build freeglut
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: stage install
|
||||||
|
run: DESTDIR=freeglut-instdir make install
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: freeglut-instdir
|
||||||
|
path: freeglut-instdir
|
||||||
|
|
||||||
|
# vi:ts=2 sts=2 sw=2 expandtab:
|
|
@ -0,0 +1,35 @@
|
||||||
|
name: Windows MSVC build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: prepare environment
|
||||||
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
|
|
||||||
|
- name: generate project files
|
||||||
|
run: cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_GENERATOR="Visual Studio 17 2022" -DCMAKE_INSTALL_PREFIX=freeglut-instdir .
|
||||||
|
|
||||||
|
- name: build freeglut
|
||||||
|
run: cmake --build . --config Release
|
||||||
|
|
||||||
|
- name: stage install
|
||||||
|
run: cmake --install .
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: freeglut-instdir
|
||||||
|
path: |
|
||||||
|
freeglut-instdir
|
||||||
|
bin
|
||||||
|
|
||||||
|
# vi:ts=2 sts=2 sw=2 expandtab:
|
|
@ -0,0 +1,39 @@
|
||||||
|
Makefile.in
|
||||||
|
Makefile
|
||||||
|
INSTALL
|
||||||
|
.deps
|
||||||
|
aclocal.m4
|
||||||
|
autom4te.cache
|
||||||
|
compile
|
||||||
|
config.guess
|
||||||
|
config.sub
|
||||||
|
configure
|
||||||
|
configure.cache
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
config.h
|
||||||
|
depcomp
|
||||||
|
install-sh
|
||||||
|
ltmain.sh
|
||||||
|
missing
|
||||||
|
stamp-h1
|
||||||
|
*.tar
|
||||||
|
*.tar.gz
|
||||||
|
*.tar.bz2
|
||||||
|
*.zip
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*~
|
||||||
|
*.swp
|
||||||
|
cross-android
|
||||||
|
cross-woe
|
||||||
|
native
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.a
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
|
freeglut.pc
|
||||||
|
freeglut.rc
|
||||||
|
FreeGLUT/
|
|
@ -0,0 +1,51 @@
|
||||||
|
Current maintainers: John F. Fay, Diederick C. Niehorster, John Tsiombikas
|
||||||
|
|
||||||
|
|
||||||
|
Pawel W. Olszta <olszta@sourceforge.net>
|
||||||
|
the person to be blamed for freeglut
|
||||||
|
|
||||||
|
Andreas Umbach <marvin@dataway.ch>
|
||||||
|
the first person to contribute to the freeglut project,
|
||||||
|
contributed the cube and sphere geometry code
|
||||||
|
|
||||||
|
Steve Baker <sjbaker1@airmail.net>
|
||||||
|
joystick code (from his great PLIB), numerous hints
|
||||||
|
tips on the freeglut usability
|
||||||
|
and for taking the project over when Pawel bowed out
|
||||||
|
|
||||||
|
Christopher John Purnell
|
||||||
|
Don Heyse
|
||||||
|
Dave McClurg
|
||||||
|
John F. Fay
|
||||||
|
Norman Vine
|
||||||
|
Daniel Wagner
|
||||||
|
Sven Panne <sven.panne@aedion.de>
|
||||||
|
contributing to the project, using the product, and generally keeping it going
|
||||||
|
|
||||||
|
Brian Paul
|
||||||
|
Eric Sandall
|
||||||
|
giving us the oomph! to make an official release
|
||||||
|
|
||||||
|
James 'J.C.' Jones
|
||||||
|
designing the new website
|
||||||
|
|
||||||
|
John Tsiombikas <nuclear@member.fsf.org>
|
||||||
|
mostly on the UNIX/X11 side of things.
|
||||||
|
|
||||||
|
Sylvain Beucler
|
||||||
|
support for Android, X11/EGL, OpenGL(ES) 2.x, misc fixes
|
||||||
|
|
||||||
|
Manuel Bachmann
|
||||||
|
support for Wayland
|
||||||
|
|
||||||
|
Diederick C. Niehorster
|
||||||
|
Chris Marshall
|
||||||
|
Clive McCarthy
|
||||||
|
Eero Pajarre
|
||||||
|
Florian Echtler
|
||||||
|
Matti Lehtonen
|
||||||
|
|
||||||
|
Vincent Simonetti
|
||||||
|
support for BlackBerry
|
||||||
|
|
||||||
|
...and all the opengl-gamedev-l people that made Pawel start this project :)
|
|
@ -0,0 +1,672 @@
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0 FATAL_ERROR)
|
||||||
|
PROJECT(freeglut C)
|
||||||
|
|
||||||
|
# for multiarch LIBDIR support (requires cmake>=2.8.8)
|
||||||
|
INCLUDE(GNUInstallDirs)
|
||||||
|
|
||||||
|
# NOTE: On Windows and Cygwin, the dll's are placed in the
|
||||||
|
# CMAKE_RUNTIME_OUTPUT_DIRECTORY, while their corresponding import
|
||||||
|
# libraries end up in CMAKE_ARCHIVE_OUTPUT_DIRECTORY. On other
|
||||||
|
# platforms, such as Linux, the shared libraries are put in
|
||||||
|
# CMAKE_ARCHIVE_OUTPUT_DIRECTORY instead.
|
||||||
|
# Static libraries end up in CMAKE_ARCHIVE_OUTPUT_DIRECTORY on all
|
||||||
|
# platforms.
|
||||||
|
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||||
|
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
|
||||||
|
# setup version numbers
|
||||||
|
# XXX: Update these for each release!
|
||||||
|
set(VERSION_MAJOR 3)
|
||||||
|
set(VERSION_MINOR 4)
|
||||||
|
set(VERSION_PATCH 0)
|
||||||
|
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
|
||||||
|
|
||||||
|
# Update fg_version.h to match the versions number here in cmake
|
||||||
|
CONFIGURE_FILE(src/fg_version.h.in src/fg_version.h)
|
||||||
|
|
||||||
|
# shared lib version numbers (XXX: change before release)
|
||||||
|
set(SO_MAJOR 3) # increment on backwards incompatible API/ABI changes
|
||||||
|
set(SO_MINOR 12) # increment on backwards compatible API additions
|
||||||
|
set(SO_REV 0) # increment if only internal changes happened between releases
|
||||||
|
|
||||||
|
# FREEGLUT_BUILD_SHARED_LIBS is already a standard CMake variable, but we need to
|
||||||
|
# re-declare it here so it will show up in the GUI.
|
||||||
|
# by default, we want to build both
|
||||||
|
OPTION(FREEGLUT_BUILD_SHARED_LIBS "Build FreeGLUT shared library." ON)
|
||||||
|
OPTION(FREEGLUT_BUILD_STATIC_LIBS "Build FreeGLUT static library." ON)
|
||||||
|
|
||||||
|
# option for whether warnings and errors should be printed
|
||||||
|
OPTION(FREEGLUT_PRINT_ERRORS "Lib prints errors to stderr" ON)
|
||||||
|
#MARK_AS_ADVANCED(FREEGLUT_PRINT_ERRORS)
|
||||||
|
OPTION(FREEGLUT_PRINT_WARNINGS "Lib prints warnings to stderr" ON)
|
||||||
|
#MARK_AS_ADVANCED(FREEGLUT_PRINT_WARNINGS)
|
||||||
|
|
||||||
|
# option to also copy .pdb files to install directory when executing
|
||||||
|
# INSTALL target
|
||||||
|
IF(MSVC)
|
||||||
|
OPTION(INSTALL_PDB "Also install .pdb files" ON)
|
||||||
|
ELSE()
|
||||||
|
SET(INSTALL_PDB OFF)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# OpenGL ES support
|
||||||
|
IF(ANDROID)
|
||||||
|
OPTION(FREEGLUT_GLES "Use OpenGL ES (requires EGL)" ON)
|
||||||
|
ELSE()
|
||||||
|
OPTION(FREEGLUT_GLES "Use OpenGL ES (requires EGL)" OFF)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# option to build either as "glut" (ON) or "freeglut" (OFF)
|
||||||
|
IF(WIN32)
|
||||||
|
OPTION(FREEGLUT_REPLACE_GLUT "Be a replacement for GLUT" OFF)
|
||||||
|
ELSE()
|
||||||
|
OPTION(FREEGLUT_REPLACE_GLUT "Be a replacement for GLUT" ON)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(NOT WIN32)
|
||||||
|
# Wayland support
|
||||||
|
OPTION(FREEGLUT_WAYLAND "Use Wayland (no X11)" OFF)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
|
SET(FREEGLUT_HEADERS
|
||||||
|
include/GL/freeglut.h
|
||||||
|
include/GL/freeglut_ucall.h
|
||||||
|
include/GL/freeglut_ext.h
|
||||||
|
include/GL/freeglut_std.h
|
||||||
|
)
|
||||||
|
IF(FREEGLUT_REPLACE_GLUT)
|
||||||
|
LIST(APPEND FREEGLUT_HEADERS
|
||||||
|
include/GL/glut.h
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
SET(FREEGLUT_SRCS
|
||||||
|
${FREEGLUT_HEADERS}
|
||||||
|
src/fg_callbacks.c
|
||||||
|
src/fg_cursor.c
|
||||||
|
src/fg_display.c
|
||||||
|
src/fg_ext.c
|
||||||
|
src/fg_font_data.c
|
||||||
|
src/fg_gamemode.c
|
||||||
|
src/fg_geometry.c
|
||||||
|
src/fg_gl2.c
|
||||||
|
src/fg_gl2.h
|
||||||
|
src/fg_init.c
|
||||||
|
src/fg_init.h
|
||||||
|
src/fg_internal.h
|
||||||
|
src/fg_callback_macros.h
|
||||||
|
src/fg_input_devices.c
|
||||||
|
src/fg_joystick.c
|
||||||
|
src/fg_main.c
|
||||||
|
src/fg_misc.c
|
||||||
|
src/fg_overlay.c
|
||||||
|
src/fg_spaceball.c
|
||||||
|
src/fg_state.c
|
||||||
|
src/fg_stroke_mono_roman.c
|
||||||
|
src/fg_stroke_roman.c
|
||||||
|
src/fg_structure.c
|
||||||
|
src/fg_teapot.c
|
||||||
|
src/fg_teapot_data.h
|
||||||
|
src/fg_videoresize.c
|
||||||
|
src/fg_window.c
|
||||||
|
)
|
||||||
|
# TODO: OpenGL ES requires a compatible version of these files:
|
||||||
|
IF(NOT FREEGLUT_GLES)
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/fg_font.c
|
||||||
|
src/fg_menu.c
|
||||||
|
)
|
||||||
|
ELSE()
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/gles_stubs.c
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(WIN32)
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/mswin/fg_cursor_mswin.c
|
||||||
|
src/mswin/fg_display_mswin.c
|
||||||
|
src/mswin/fg_ext_mswin.c
|
||||||
|
src/mswin/fg_gamemode_mswin.c
|
||||||
|
src/mswin/fg_init_mswin.c
|
||||||
|
src/mswin/fg_internal_mswin.h
|
||||||
|
src/mswin/fg_input_devices_mswin.c
|
||||||
|
src/mswin/fg_joystick_mswin.c
|
||||||
|
src/mswin/fg_main_mswin.c
|
||||||
|
src/mswin/fg_menu_mswin.c
|
||||||
|
src/mswin/fg_spaceball_mswin.c
|
||||||
|
src/mswin/fg_state_mswin.c
|
||||||
|
src/mswin/fg_structure_mswin.c
|
||||||
|
src/mswin/fg_window_mswin.c
|
||||||
|
src/mswin/fg_cmap_mswin.c
|
||||||
|
${CMAKE_BINARY_DIR}/freeglut.rc # generated below from freeglut.rc.in
|
||||||
|
)
|
||||||
|
IF (MSVC AND NOT CMAKE_CL_64)
|
||||||
|
# .def file only for 32bit Windows builds (TODO: MSVC only right
|
||||||
|
# now, needed for any other Windows platform?)
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
${CMAKE_BINARY_DIR}/freeglutdll.def # generated below from src/freeglutdll.def.in
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
ELSEIF(ANDROID OR BLACKBERRY)
|
||||||
|
# BlackBerry and Android share some similar design concepts and ideas, as with many mobile devices.
|
||||||
|
# As such, some classes can be shared between the two. XXX: Possibly rename shareable classes to
|
||||||
|
# a more generic name. *_stub? *_mobile?
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/android/fg_cursor_android.c
|
||||||
|
src/android/fg_ext_android.c
|
||||||
|
src/android/fg_gamemode_android.c
|
||||||
|
src/android/fg_joystick_android.c
|
||||||
|
src/android/fg_spaceball_android.c
|
||||||
|
)
|
||||||
|
IF(ANDROID)
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/android/native_app_glue/android_native_app_glue.c
|
||||||
|
src/android/native_app_glue/android_native_app_glue.h
|
||||||
|
src/android/fg_internal_android.h
|
||||||
|
src/android/fg_init_android.c
|
||||||
|
src/android/fg_input_devices_android.c
|
||||||
|
src/android/fg_main_android.c
|
||||||
|
src/android/fg_main_android.h
|
||||||
|
src/android/fg_runtime_android.c
|
||||||
|
src/android/fg_state_android.c
|
||||||
|
src/android/fg_structure_android.c
|
||||||
|
src/android/fg_window_android.c
|
||||||
|
)
|
||||||
|
ELSE()
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/blackberry/fg_internal_blackberry.h
|
||||||
|
src/blackberry/fg_init_blackberry.c
|
||||||
|
src/x11/fg_input_devices_x11.c
|
||||||
|
src/blackberry/fg_main_blackberry.c
|
||||||
|
src/blackberry/fg_state_blackberry.c
|
||||||
|
src/blackberry/fg_structure_blackberry.c
|
||||||
|
src/blackberry/fg_window_blackberry.c
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
ELSE()
|
||||||
|
# UNIX (Wayland)
|
||||||
|
IF(FREEGLUT_WAYLAND)
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/wayland/fg_cursor_wl.c
|
||||||
|
src/wayland/fg_ext_wl.c
|
||||||
|
src/wayland/fg_gamemode_wl.c
|
||||||
|
src/wayland/fg_init_wl.c
|
||||||
|
src/wayland/fg_internal_wl.h
|
||||||
|
src/wayland/fg_input_devices_wl.c
|
||||||
|
src/wayland/fg_main_wl.c
|
||||||
|
src/wayland/fg_state_wl.c
|
||||||
|
src/wayland/fg_structure_wl.c
|
||||||
|
src/wayland/fg_window_wl.c
|
||||||
|
# font, serial port & joystick code are agnostic
|
||||||
|
src/x11/fg_glutfont_definitions_x11.c
|
||||||
|
src/x11/fg_input_devices_x11.c
|
||||||
|
src/x11/fg_joystick_x11.c
|
||||||
|
)
|
||||||
|
# UNIX (X11)
|
||||||
|
ELSE()
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/x11/fg_cursor_x11.c
|
||||||
|
src/x11/fg_ext_x11.c
|
||||||
|
src/x11/fg_gamemode_x11.c
|
||||||
|
src/x11/fg_glutfont_definitions_x11.c
|
||||||
|
src/x11/fg_init_x11.c
|
||||||
|
src/x11/fg_internal_x11.h
|
||||||
|
src/x11/fg_input_devices_x11.c
|
||||||
|
src/x11/fg_joystick_x11.c
|
||||||
|
src/x11/fg_main_x11.c
|
||||||
|
src/x11/fg_menu_x11.c
|
||||||
|
src/x11/fg_spaceball_x11.c
|
||||||
|
src/x11/fg_state_x11.c
|
||||||
|
src/x11/fg_structure_x11.c
|
||||||
|
src/x11/fg_window_x11.c
|
||||||
|
src/x11/fg_xinput_x11.c
|
||||||
|
src/x11/fg_cmap_x11.c
|
||||||
|
)
|
||||||
|
IF(NOT(FREEGLUT_GLES))
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/x11/fg_internal_x11_glx.h
|
||||||
|
src/x11/fg_display_x11_glx.c
|
||||||
|
src/x11/fg_state_x11_glx.c
|
||||||
|
src/x11/fg_state_x11_glx.h
|
||||||
|
src/x11/fg_window_x11_glx.c
|
||||||
|
src/x11/fg_window_x11_glx.h
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# OpenGL ES requires EGL, and so does Wayland
|
||||||
|
IF(FREEGLUT_GLES OR FREEGLUT_WAYLAND)
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/egl/fg_internal_egl.h
|
||||||
|
src/egl/fg_display_egl.c
|
||||||
|
src/egl/fg_ext_egl.c
|
||||||
|
src/egl/fg_init_egl.c
|
||||||
|
src/egl/fg_init_egl.h
|
||||||
|
src/egl/fg_state_egl.c
|
||||||
|
src/egl/fg_state_egl.h
|
||||||
|
src/egl/fg_structure_egl.c
|
||||||
|
src/egl/fg_structure_egl.h
|
||||||
|
src/egl/fg_window_egl.c
|
||||||
|
src/egl/fg_window_egl.h
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
INCLUDE(CheckIncludeFiles)
|
||||||
|
IF(UNIX AND NOT(ANDROID OR BLACKBERRY OR FREEGLUT_WAYLAND))
|
||||||
|
FIND_PACKAGE(X11 REQUIRED)
|
||||||
|
INCLUDE_DIRECTORIES(${X11_X11_INCLUDE_PATH})
|
||||||
|
LIST(APPEND LIBS ${X11_X11_LIB})
|
||||||
|
IF(X11_Xrandr_FOUND)
|
||||||
|
SET(HAVE_X11_EXTENSIONS_XRANDR_H TRUE)
|
||||||
|
LIST(APPEND LIBS ${X11_Xrandr_LIB})
|
||||||
|
ENDIF()
|
||||||
|
IF(X11_xf86vmode_FOUND)
|
||||||
|
SET(HAVE_X11_EXTENSIONS_XF86VMODE_H TRUE)
|
||||||
|
LIST(APPEND LIBS ${X11_Xxf86vm_LIB})
|
||||||
|
ENDIF()
|
||||||
|
IF(X11_Xinput_FOUND)
|
||||||
|
# Needed for multi-touch:
|
||||||
|
CHECK_INCLUDE_FILES("${X11_Xinput_INCLUDE_PATH}/X11/extensions/XInput2.h" HAVE_X11_EXTENSIONS_XINPUT2_H)
|
||||||
|
LIST(APPEND LIBS ${X11_Xinput_LIB})
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(FATAL_ERROR "Missing X11's XInput2.h (X11/extensions/XInput2.h)")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# FreeBSD and NetBSD joystick code uses libusbhid
|
||||||
|
IF(CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
|
||||||
|
IF(HAVE_USBHID_H)
|
||||||
|
LIST(APPEND LIBS "-lusbhid")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# For OpenGL ES (GLES): compile with -DFREEGLUT_GLES to cleanly
|
||||||
|
# bootstrap headers inclusion in freeglut_std.h; this constant also
|
||||||
|
# need to be defined in client applications (e.g. through pkg-config),
|
||||||
|
# but do use GLES constants directly for all other needs
|
||||||
|
# GLES1 and GLES2 libraries are compatible and can be co-linked.
|
||||||
|
IF(FREEGLUT_GLES)
|
||||||
|
LIST(APPEND PUBLIC_DEFINITIONS -DFREEGLUT_GLES)
|
||||||
|
LIST(APPEND LIBS GLESv2 GLESv1_CM EGL)
|
||||||
|
ELSE()
|
||||||
|
# On OS X, we need to link against the X11 OpenGL libraries, NOT the Cocoa OpenGL libraries.
|
||||||
|
# To do that, you need to manually find two of the libraries before calling FindOpenGL
|
||||||
|
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||||
|
# get path where X11 libs are
|
||||||
|
get_filename_component(X11_LIB_PATH ${X11_Xi_LIB} DIRECTORY)
|
||||||
|
|
||||||
|
find_library(OPENGL_gl_LIBRARY NAME GL HINTS ${X11_LIB_PATH})
|
||||||
|
find_library(OPENGL_glu_LIBRARY NAME GLU HINTS ${X11_LIB_PATH})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
LIST(APPEND LIBS ${OPENGL_gl_LIBRARY})
|
||||||
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# For Wayland: compile with -DFREEGLUT_WAYLAND and pull EGL
|
||||||
|
IF(FREEGLUT_WAYLAND)
|
||||||
|
ADD_DEFINITIONS(-DFREEGLUT_WAYLAND)
|
||||||
|
LIST(APPEND LIBS wayland-client wayland-cursor wayland-egl EGL xkbcommon)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# lib m for math, not needed on windows
|
||||||
|
IF (NOT WIN32)
|
||||||
|
# For compilation:
|
||||||
|
LIST(APPEND LIBS m)
|
||||||
|
# For CHECK_FUNCTION_EXISTS:
|
||||||
|
LIST(APPEND CMAKE_REQUIRED_LIBRARIES m)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(WIN32)
|
||||||
|
# hide insecure CRT warnings, common practice
|
||||||
|
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
IF(MSVC)
|
||||||
|
SET( CMAKE_DEBUG_POSTFIX "d" )
|
||||||
|
ENDIF(MSVC)
|
||||||
|
|
||||||
|
IF(NOT(MSVC_VERSION LESS "1600"))
|
||||||
|
# minimum requirement for WM_TOUCH device
|
||||||
|
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0601)
|
||||||
|
ADD_DEFINITIONS(-DWINVER=0x0601)
|
||||||
|
ELSEIF(NOT(MSVC_VERSION LESS "1300"))
|
||||||
|
# minimum requirement for spaceball device
|
||||||
|
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501)
|
||||||
|
ADD_DEFINITIONS(-DWINVER=0x0501)
|
||||||
|
ELSE()
|
||||||
|
# enable the use of Win2000 APIs (needed for really old compilers like MSVC6)
|
||||||
|
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0500)
|
||||||
|
ADD_DEFINITIONS(-DWINVER=0x0500)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||||
|
IF(NOT(ANDROID OR BLACKBERRY OR FREEGLUT_WAYLAND))
|
||||||
|
# not setting -ansi as EGL/KHR headers doesn't support it
|
||||||
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
|
||||||
|
IF(ANDROID)
|
||||||
|
# -landroid for ANativeWindow
|
||||||
|
# -llog for native Android logging
|
||||||
|
LIST(APPEND LIBS android log)
|
||||||
|
ELSEIF(BLACKBERRY)
|
||||||
|
# -lbps for event loop
|
||||||
|
# -screen for native screen
|
||||||
|
LIST(APPEND LIBS bps screen)
|
||||||
|
|
||||||
|
if(NOT PLAYBOOK)
|
||||||
|
# -lslog2 for logging
|
||||||
|
# -pps for low-level screen manipulation
|
||||||
|
LIST(APPEND LIBS slog2 pps)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
INCLUDE(CheckFunctionExists)
|
||||||
|
INCLUDE(CheckTypeSize)
|
||||||
|
INCLUDE(CheckCCompilerFlag)
|
||||||
|
CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H)
|
||||||
|
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
|
||||||
|
CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H)
|
||||||
|
CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H)
|
||||||
|
CHECK_INCLUDE_FILES(sys/param.h HAVE_SYS_PARAM_H)
|
||||||
|
CHECK_INCLUDE_FILES(sys/ioctl.h HAVE_SYS_IOCTL_H)
|
||||||
|
CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H)
|
||||||
|
CHECK_INCLUDE_FILES(usbhid.h HAVE_USBHID_H)
|
||||||
|
CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
|
||||||
|
CHECK_FUNCTION_EXISTS(XParseGeometry HAVE_XPARSEGEOMETRY)
|
||||||
|
IF (NOT HAVE_XPARSEGEOMETRY)
|
||||||
|
LIST(APPEND FREEGLUT_SRCS
|
||||||
|
src/util/xparsegeometry_repl.c
|
||||||
|
src/util/xparsegeometry_repl.h)
|
||||||
|
SET(NEED_XPARSEGEOMETRY_IMPL TRUE)
|
||||||
|
ENDIF()
|
||||||
|
# decide on suitable type for internal time keeping, 64-bit if possible
|
||||||
|
CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H)
|
||||||
|
CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H)
|
||||||
|
IF (NOT (HAVE_STDINT_H OR HAVE_INTTYPES_H))
|
||||||
|
IF (MSVC)
|
||||||
|
# Some old Microsoft VC releases don't support unsigned long
|
||||||
|
# long, but all we care about is support for unsigned __int64 on
|
||||||
|
# MSVC, so test for presence of that type
|
||||||
|
CHECK_TYPE_SIZE("unsigned __int64" U__INT64 BUILTIN_TYPES_ONLY)
|
||||||
|
ELSEIF()
|
||||||
|
CHECK_TYPE_SIZE("unsigned long long" ULONG_LONG BUILTIN_TYPES_ONLY)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# The generated config.h is placed in the project's build directory, just to
|
||||||
|
# ensure that all CMake-generated files are kept away from the main source tree.
|
||||||
|
# As a result, the build directory must to be added to the include path list.
|
||||||
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_BINARY_DIR}/config.h)
|
||||||
|
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
|
||||||
|
IF(WIN32)
|
||||||
|
# we also have to generate freeglut.rc, which contains the version
|
||||||
|
# number
|
||||||
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/freeglut.rc.in ${CMAKE_BINARY_DIR}/freeglut.rc)
|
||||||
|
IF (MSVC AND NOT CMAKE_CL_64)
|
||||||
|
# .def file only for 32bit Windows builds with Visual Studio
|
||||||
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/src/freeglutdll.def.in ${CMAKE_BINARY_DIR}/freeglutdll.def)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(FREEGLUT_BUILD_SHARED_LIBS)
|
||||||
|
ADD_LIBRARY(freeglut SHARED ${FREEGLUT_SRCS})
|
||||||
|
ENDIF()
|
||||||
|
IF(FREEGLUT_BUILD_STATIC_LIBS)
|
||||||
|
ADD_LIBRARY(freeglut_static STATIC ${FREEGLUT_SRCS})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
|
SET(LIBNAME freeglut)
|
||||||
|
IF(WIN32)
|
||||||
|
IF(FREEGLUT_REPLACE_GLUT)
|
||||||
|
SET(LIBNAME glut)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
LIST(APPEND LIBS winmm gdi32)
|
||||||
|
IF(FREEGLUT_BUILD_SHARED_LIBS)
|
||||||
|
TARGET_COMPILE_DEFINITIONS(freeglut PRIVATE FREEGLUT_EXPORTS)
|
||||||
|
SET_TARGET_PROPERTIES(freeglut PROPERTIES OUTPUT_NAME ${LIBNAME})
|
||||||
|
ENDIF()
|
||||||
|
IF(FREEGLUT_BUILD_STATIC_LIBS)
|
||||||
|
TARGET_COMPILE_DEFINITIONS(freeglut_static PUBLIC FREEGLUT_STATIC)
|
||||||
|
IF(FREEGLUT_REPLACE_GLUT)
|
||||||
|
SET_TARGET_PROPERTIES(freeglut_static PROPERTIES OUTPUT_NAME ${LIBNAME})
|
||||||
|
ENDIF()
|
||||||
|
# need to set machine:x64 for linker, at least for VC10, and
|
||||||
|
# doesn't hurt for older compilers:
|
||||||
|
# http://public.kitware.com/Bug/view.php?id=11240#c22768
|
||||||
|
IF (CMAKE_CL_64)
|
||||||
|
SET_TARGET_PROPERTIES(freeglut_static PROPERTIES STATIC_LIBRARY_FLAGS "/machine:x64")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ELSE()
|
||||||
|
# on UNIX we need to make sure:
|
||||||
|
# - all shared libraries must have a soname/version, see :
|
||||||
|
# http://sourceware.org/autobook/autobook/autobook_91.html#SEC91
|
||||||
|
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
|
# Current: -version-info 12:0:9 -> 3.9.0
|
||||||
|
# Note: most platforms now prefer the latter major.minor.revision form
|
||||||
|
# (e.g. FreeBSD, cf. http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8765),
|
||||||
|
# or special-cased FreeGLUT long ago (e.g. .so.4 on OpenBSD), so
|
||||||
|
# the lack of support for current:revision:age in CMake should
|
||||||
|
# not be a problem.
|
||||||
|
# - the output library should be named glut so it'll be linkable with -lglut
|
||||||
|
# (unless FREEGLUT_REPLACE_GLUT is false).
|
||||||
|
# - the shared library should link to the dependency libraries so that the user
|
||||||
|
# won't have to link them explicitly (they shouldn't have to know that we depend
|
||||||
|
# on Xrandr or Xxf86vm)
|
||||||
|
IF(FREEGLUT_GLES)
|
||||||
|
SET(LIBNAME freeglut-gles)
|
||||||
|
ELSE()
|
||||||
|
IF(FREEGLUT_REPLACE_GLUT)
|
||||||
|
SET(LIBNAME glut)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(FREEGLUT_BUILD_SHARED_LIBS)
|
||||||
|
SET_TARGET_PROPERTIES(freeglut PROPERTIES VERSION ${SO_MAJOR}.${SO_MINOR}.${SO_REV} SOVERSION ${SO_MAJOR} OUTPUT_NAME ${LIBNAME})
|
||||||
|
ENDIF()
|
||||||
|
IF(FREEGLUT_BUILD_STATIC_LIBS)
|
||||||
|
SET_TARGET_PROPERTIES(freeglut_static PROPERTIES OUTPUT_NAME ${LIBNAME})
|
||||||
|
ENDIF()
|
||||||
|
IF(ANDROID)
|
||||||
|
# Not in CMake toolchain file, because the toolchain
|
||||||
|
# file is called several times and generally doesn't
|
||||||
|
# seem to be meant for modifying CFLAGS:
|
||||||
|
# '-mandroid' is not mandatory but doesn't hurt
|
||||||
|
# '-O0 -gstabs+' helps the currently buggy GDB port
|
||||||
|
# Too late to manipulate ENV: SET(ENV{CFLAGS} "$ENV{CFLAGS} -mandroid")
|
||||||
|
# Not using _INIT variables, they seem to be used internally only
|
||||||
|
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mandroid")
|
||||||
|
ENDIF()
|
||||||
|
CHECK_C_COMPILER_FLAG(-O0 HAVE_O0_FLAG)
|
||||||
|
IF(HAVE_O0_FLAG)
|
||||||
|
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
|
||||||
|
ENDIF()
|
||||||
|
CHECK_C_COMPILER_FLAG(-gstabs+ HAVE_GSTABSP_FLAG)
|
||||||
|
IF(HAVE_gstabsp_FLAG)
|
||||||
|
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gstabs+")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
IF(FREEGLUT_BUILD_SHARED_LIBS)
|
||||||
|
TARGET_LINK_LIBRARIES(freeglut ${LIBS})
|
||||||
|
TARGET_COMPILE_DEFINITIONS(freeglut PUBLIC ${PUBLIC_DEFINITIONS})
|
||||||
|
ENDIF()
|
||||||
|
IF(FREEGLUT_BUILD_STATIC_LIBS)
|
||||||
|
TARGET_LINK_LIBRARIES(freeglut_static ${LIBS})
|
||||||
|
TARGET_COMPILE_DEFINITIONS(freeglut_static PUBLIC ${PUBLIC_DEFINITIONS})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(FREEGLUT_BUILD_SHARED_LIBS)
|
||||||
|
INSTALL(TARGETS freeglut EXPORT FreeGLUTTargets
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
INCLUDES DESTINATION include
|
||||||
|
)
|
||||||
|
IF(INSTALL_PDB)
|
||||||
|
IF(CMAKE_GENERATOR MATCHES "^Visual Studio" OR
|
||||||
|
CMAKE_GENERATOR MATCHES "Ninja Multi-Config")
|
||||||
|
INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/freeglut${CMAKE_DEBUG_POSTFIX}.pdb
|
||||||
|
DESTINATION bin
|
||||||
|
CONFIGURATIONS Debug
|
||||||
|
COMPONENT Devel)
|
||||||
|
ELSE()
|
||||||
|
INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/freeglut${CMAKE_DEBUG_POSTFIX}.pdb
|
||||||
|
DESTINATION bin
|
||||||
|
CONFIGURATIONS Debug
|
||||||
|
COMPONENT Devel)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
IF(FREEGLUT_BUILD_STATIC_LIBS)
|
||||||
|
INSTALL(TARGETS freeglut_static EXPORT FreeGLUTTargets
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
INCLUDES DESTINATION include
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
INSTALL(FILES ${FREEGLUT_HEADERS} DESTINATION include/GL COMPONENT Devel)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Optionally build demos, on by default.
|
||||||
|
option( FREEGLUT_BUILD_DEMOS "Build FreeGLUT demos." ON )
|
||||||
|
|
||||||
|
SET(DEMO_LIBS ${OPENGL_glu_LIBRARY} ${LIBS})
|
||||||
|
# lib m for math, not needed on windows
|
||||||
|
IF (NOT WIN32)
|
||||||
|
LIST(APPEND DEMO_LIBS m)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
MACRO(ADD_DEMO name)
|
||||||
|
IF( FREEGLUT_BUILD_DEMOS )
|
||||||
|
IF(FREEGLUT_BUILD_SHARED_LIBS)
|
||||||
|
ADD_EXECUTABLE(${name} ${ARGN})
|
||||||
|
TARGET_LINK_LIBRARIES(${name} ${DEMO_LIBS} freeglut)
|
||||||
|
IF(WIN32 AND MSVC)
|
||||||
|
SET_TARGET_PROPERTIES(${name} PROPERTIES DEBUG_POSTFIX d)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
IF(FREEGLUT_BUILD_STATIC_LIBS)
|
||||||
|
ADD_EXECUTABLE(${name}_static ${ARGN})
|
||||||
|
TARGET_LINK_LIBRARIES(${name}_static ${DEMO_LIBS} freeglut_static)
|
||||||
|
IF(WIN32 AND MSVC)
|
||||||
|
SET_TARGET_PROPERTIES(${name}_static PROPERTIES DEBUG_POSTFIX d)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ENDMACRO()
|
||||||
|
|
||||||
|
ADD_DEMO(CallbackMaker progs/demos/CallbackMaker/CallbackMaker.c)
|
||||||
|
ADD_DEMO(Fractals progs/demos/Fractals/fractals.c)
|
||||||
|
ADD_DEMO(Fractals_random progs/demos/Fractals_random/fractals_random.c)
|
||||||
|
ADD_DEMO(Lorenz progs/demos/Lorenz/lorenz.c)
|
||||||
|
IF (NOT WIN32)
|
||||||
|
ADD_DEMO(One progs/demos/One/one.c)
|
||||||
|
ELSE()
|
||||||
|
ADD_DEMO(One progs/demos/One/one.c
|
||||||
|
progs/demos/One/one.rc)
|
||||||
|
ENDIF()
|
||||||
|
ADD_DEMO(resizer progs/demos/resizer/resizer.c)
|
||||||
|
ADD_DEMO(multi-touch progs/demos/multi-touch/multi-touch.c)
|
||||||
|
ADD_DEMO(shapes progs/demos/shapes/shapes.c
|
||||||
|
progs/demos/shapes/glmatrix.h
|
||||||
|
progs/demos/shapes/glmatrix.c)
|
||||||
|
ADD_DEMO(smooth_opengl3 progs/demos/smooth_opengl3/smooth_opengl3.c)
|
||||||
|
ADD_DEMO(spaceball progs/demos/spaceball/spaceball.c
|
||||||
|
progs/demos/spaceball/vmath.c
|
||||||
|
progs/demos/spaceball/vmath.h)
|
||||||
|
ADD_DEMO(joystick progs/demos/joystick/joystick.c)
|
||||||
|
ADD_DEMO(subwin progs/demos/subwin/subwin.c)
|
||||||
|
ADD_DEMO(timer progs/demos/timer/timer.c)
|
||||||
|
ADD_DEMO(timer_callback progs/demos/timer_callback/timer.c)
|
||||||
|
ADD_DEMO(keyboard progs/demos/keyboard/keyboard.c)
|
||||||
|
ADD_DEMO(indexed_color progs/demos/indexed_color/idxcol.c)
|
||||||
|
ADD_DEMO(3dview progs/demos/3dview/3dview.c)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# pkg-config support, to install at $(libdir)/pkgconfig
|
||||||
|
# Define static build dependencies
|
||||||
|
IF(WIN32)
|
||||||
|
SET(PC_LIBS_PRIVATE "-lopengl32 -lwinmm -lgdi32")
|
||||||
|
ELSEIF(FREEGLUT_GLES)
|
||||||
|
IF(ANDROID)
|
||||||
|
SET(PC_LIBS_PRIVATE "-llog -landroid -lGLESv2 -lGLESv1_CM -lEGL -lm")
|
||||||
|
ELSEIF(BLACKBERRY)
|
||||||
|
IF(PLAYBOOK)
|
||||||
|
SET(PC_LIBS_PRIVATE "-lbps -lscreen -lGLESv2 -lGLESv1_CM -lEGL -lm")
|
||||||
|
ELSE()
|
||||||
|
SET(PC_LIBS_PRIVATE "-lbps -lslog2 -lscreen -lGLESv2 -lGLESv1_CM -lEGL -lm")
|
||||||
|
ENDIF()
|
||||||
|
ELSEIF(FREEGLUT_WAYLAND)
|
||||||
|
SET(PC_LIBS_PRIVATE "-lwayland-client -lwayland-cursor -lwayland-egl -lGLESv2 -lGLESv1_CM -lEGL -lxkbcommon -lm")
|
||||||
|
ELSE()
|
||||||
|
SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGLESv2 -lGLESv1_CM -lEGL -lm")
|
||||||
|
ENDIF()
|
||||||
|
ELSE()
|
||||||
|
IF(FREEGLUT_WAYLAND)
|
||||||
|
SET(PC_LIBS_PRIVATE "-lwayland-client -lwayland-cursor -lwayland-egl -lGL -lxkbcommon -lm")
|
||||||
|
ELSE()
|
||||||
|
SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGL -lm")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
# Client applications need to define FreeGLUT GLES version to
|
||||||
|
# bootstrap headers inclusion in freeglut_std.h:
|
||||||
|
SET(PC_LIBNAME ${LIBNAME})
|
||||||
|
SET(PC_FILENAME "${LIBNAME}.pc")
|
||||||
|
IF(FREEGLUT_GLES)
|
||||||
|
SET(PC_CFLAGS "-DFREEGLUT_GLES")
|
||||||
|
ENDIF()
|
||||||
|
IF(FREEGLUT_BUILD_STATIC_LIBS)
|
||||||
|
LIST(APPEND PC_CFLAGS -DFREEGLUT_STATIC)
|
||||||
|
ENDIF()
|
||||||
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/freeglut.pc.in ${CMAKE_BINARY_DIR}/freeglut.pc @ONLY)
|
||||||
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/freeglut.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig/ RENAME ${PC_FILENAME} COMPONENT Devel)
|
||||||
|
# TODO: change the library and .pc name when building for GLES,
|
||||||
|
# e.g. -lglut-GLES
|
||||||
|
|
||||||
|
INCLUDE(CMakePackageConfigHelpers)
|
||||||
|
WRITE_BASIC_PACKAGE_VERSION_FILE(
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTConfigVersion.cmake"
|
||||||
|
VERSION ${VERSION}
|
||||||
|
COMPATIBILITY AnyNewerVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
# needs cmake 3.0 (as does the "INCLUDES DIRECTORY" argument to install(TARGETS)):
|
||||||
|
EXPORT(EXPORT FreeGLUTTargets
|
||||||
|
FILE "${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTTargets.cmake"
|
||||||
|
NAMESPACE FreeGLUT::
|
||||||
|
)
|
||||||
|
CONFIGURE_FILE(FreeGLUTConfig.cmake.in
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTConfig.cmake"
|
||||||
|
@ONLY
|
||||||
|
)
|
||||||
|
SET(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/FreeGLUT)
|
||||||
|
INSTALL(EXPORT FreeGLUTTargets
|
||||||
|
FILE FreeGLUTTargets.cmake
|
||||||
|
NAMESPACE FreeGLUT::
|
||||||
|
DESTINATION ${ConfigPackageLocation}
|
||||||
|
)
|
||||||
|
INSTALL(
|
||||||
|
FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTConfig.cmake"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTConfigVersion.cmake"
|
||||||
|
DESTINATION ${ConfigPackageLocation}
|
||||||
|
COMPONENT Devel
|
||||||
|
)
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
Freeglut Copyright
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Freeglut code without an explicit copyright is covered by the following
|
||||||
|
copyright:
|
||||||
|
|
||||||
|
Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Pawel W. Olszta shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Pawel W. Olszta.
|
|
@ -0,0 +1 @@
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/FreeGLUTTargets.cmake")
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
See http://freeglut.sourceforge.net/docs/android.php
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# BlackBerry CMake toolchain file, for use with the BlackBerry 10 NDK
|
||||||
|
# Requires cmake 2.6.3 or newer (2.8.3 or newer is recommended).
|
||||||
|
#
|
||||||
|
# Usage Linux:
|
||||||
|
# $ source /absolute/path/to/the/bbndk/bbndk-env.sh
|
||||||
|
# $ mkdir build
|
||||||
|
# $ cd build
|
||||||
|
# $ cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles"
|
||||||
|
# $ make -j8
|
||||||
|
#
|
||||||
|
# Usage Mac:
|
||||||
|
# Same as the steps on Linux
|
||||||
|
#
|
||||||
|
# Usage Windows:
|
||||||
|
# > /absolute/path/to/the/bbndk/bbndk-env.bat
|
||||||
|
# > mkdir build
|
||||||
|
# > cd build
|
||||||
|
# > cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles"
|
||||||
|
# > make -j8
|
||||||
|
#
|
||||||
|
|
||||||
|
To change which version of OpenGL to use, call glutInitContextVersion(1, 0) for OpenGL ES 1.x, glutInitContextVersion(2, 0) for OpenGL ES 2.0, or glutInitContextVersion(3, 0) for OpenGL ES 3.0.
|
|
@ -0,0 +1,80 @@
|
||||||
|
How to build freeglut with CMake on Windows (MS Visual Studio)
|
||||||
|
--------------------------------------------------------------
|
||||||
|
1. Download CMake (http://www.cmake.org/cmake/resources/software.html).
|
||||||
|
Get one of the releases from the binary distribution section.
|
||||||
|
2. Run the CMake installer, install wherever you like.
|
||||||
|
3. Launch CMake via Start > Program Files > CMake 2.8 > CMake (GUI)
|
||||||
|
(note that the shortcut put by the installer on your desktop does NOT
|
||||||
|
point to the CMake GUI program!)
|
||||||
|
4. In the "Where is the source code" box, type or browse to the root
|
||||||
|
directory of your freeglut source (so that's /freeglut, not
|
||||||
|
/freeglut/src).
|
||||||
|
5. In the "Where to build the binaries" box, type or browse to any
|
||||||
|
folder you like - this will be where the Visual Studio solution will be
|
||||||
|
generated. This folder does not have to exist yet.
|
||||||
|
6. Hit the Configure button near the bottom of the window.
|
||||||
|
7. Pick your target compiler, make sure that its installed on your
|
||||||
|
system of course!
|
||||||
|
8. Answer Ok when asked if you want to create the build directory.
|
||||||
|
9. Wait for the configure process to finish.
|
||||||
|
10. The screen will now have some configuration options on it, for
|
||||||
|
instance specifying whether you want to build static and/or shared
|
||||||
|
libraries (see below for a complete list). When you've selected your
|
||||||
|
options, click the Configure button again.
|
||||||
|
11. The Generate button at the bottom will now be enabled. Click Generate.
|
||||||
|
12. The build files will now be generated in the location you picked.
|
||||||
|
|
||||||
|
You can now navigate to the build directory you specified in step 5.
|
||||||
|
Open the freeglut.sln file that was generated in your build directory,
|
||||||
|
and compile as usual
|
||||||
|
|
||||||
|
|
||||||
|
How to build freeglut on UNIX
|
||||||
|
-----------------------------
|
||||||
|
- Make sure you have cmake installed. Examples:
|
||||||
|
- Debian/Ubuntu: apt-get install cmake
|
||||||
|
- Fedora: yum install cmake
|
||||||
|
- FreeBSD: cd /usr/ports/devel/cmake && make install
|
||||||
|
Or directly from their website:
|
||||||
|
http://www.cmake.org/cmake/resources/software.html
|
||||||
|
- Make sure you have the basics for compiling code, such as C compiler
|
||||||
|
(e.g., GCC) and the make package.
|
||||||
|
- Also make sure you have packages installed that provide the relevant
|
||||||
|
header files for opengl (e.g., libgl1-mesa-dev on Debian/Ubuntu) and
|
||||||
|
the chosen backend :
|
||||||
|
- X11: x11 (e.g., libx11-dev, libxrandr-devel on Debian/Ubuntu) and
|
||||||
|
XInput (libxi-dev / libXi-devel)
|
||||||
|
- Wayland: wayland (e.g., libwayland-dev and libegl1-mesa-dev on
|
||||||
|
Debian/Ubuntu) and xkbcommon (libxkbcommon-dev /libxkbcommon-devel)
|
||||||
|
- Run 'cmake .' (or 'cmake . -DFREEGLUT_WAYLAND=ON' for Wayland) in the
|
||||||
|
freeglut directory to generate the makefile.
|
||||||
|
- Run 'make' to build, and 'make install' to install freeglut.
|
||||||
|
- If you wish to change any build options run 'ccmake .'
|
||||||
|
|
||||||
|
|
||||||
|
Breakdown of CMake configuration options
|
||||||
|
----------------------------------------
|
||||||
|
CMAKE_BUILD_TYPE [Empty, Debug, Release] Can be overriden by
|
||||||
|
passing it as a make variable during build.
|
||||||
|
CMAKE_INSTALL_PREFIX Installation prefix (e.g. /usr/local on UNIX)
|
||||||
|
FREEGLUT_BUILD_DEMOS [ON, OFF] Controls whether the demos are
|
||||||
|
built or not.
|
||||||
|
FREEGLUT_BUILD_SHARED_LIBS [ON, OFF] Build freeglut as a shared library
|
||||||
|
FREEGLUT_BUILD_STATIC_LIBS [ON, OFF] Build freeglut as a static library
|
||||||
|
FREEGLUT_GLES [ON, OFF] Link with GLEs libraries instead
|
||||||
|
of OpenGL
|
||||||
|
FREEGLUT_WAYLAND [ON, OFF] Link with Wayland libraries instead
|
||||||
|
of X11
|
||||||
|
FREEGLUT_PRINT_ERRORS [ON, OFF] Controls whether errors are
|
||||||
|
default handled or not when user does not
|
||||||
|
provide an error callback
|
||||||
|
FREEGLUT_PRINT_WARNINGS [ON, OFF] Controls whether warnings are
|
||||||
|
default handled or not when user does not
|
||||||
|
provide an warning callback
|
||||||
|
FREEGLUT_REPLACE_GLUT [ON, OFF] For non-Windows platforms,
|
||||||
|
freeglut is by default built as -lglut. if
|
||||||
|
off, built as -lfreeglut. On Windows,
|
||||||
|
libraries are always built as freeglut.
|
||||||
|
INSTALL_PDB [ON, OFF] MSVC only: controls whether debug
|
||||||
|
information files are included with the
|
||||||
|
install or not
|
|
@ -0,0 +1,209 @@
|
||||||
|
Glut then!
|
||||||
|
|
||||||
|
By Jean-Seb on Friday July 10, 2009, 00:18
|
||||||
|
Translated by Babelfish with a scrub from John F. Fay. For points of confusion
|
||||||
|
please refer to the original French version.
|
||||||
|
|
||||||
|
Freeglut is an open-source evolution of GLUT.
|
||||||
|
Under Windows, one can use it with Cygwin.
|
||||||
|
Easy? Yes, if one agrees to distribute "cygwin1.dll".
|
||||||
|
Let us help freeglut gain its independence !
|
||||||
|
Update 10/7/2009: generation of a library for linking without the DLL.
|
||||||
|
|
||||||
|
|
||||||
|
Grabbing the sources
|
||||||
|
|
||||||
|
* Download the sources for version 2.6.0 which integrates recent changes.
|
||||||
|
* Using version 2.6 is better than the 2.4-stable branch because many
|
||||||
|
bugs have been corrected.
|
||||||
|
* You will find the sources on the site of Freeglut:
|
||||||
|
o http://freeglut.sourceforge.net/
|
||||||
|
|
||||||
|
|
||||||
|
Goals
|
||||||
|
|
||||||
|
* We will create a DLL for Cygwin, and an independent static library
|
||||||
|
* We will also create a dynamic library, allowing linking with the DLL.
|
||||||
|
|
||||||
|
|
||||||
|
List of generated files
|
||||||
|
|
||||||
|
* freeglut.dll: a traditional DLL for the dynamic linkage.
|
||||||
|
* libfreeglut.a: the static library. The final program is autonomous (at
|
||||||
|
least for OpenGL).
|
||||||
|
* libfreeglutdll.a: the dynamic library. The final program needs
|
||||||
|
freeglut.dll.
|
||||||
|
|
||||||
|
|
||||||
|
Preparation
|
||||||
|
|
||||||
|
* Extract the files from the freeglut archive.
|
||||||
|
* Go in the directory src (located at the root of the Freeglut directory),
|
||||||
|
and create a "Gl" sub-directory
|
||||||
|
o In this sub-directory, copy the files of the directory "include/Gl"
|
||||||
|
|
||||||
|
* Why is it necessary to create a "Gl" directory for compilation?
|
||||||
|
o I needed it to simplify things during my tests.
|
||||||
|
o If not you can create the repertories directly, and copy the files
|
||||||
|
as indicated in the point installation (see below).
|
||||||
|
|
||||||
|
* Do a little housekeeping in /lib:
|
||||||
|
o Erase all the references to the glut, so as not to conflict with the
|
||||||
|
linking.
|
||||||
|
o This stage is optional, you can also choose to do the housekeeping
|
||||||
|
only after a successful compilation of Freeglut.
|
||||||
|
o In your enthusiasm to clean things up, be careful not to erase the
|
||||||
|
library glu32.lib (not to be confused with glut32.lib).
|
||||||
|
|
||||||
|
|
||||||
|
Compilation
|
||||||
|
|
||||||
|
* Forget the "./configure, make, make install" triptych.
|
||||||
|
o It does not go at all with Cygwin.
|
||||||
|
|
||||||
|
* Here Makefile which will make the deal:
|
||||||
|
|
||||||
|
#Makefile for Freeglut 2.6.0-rc and Cygwin
|
||||||
|
#To place in the directory 'src/Common'
|
||||||
|
|
||||||
|
sources=$ (wildcard *.c)
|
||||||
|
objs=$ (sources: .c=.o)
|
||||||
|
libname=freeglut
|
||||||
|
|
||||||
|
|
||||||
|
CFLAGS=-O2 - DTARGET_HOST_MS_WINDOWS - DX_DISPLAY_MISSING - DFREEGLUT_STATIC - I./
|
||||||
|
LDFLAGS=-lopengl32 - lgdi32 - lwinmm
|
||||||
|
|
||||||
|
nocyg=-mno-cygwin - mwindows
|
||||||
|
|
||||||
|
all: $ (objs)
|
||||||
|
#construction DLL related to cygwin1.dll
|
||||||
|
gcc $(nocyg) $(objs) -shared $(LDFLAGS) -o $(libname).dll
|
||||||
|
nm $(libname).dll | awk 'BEGIN { print "EXPORTS" } /T _glut/ {sub( /^.*T _/, "\t"); print}' > $(libname).def
|
||||||
|
dlltool --dllname $(libname).dll --input-def $(libname).def --output-lib lib$(libname)dll.a
|
||||||
|
|
||||||
|
#construction static library independent of cygwin
|
||||||
|
ar cr lib$(libname).a $(objs)
|
||||||
|
#pas inevitably obligatory (creation of an index to accelerate the accesses)
|
||||||
|
ranlib lib$(libname).a
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
gcc $(nocyg) -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o $(libname).dll $(libname).def lib$(libname)dll.a lib$(libname).a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Some remarks on the Makefile
|
||||||
|
|
||||||
|
* This makefile creates a DLL, a static library (a file, in other words) and
|
||||||
|
the dynamic library which will allow the use of the DLL.
|
||||||
|
|
||||||
|
* Do not try to strip the static library! You may not be able to compile
|
||||||
|
applications with static library any more.
|
||||||
|
o On the other hand, you can strip the final executable obtained after
|
||||||
|
compiling your application.
|
||||||
|
|
||||||
|
* I chose to call the DLL and the libraries by their "true names":
|
||||||
|
freeglut.dll libfreeglutdll.a and libfreeglut.a.
|
||||||
|
o Script configures recreated (for reasons of compatibility with the
|
||||||
|
old GLUT library) glut.dll and libglut.a.
|
||||||
|
o During the my tests, I had conflicts with an authentic "glut" which
|
||||||
|
trailed in my "/lib". I decided to call the things by their name, in
|
||||||
|
order to avoid confusions.
|
||||||
|
o Nothing prevents you from renaming the DLL, if you need to use GLUT
|
||||||
|
programs which you cannot recompile.
|
||||||
|
|
||||||
|
* The dynamic library is generated starting from the DLL.
|
||||||
|
o For reasons of brevity, I used awk. It generates the export file
|
||||||
|
used by dlltool.
|
||||||
|
o The only notable thing is the selection of the functions whose name
|
||||||
|
starts with _glut, in order to avoid including in the dynamic
|
||||||
|
library the functions that are not related to freeglut.
|
||||||
|
o then, one uses dlltool in a very traditional way.
|
||||||
|
|
||||||
|
nm $(libname).dll | awk 'BEGIN { print "EXPORTS" } /T _glut/ {sub( /^.*T _/, "\t"); print}' > $(libname).def
|
||||||
|
dlltool --dllname $(libname).dll --input-def $(libname).def --output-lib lib$(libname)dll.a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
|
||||||
|
* Copy libfreeglut.a, libfreeglutdll.a into the Cygwin directory /lib.
|
||||||
|
* Copy freglut.dll in the system32 of Windows (this is practical, but not
|
||||||
|
clean!).
|
||||||
|
* Copy the files headers of Freeglut (/include/gl) into the Cygwin directory
|
||||||
|
/usr/include/Gl.
|
||||||
|
* Copy the files headers (always /include/gl) into /usr/include/mingw/Gl:
|
||||||
|
this is used for compilations with the flag - mno-cygwin, which uses the
|
||||||
|
includes in mingw.
|
||||||
|
o You may need to erase the old GLUT include files if you installed it
|
||||||
|
with Cygwin.
|
||||||
|
|
||||||
|
|
||||||
|
Use of the library
|
||||||
|
|
||||||
|
* We will test with the program shapes, found in progs/demonstrations/shapes
|
||||||
|
o -mno-cygwin is used to force the use of Mingw without the large
|
||||||
|
dependence cygwin1.dll.
|
||||||
|
o -mwindows is only used to remove the horrible Shell window (very
|
||||||
|
useful for the settling, on the other hand).
|
||||||
|
o -L. (note the period after the "L"): I left libfreeglut.a,
|
||||||
|
libfreeglutdll.a and freeglut.dll in the test directory, at the time
|
||||||
|
of the tests.
|
||||||
|
|
||||||
|
|
||||||
|
Compilation of the static freeglut library, without cygwin
|
||||||
|
|
||||||
|
* All the simplicity lies in the define: -DFREEGLUT_STATIC
|
||||||
|
o It serves to obtain good decoration of the function names in the
|
||||||
|
imports of the lib Freeglut.
|
||||||
|
o You can test without and use a hex editor to see the differences
|
||||||
|
in the objects.
|
||||||
|
* attention with the order of the libraries: -lfreeglut (static) must be
|
||||||
|
before the declaration of the dynamic libraries.
|
||||||
|
|
||||||
|
* gcc shapes.c -L. -lfreeglut -lopengl32 -lwinmm -lgdi32 -mno-cygwin -mwindows -DFREEGLUT_STATIC
|
||||||
|
|
||||||
|
|
||||||
|
Compilation with DLL freeglut, without cygwin
|
||||||
|
|
||||||
|
* For the define, see the notices above
|
||||||
|
* The order of the libraries is no longer important.
|
||||||
|
|
||||||
|
* gcc shapes.c -L. -lopengl32 -lwinmm -lgdi32 -lfreeglut -mno-cygwin -DFREEGLUT_STATIC
|
||||||
|
|
||||||
|
|
||||||
|
Compilation with DLL freeglut, Cygwin
|
||||||
|
|
||||||
|
* This example is given only for reference, the topic of this ticket being
|
||||||
|
to get rid of Cygwin.
|
||||||
|
o Let us say that can be used to make the point (and later).
|
||||||
|
|
||||||
|
* gcc shapes.c -L. -lopengl32 -lwinmm -lgdi32 -lfreeglut
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Where are the dooooocs?
|
||||||
|
|
||||||
|
* Freeglut is delivered with its documentation, more very up to date.
|
||||||
|
o It seems that there is a problem with the original GLUT
|
||||||
|
documentation. Not only it does not correspond completely to the
|
||||||
|
operation of Freeglut, but moreover, its author (Mark Kilgard)
|
||||||
|
copyrighted it. Its distribution is thus difficult.
|
||||||
|
|
||||||
|
* Jocelyn Fréchot undertook a levelling of the docs for version 2.6.0. One can find them on his site for the moment:
|
||||||
|
o http://jocelyn.frechot.free.fr/freeglut/
|
||||||
|
|
||||||
|
|
||||||
|
Something survived...
|
||||||
|
|
||||||
|
* I also tested the recompiling of the demonstrations of the original lib
|
||||||
|
GLUT (peace with its ashes).
|
||||||
|
o Nothing in particular to be announced.
|
||||||
|
|
||||||
|
* Thank you with all the courageous maintainers for Freeglut, that one
|
||||||
|
believed dead, but which still move.
|
|
@ -0,0 +1,48 @@
|
||||||
|
Freeglut on MacOS X
|
||||||
|
===================
|
||||||
|
|
||||||
|
Currently freeglut does not support the native Cocoa API and the OpenGL
|
||||||
|
framework which works with it, but rather relies on X11 (XQuartz) and the Mesa
|
||||||
|
OpenGL and GLX libraries.
|
||||||
|
|
||||||
|
The simplest way to set up the prerequisites for building and using freeglut is
|
||||||
|
with the homebrew package management system: https://brew.sh
|
||||||
|
|
||||||
|
Build instructions
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
- If you don't already have homebrew, go to https://brew.sh and follow their
|
||||||
|
instructions.
|
||||||
|
- If you don't already have a compiler toolchain installed, download the Xcode
|
||||||
|
commandline tools from the apple store and install them first.
|
||||||
|
- If you don't have XQuartz installed, get it from https://www.xquartz.org
|
||||||
|
- Use homebrew to install cmake, and all the necessary libraries:
|
||||||
|
`brew install cmake libx11 libxi libxrandr libxxf86vm pkg-config mesa`
|
||||||
|
|
||||||
|
Build freeglut:
|
||||||
|
- Create a build directory under the freeglut directory and change into it:
|
||||||
|
`mkdir build && cd build`
|
||||||
|
- Run cmake to generate the makefile:
|
||||||
|
`cmake -DFREEGLUT_BUILD_DEMOS=OFF -DOPENGL_gl_LIBRARY=/usr/local/lib/libGL.dylib ..`
|
||||||
|
- Run `make` to build freeglut, and `make install` to install it.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
To use freeglut in your program **do not** include `<GLUT/glut.h>`; that header
|
||||||
|
is part of Apple's GLUT framework. Use `#include <GL/glut.h>` instead as usual,
|
||||||
|
or `#include <GL/freeglut.h>` if you wish to take advantage of the extended
|
||||||
|
freeglut API.
|
||||||
|
|
||||||
|
Similarly, to link with freeglut **do not** use `-framework GLUT` in your
|
||||||
|
linker command line. Instead use the standard `-lglut` argument, as you would
|
||||||
|
on any other UNIX system.
|
||||||
|
|
||||||
|
Known issues
|
||||||
|
------------
|
||||||
|
|
||||||
|
Some versions of XQuartz do not map the option keys to ALT by default, making
|
||||||
|
it impossible to get the `GLUT_ACTIVE_ALT` bit set in the bitmask returned by
|
||||||
|
`glutGetModifiers`. To change this behavior go to the XQuartz preferences and
|
||||||
|
enable the "Option keys send Alt_L and Alt_R" checkbox in the "input" tab.
|
|
@ -0,0 +1,97 @@
|
||||||
|
freeglut
|
||||||
|
========
|
||||||
|
|
||||||
|
![GNU/Linux (X11) build status](https://github.com/FreeGLUTProject/freeglut/actions/workflows/build_gnulinux_x11.yml/badge.svg)
|
||||||
|
![Windows build status](https://github.com/FreeGLUTProject/freeglut/actions/workflows/build_win_msvc.yml/badge.svg)
|
||||||
|
![MacOS X (X11) build status](https://github.com/FreeGLUTProject/freeglut/actions/workflows/build_macosx_x11.yml/badge.svg)
|
||||||
|
|
||||||
|
OVERVIEW
|
||||||
|
--------
|
||||||
|
|
||||||
|
Freeglut, the Free OpenGL Utility Toolkit, is meant to be a free alternative to
|
||||||
|
Mark Kilgard's GLUT library. Freeglut is free software, distributed under an
|
||||||
|
MIT/X11 style license. You are free to use, modify, and redistribute freeglut
|
||||||
|
with or without modifications (see COPYING for details).
|
||||||
|
|
||||||
|
In short, freeglut can be used by OpenGL programs to perform those tasks which
|
||||||
|
would normally require platform-specific code. Tasks like creating a window,
|
||||||
|
creating an OpenGL context and binding it to the window, and processing input
|
||||||
|
events. Freeglut provides a concise and elegant API to handle those tasks, in a
|
||||||
|
platform-independent manner, keeping the application simple and portable.
|
||||||
|
|
||||||
|
One of the main goals of freeglut, is maximum compatibility. Freeglut is both
|
||||||
|
source and binary-compatible with the original GLUT, and can be used as a
|
||||||
|
drop-in replacement for it. We take great care to maintain a stable API and ABI,
|
||||||
|
and to introduce any new features and improvements in a way which does not
|
||||||
|
compromise compatibility.
|
||||||
|
|
||||||
|
Freeglut can be used with a wide range of OpenGL implementations, from the very
|
||||||
|
early OpenGL 1.0 on SGI computers, to the very latest modern OpenGL versions on
|
||||||
|
current GPUs. It can be used to create a classic OpenGL context, or a versioned
|
||||||
|
core profile or compatibility context. Freeglut can also be used with OpenGL ES,
|
||||||
|
on desktop or mobile devices.
|
||||||
|
|
||||||
|
|
||||||
|
PORTS
|
||||||
|
-----
|
||||||
|
|
||||||
|
Currently supported platforms:
|
||||||
|
- UNIX systems with X11 or Wayland (such as GNU/Linux, FreeBSD, IRIX, etc)
|
||||||
|
- MS Windows
|
||||||
|
- macOS with XQuartz (no native Cocoa support yet)
|
||||||
|
- Android (NDK)
|
||||||
|
- BlackBerry
|
||||||
|
|
||||||
|
Consult the platform-specific readme files for details on the level of support
|
||||||
|
and build instructions.
|
||||||
|
|
||||||
|
|
||||||
|
INSTALLATION
|
||||||
|
------------
|
||||||
|
|
||||||
|
Freeglut relies on cmake (minimum 3.0.0) to generate build files for all the
|
||||||
|
different supported platforms and toolchains.
|
||||||
|
|
||||||
|
See [`README.cmake`](README.cmake) as a starting point, as well as the other `README`
|
||||||
|
files for further info.
|
||||||
|
|
||||||
|
For those cases where using cmake is inconvenient, we also provide a set of
|
||||||
|
unofficial, unsupported, possibly unmaintained, but potentially useful,
|
||||||
|
alternative build files. See [`altbuild/README.md`](altbuild/README.md) for details.
|
||||||
|
|
||||||
|
|
||||||
|
CONTRIBUTING
|
||||||
|
------------
|
||||||
|
|
||||||
|
Patches and pull requests for bugfixes and new features are certainly welcome.
|
||||||
|
Please send patches to the freeglut-developer mailing list (see CONTACT below).
|
||||||
|
|
||||||
|
Feel free to report any bugs you encounter, using the github *issues* system.
|
||||||
|
|
||||||
|
Older bug reports and feature requests are still reachable on:
|
||||||
|
- https://sourceforge.net/p/freeglut/bugs/
|
||||||
|
- https://sourceforge.net/p/freeglut/feature-requests/
|
||||||
|
|
||||||
|
But you are encouraged to use github issues for new ones.
|
||||||
|
|
||||||
|
Alternatively you can also send bug reports and feature requests to the
|
||||||
|
freeglut-developer mailing list if you prefer. Extended discussions about new
|
||||||
|
features and design issues for large contributions, are best suited to the
|
||||||
|
mailing list.
|
||||||
|
|
||||||
|
|
||||||
|
CONTACT
|
||||||
|
-------
|
||||||
|
|
||||||
|
FreeGLUT website: http://freeglut.sourceforge.net
|
||||||
|
|
||||||
|
FreeGLUT mailing lists:
|
||||||
|
- developer: https://lists.sourceforge.net/lists/listinfo/freeglut-developer
|
||||||
|
- bugs: https://lists.sourceforge.net/lists/listinfo/freeglut-bugs
|
||||||
|
- announce: https://lists.sourceforge.net/lists/listinfo/freeglut-announce
|
||||||
|
|
||||||
|
You need to subscribe before posting to any of our mailing lists. Make sure
|
||||||
|
to avoid selecting "daily digest mode" if you intend to post, so that you can
|
||||||
|
reply properly to specific messages. Also, please do not top-post, and try to
|
||||||
|
send properly formated emails (text, hard-wrapped at 72 columns, no binary or
|
||||||
|
large attachements).
|
|
@ -0,0 +1,49 @@
|
||||||
|
Cross-compilation from GNU/Linux (static and shared DLL)
|
||||||
|
========================================================
|
||||||
|
|
||||||
|
Install MinGW, and specify which MinGW you're using:
|
||||||
|
|
||||||
|
- on Debian/Ubuntu, mingw-w64, 64-bit executables:
|
||||||
|
|
||||||
|
apt-get install mingw-w64
|
||||||
|
GNU_HOST=x86_64-w64-mingw32
|
||||||
|
|
||||||
|
- on Debian/Ubuntu, mingw-w64, 32-bit executables:
|
||||||
|
|
||||||
|
apt-get install mingw-w64
|
||||||
|
GNU_HOST=i686-w64-mingw32
|
||||||
|
|
||||||
|
- on Fedora, mingw32, 32-bit executables:
|
||||||
|
|
||||||
|
yum install mingw32-gcc
|
||||||
|
GNU_HOST=i686-pc-mingw32
|
||||||
|
|
||||||
|
- on Debian/Ubuntu, mingw32 (deprecated):
|
||||||
|
|
||||||
|
apt-get install mingw32
|
||||||
|
GNU_HOST=i586-mingw32msvc
|
||||||
|
|
||||||
|
|
||||||
|
With CMake
|
||||||
|
----------
|
||||||
|
|
||||||
|
Cross-compile with:
|
||||||
|
|
||||||
|
mkdir cross-woe/ && cd cross-woe/
|
||||||
|
cmake \
|
||||||
|
-D GNU_HOST=$GNU_HOST \
|
||||||
|
-D CMAKE_TOOLCHAIN_FILE=mingw_cross_toolchain.cmake \
|
||||||
|
-D CMAKE_INSTALL_PREFIX=/freeglut \
|
||||||
|
..
|
||||||
|
make -j4
|
||||||
|
make install DESTDIR=$(pwd)
|
||||||
|
|
||||||
|
Everything is now in the new 'freeglut/' directory.
|
||||||
|
The .dll is in 'freeglut/lib/'.
|
||||||
|
|
||||||
|
|
||||||
|
Compiling your code
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Compilation of your own programs is done as usual.
|
||||||
|
See README.cygwin_mingw for details.
|
|
@ -0,0 +1,91 @@
|
||||||
|
NB
|
||||||
|
==================================
|
||||||
|
For ancient 16bit compatibility, windef.h (included through windows.h in
|
||||||
|
freeglut_std.h) defines near and far. Its best to avoid using variables
|
||||||
|
with these names in your own program.
|
||||||
|
|
||||||
|
Installing the Libraries with MSVC
|
||||||
|
==================================
|
||||||
|
|
||||||
|
To install "freeglut" on your system so that your other projects will see it,
|
||||||
|
you will need to copy various files to various locations.
|
||||||
|
|
||||||
|
- The header files "freeglut.h", "freeglut_ext.h", "freeglut_std.h", and
|
||||||
|
"glut.h" (distributed in the directory "freeglut\freeglut\include\GL")
|
||||||
|
need to be copied to a "GL" directory under the MSVC include directory.
|
||||||
|
The MSVC include directory generally has a path similar to
|
||||||
|
"C:\Program Files\Microsoft Visual Studio\VC98\Include"
|
||||||
|
The "GL" subdirectory under that will probably already have the header
|
||||||
|
files "gl.h", "glaux.h", and "glu.h".
|
||||||
|
- The library file "freeglut.lib" or "freeglut_static.lib" (from the
|
||||||
|
corresponding debug or release directory) needs to be copied into the
|
||||||
|
MSVC library directory. This usually has a path similar to:
|
||||||
|
"%ProgramFiles%\Microsoft SDKs\Windows\v7.0A\Lib" - x86 32 bits LIB's
|
||||||
|
"%ProgramFiles(x86)%\Microsoft SDKs\Windows\v7.0A\Lib" - x64 32 bits LIB's
|
||||||
|
"%ProgramFiles(x86)%\Microsoft SDKs\Windows\v7.0A\Lib\x64" - x64 64 bits LIB's
|
||||||
|
Note that there is no "GL" subdirectory here. This directory should
|
||||||
|
already have the files "opengl32.lib", "glu32.lib", and "glaux.lib".
|
||||||
|
- If you are using the DLL version of "freeglut", the file "freeglut.dll"
|
||||||
|
needs to be copied from the Debug or the Release directory into the
|
||||||
|
DLL directory. This usually has a path similar to
|
||||||
|
"%SystemRoot%\System32\" - x86 32 bits DLL's
|
||||||
|
"%SystemRoot%\SysWOW64\" - x64 32 bits DLL's
|
||||||
|
"%SystemRoot%\System32\" - x64 64 bits DLL's
|
||||||
|
and will probably already have the files "opengl32.dll" and "glu32.dll".
|
||||||
|
|
||||||
|
|
||||||
|
Building and Installing the Libraries with Open Watcom
|
||||||
|
======================================================
|
||||||
|
|
||||||
|
Start a command prompt and change directory to the freeglut installation
|
||||||
|
directory. Type "wmake -f Makefile.wat all" to build the DLL and static
|
||||||
|
libraries in both debug and release versions.
|
||||||
|
|
||||||
|
To install "freeglut" on your system so that your other projects will see it,
|
||||||
|
you will need to copy various files to various locations.
|
||||||
|
|
||||||
|
- The header files "freeglut.h", "freeglut_ext.h", "freeglut_std.h", and
|
||||||
|
"glut.h" (distributed in the directory "freeglut\freeglut\include\GL")
|
||||||
|
need to be copied to a "GL" directory under the Open Watcom 32-bit
|
||||||
|
Windows include directory. This usually has a path similar to
|
||||||
|
"C:\WATCOM\h\nt\GL"
|
||||||
|
- The library file "freeglut.lib" or "freeglut_static.lib" (from the
|
||||||
|
corresponding debug or release directory) needs to be copied into the
|
||||||
|
Open Watcom 32-bit Windows library directory. This usually has a path
|
||||||
|
similar to
|
||||||
|
"C:\WATCOM\lib386\nt"
|
||||||
|
- If you are using the DLL version of "freeglut", the file "freeglut.dll"
|
||||||
|
needs to be copied from the Debug or the Release directory into the
|
||||||
|
DLL directory. This usually has a path similar to
|
||||||
|
"C:\Windows\System32"
|
||||||
|
and will probably already have the files "opengl32.dll" and "glu32.dll".
|
||||||
|
|
||||||
|
|
||||||
|
Unlike the *nix release, the library names are NOT automatic replacements for
|
||||||
|
the GLUT library names. You may rename them manually if you wish, but this is
|
||||||
|
not necessary as the header file includes a pragma telling the compiler which
|
||||||
|
library file to look for.
|
||||||
|
|
||||||
|
|
||||||
|
Building and Installing the Libraries with Cygwin
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
To build "freeglut" under Cygwin, you have two choices:
|
||||||
|
|
||||||
|
- You can build a normal Cygwin library, which depends on Cygwin's X11
|
||||||
|
libraries. To do this, you can just use the normal autotools incantation:
|
||||||
|
./configure && make install
|
||||||
|
|
||||||
|
- Alternatively, you can build a DLL which does not depend on X11 and links
|
||||||
|
against the opengl32 DLL. To do this, configure need a few more flags:
|
||||||
|
./configure CPPFLAGS=-mno-cygwin LDFLAGS=-mno-cygwin --without-x && make install
|
||||||
|
|
||||||
|
|
||||||
|
If you don't have MSVC, Open Watcom or Cygwin
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
The "freeglut" developers' community discussed the possibility of distributing
|
||||||
|
binaries and decided against it. If you need Windows library files, please
|
||||||
|
contact John F. Fay at <john.fay@eglin.af.mil> or put a request on the
|
||||||
|
"freeglut" developers' mailing list <freeglut-developer@lists.sourceforge.net>.
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Simple UNIX makefile
|
||||||
|
# Builds freeglut as a static library.
|
||||||
|
|
||||||
|
# ------- options --------
|
||||||
|
|
||||||
|
# installation prefix
|
||||||
|
PREFIX = /usr/local
|
||||||
|
|
||||||
|
# subdirectory for libraries (lib, lib32, lib64?)
|
||||||
|
LIBDIR = lib
|
||||||
|
|
||||||
|
# optimization flags
|
||||||
|
opt = -O3
|
||||||
|
|
||||||
|
# debug symbols
|
||||||
|
#dbg = -g
|
||||||
|
|
||||||
|
# libraries to link when building the demo program (make demo). You might need
|
||||||
|
# to adjust these, depending on the choices in config.h
|
||||||
|
demo_libs = $(liba) -lGL -lX11 -lXmu -lXext -lXi -lXrandr -lXxf86vm -lm
|
||||||
|
|
||||||
|
# ---- end of options ----
|
||||||
|
|
||||||
|
coreobj = src/fg_gl2.o src/fg_misc.o src/fg_input_devices.o src/fg_ext.o \
|
||||||
|
src/fg_joystick.o src/fg_init.o src/fg_callbacks.o \
|
||||||
|
src/fg_menu.o src/fg_stroke_roman.o src/fg_structure.o src/fg_overlay.o \
|
||||||
|
src/fg_window.o src/fg_state.o src/fg_videoresize.o src/fg_spaceball.o \
|
||||||
|
src/fg_cursor.o src/fg_main.o src/fg_gamemode.o \
|
||||||
|
src/fg_stroke_mono_roman.o src/fg_geometry.o src/fg_font.o src/fg_display.o \
|
||||||
|
src/fg_font_data.o src/fg_teapot.o
|
||||||
|
|
||||||
|
x11obj = src/x11/fg_state_x11_glx.o src/x11/fg_glutfont_definitions_x11.o \
|
||||||
|
src/x11/fg_joystick_x11.o src/x11/fg_structure_x11.o src/x11/fg_cursor_x11.o \
|
||||||
|
src/x11/fg_state_x11.o src/x11/fg_main_x11.o src/x11/fg_spaceball_x11.o \
|
||||||
|
src/x11/fg_input_devices_x11.o src/x11/fg_ext_x11.o src/x11/fg_window_x11_glx.o \
|
||||||
|
src/x11/fg_gamemode_x11.o src/x11/fg_init_x11.o src/x11/fg_menu_x11.o \
|
||||||
|
src/x11/fg_xinput_x11.o src/x11/fg_window_x11.o src/x11/fg_display_x11_glx.o \
|
||||||
|
src/x11/fg_cmap_x11.o
|
||||||
|
|
||||||
|
obj = $(coreobj) $(x11obj)
|
||||||
|
|
||||||
|
liba = libglut.a
|
||||||
|
incpath = -I. -Isrc -Iinclude -I/usr/local/include -I/usr/X11R6/include
|
||||||
|
libpath = -L/usr/local/lib -L/usr/X11R6/lib
|
||||||
|
|
||||||
|
CFLAGS = -O2 $(incpath) -DHAVE_CONFIG_H
|
||||||
|
LDFLAGS = $(libpath)
|
||||||
|
|
||||||
|
|
||||||
|
$(liba): $(obj)
|
||||||
|
$(AR) rcs $@ $(obj)
|
||||||
|
|
||||||
|
demo: progs/demos/3dview/3dview.o $(liba)
|
||||||
|
$(CC) -o $@ progs/demos/3dview/3dview.o $(LDFLAGS) $(demo_libs)
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -o $@ $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f $(obj) $(liba) demo
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: $(liba)
|
||||||
|
mkdir -p $(DESTDIR)$(PREFIX)/$(LIBDIR) $(DESTDIR)$(PREFIX)/include/GL
|
||||||
|
cp include/GL/* $(DESTDIR)$(PREFIX)/include/GL
|
||||||
|
cp $(liba) $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(liba)
|
||||||
|
|
||||||
|
.PHONY: uninstall
|
||||||
|
uninstall:
|
||||||
|
rm -f $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(liba)
|
||||||
|
rm -f $(DESTDIR)$(PREFIX)/include/GL/glut.h
|
||||||
|
rm -f $(DESTDIR)$(PREFIX)/include/GL/freeglut.h
|
||||||
|
rm -f $(DESTDIR)$(PREFIX)/include/GL/freeglut_std.h
|
||||||
|
rm -f $(DESTDIR)$(PREFIX)/include/GL/freeglut_ext.h
|
||||||
|
rm -f $(DESTDIR)$(PREFIX)/include/GL/freeglut_ucall.h
|
|
@ -0,0 +1,66 @@
|
||||||
|
Simple build files for freeglut
|
||||||
|
===============================
|
||||||
|
This directory includes a number of simple ways to build freeglut, without
|
||||||
|
relying on extra tools.
|
||||||
|
|
||||||
|
The official build system used by freeglut is cmake, with the current minimum
|
||||||
|
cmake version required being set to 3.0. Installing and using cmake 3.0 or later
|
||||||
|
to generate build files might be difficult or inconvenient in some cases.
|
||||||
|
Installing modern versions of cmake on very old UNIX systems might be difficult
|
||||||
|
or impossible. And finding the exact cmake version which still supports
|
||||||
|
generating project files for a certain old IDE, dropped from current cmake, can
|
||||||
|
be annoying.
|
||||||
|
|
||||||
|
None of the files in this directory are officially supported! Some of them might
|
||||||
|
be completely unmaintained, broken, or out of date. Please report any issues,
|
||||||
|
but be warned that you may have to fix them yourself.
|
||||||
|
|
||||||
|
The simple build files in this directory do not build the demo programs, and do
|
||||||
|
not provide the same flexibility of build options as the official cmake build.
|
||||||
|
Most of them just build a default configuration of freeglut as a static library
|
||||||
|
and that's it.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
Before using any of these build files, first you'll need to select one of the
|
||||||
|
`config.h.*` files provided, copy it to the project root directory with the name
|
||||||
|
`config.h`. The following config files are available:
|
||||||
|
|
||||||
|
- config.h.unix: Modern UNIX with X11 (GNU/Linux, FreeBSD, etc).
|
||||||
|
- config.h.msvc6: Windows build with MS Visual C/C++ 6.0.
|
||||||
|
- config.h.irix5: IRIX 5.x build with the SGI compiler.
|
||||||
|
- config.h.irix6: IRIX 6.x build with the SGI compiler.
|
||||||
|
|
||||||
|
You can edit the `config.h` file to remove unnecessary dependencies (and their
|
||||||
|
corresponding features). For example, some old X servers do not have the XRandR
|
||||||
|
extension, or you may not wish to install libXrandr, in which case you should
|
||||||
|
disable it by deleting the `#define HAVE_X11_EXTENSIONS_XRANDR_H` line, or
|
||||||
|
changing `define` to `undef`.
|
||||||
|
|
||||||
|
Simple UNIX Makefile
|
||||||
|
--------------------
|
||||||
|
This should build freeglut on many different UNIX systems with their native
|
||||||
|
make utility.
|
||||||
|
|
||||||
|
- Copy `Makefile` to the project root directory.
|
||||||
|
- Copy the appropriate `config.h.*` file to the project root directory renamed
|
||||||
|
to `config.h`.
|
||||||
|
- `make` to build.
|
||||||
|
- `make install` to install. Change the `PREFIX` variable at the top of the
|
||||||
|
`Makefile` to change the installation prefix.
|
||||||
|
|
||||||
|
You can also attempt to build a simple statically linked demo program, by typing
|
||||||
|
`make demo`. But be warned that you might need to modify the `demo_libs`
|
||||||
|
variable at the top of the `Makefile` to adjust for whatever options are
|
||||||
|
selected in the `config.h` you used to build freeglut.
|
||||||
|
|
||||||
|
MS Visual Studio 6.0 project
|
||||||
|
----------------------------
|
||||||
|
Project files for building freeglut on 32bit windows, using MSVC6.
|
||||||
|
|
||||||
|
- Copy `config.h.msvc6` to the project root directory renamed to `config.h`.
|
||||||
|
- Open the `freeglut.dsw` "workspace" file with visual studio 6.
|
||||||
|
- Select build all from the build menu.
|
||||||
|
|
||||||
|
The MSVC6 project builds freeglut as both a static library and a DLL, and also
|
||||||
|
builds a simple statically linked demo program.
|
|
@ -0,0 +1,23 @@
|
||||||
|
/* freeglut configuration file for building on SGI IRIX 5.x
|
||||||
|
*
|
||||||
|
* #define to enable, #undef or delete line to disable
|
||||||
|
*
|
||||||
|
* Copy to the freeglut root directory as config.h along with altbuild/Makefile
|
||||||
|
*/
|
||||||
|
#define HAVE_SYS_TYPES_H
|
||||||
|
#define HAVE_UNISTD_H
|
||||||
|
#define HAVE_SYS_TIME_H
|
||||||
|
#define HAVE_SYS_PARAM_H
|
||||||
|
#define HAVE_SYS_IOCTL_H
|
||||||
|
#define HAVE_FCNTL_H
|
||||||
|
#define HAVE_ERRNO_H
|
||||||
|
#define HAVE_GETTIMEOFDAY
|
||||||
|
#define HAVE_VFPRINTF
|
||||||
|
#define HAVE_ULONG_LONG
|
||||||
|
|
||||||
|
/* inttypes.h conflicts with sys/types.h */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* warning and errors printed? */
|
||||||
|
#define FREEGLUT_PRINT_WARNINGS
|
||||||
|
#define FREEGLUT_PRINT_ERRORS
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* freeglut configuration file for IRIX 6.x (tested 6.5.26)
|
||||||
|
*
|
||||||
|
* #define to enable, #undef or delete line to disable
|
||||||
|
*
|
||||||
|
* Copy to the freeglut root directory as config.h along with altbuild/Makefile
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* warning and errors printed? */
|
||||||
|
#define FREEGLUT_PRINT_WARNINGS
|
||||||
|
#define FREEGLUT_PRINT_ERRORS
|
||||||
|
|
||||||
|
/* all of these should be available on relatively modern UNIX systems */
|
||||||
|
#define HAVE_SYS_TYPES_H /* sys/types.h */
|
||||||
|
#define HAVE_UNISTD_H /* unistd.h */
|
||||||
|
#define HAVE_SYS_TIME_H /* sys/time.h */
|
||||||
|
#define HAVE_SYS_PARAM_H /* sys/param.h */
|
||||||
|
#define HAVE_SYS_IOCTL_H /* sys/ioctl.h */
|
||||||
|
#define HAVE_FCNTL_H /* fcntl.h */
|
||||||
|
#define HAVE_ERRNO_H /* errno.h */
|
||||||
|
#define HAVE_GETTIMEOFDAY /* gettimeofday() */
|
||||||
|
#define HAVE_VFPRINTF /* vfprintf() */
|
||||||
|
#define HAVE_INTTYPES_H /* inttypes.h */
|
||||||
|
#define HAVE_ULONG_LONG /* unsigned long long */
|
||||||
|
#undef HAVE_STDINT_H /* stdint.h - not available with MIPSpro cc */
|
||||||
|
|
||||||
|
/* don't need, XParseGeometry is in libX11 */
|
||||||
|
#undef NEED_XPARSEGEOMETRY_IMPL
|
||||||
|
/* __int64 fallback is for msvc */
|
||||||
|
#undef HAVE_U__INT64
|
||||||
|
/* SGI X server does not support xf86vm, xrandr, and xinput2 */
|
||||||
|
#undef HAVE_X11_EXTENSIONS_XF86VMODE_H
|
||||||
|
#undef HAVE_X11_EXTENSIONS_XRANDR_H
|
||||||
|
#undef HAVE_X11_EXTENSIONS_XINPUT2_H
|
||||||
|
/* USB HID, is only needed needed for joystick on BSD */
|
||||||
|
#undef HAVE_USBHID_H
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* freeglut configuration file for Windows with MS Visual C 6.0
|
||||||
|
*
|
||||||
|
* Copy to the freeglut root dir as config.h, and open altbuild/freeglut.dsw
|
||||||
|
* Do not move the dsw/dsp project files, leave them in altbuild.
|
||||||
|
*/
|
||||||
|
#define HAVE_SYS_TYPES_H
|
||||||
|
#define HAVE_FCNTL_H
|
||||||
|
#define HAVE_ERRNO_H
|
||||||
|
#define NEED_XPARSEGEOMETRY_IMPL
|
||||||
|
#define HAVE_U__INT64
|
||||||
|
|
||||||
|
/* warning and errors printed? */
|
||||||
|
#define FREEGLUT_PRINT_WARNINGS
|
||||||
|
#define FREEGLUT_PRINT_ERRORS
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* freeglut configuration file for GNU/Linux and BSD
|
||||||
|
*
|
||||||
|
* #define to enable, #undef or delete line to disable
|
||||||
|
*
|
||||||
|
* Copy to the freeglut root directory as config.h along with altbuild/Makefile
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XFree86 Video Mode extension, used for game mode, requires libXxf86vm */
|
||||||
|
#define HAVE_X11_EXTENSIONS_XF86VMODE_H
|
||||||
|
/* XR&R extension, used for game mode, requires libXrandr */
|
||||||
|
#define HAVE_X11_EXTENSIONS_XRANDR_H
|
||||||
|
/* XInput2 extension, used for joystick input, requires libXi */
|
||||||
|
#define HAVE_X11_EXTENSIONS_XINPUT2_H
|
||||||
|
/* USB HID, needed for joystick on BSD, requires libusbhid */
|
||||||
|
#define HAVE_USBHID_H
|
||||||
|
/* warning and errors printed? */
|
||||||
|
#define FREEGLUT_PRINT_WARNINGS
|
||||||
|
#define FREEGLUT_PRINT_ERRORS
|
||||||
|
|
||||||
|
/* all of these should be available on relatively modern UNIX systems */
|
||||||
|
#define HAVE_SYS_TYPES_H /* sys/types.h */
|
||||||
|
#define HAVE_UNISTD_H /* unistd.h */
|
||||||
|
#define HAVE_SYS_TIME_H /* sys/time.h */
|
||||||
|
#define HAVE_SYS_PARAM_H /* sys/param.h */
|
||||||
|
#define HAVE_SYS_IOCTL_H /* sys/ioctl.h */
|
||||||
|
#define HAVE_FCNTL_H /* fcntl.h */
|
||||||
|
#define HAVE_ERRNO_H /* errno.h */
|
||||||
|
#define HAVE_GETTIMEOFDAY /* gettimeofday() */
|
||||||
|
#define HAVE_VFPRINTF /* vfprintf() */
|
||||||
|
#define HAVE_STDINT_H /* stdint.h - might not be available, undef if not found */
|
||||||
|
#define HAVE_INTTYPES_H /* inttypes.h */
|
||||||
|
#define HAVE_ULONG_LONG /* unsigned long long */
|
||||||
|
|
||||||
|
/* don't need, XParseGeometry is in libX11 */
|
||||||
|
#undef NEED_XPARSEGEOMETRY_IMPL
|
||||||
|
/* __int64 fallback is for msvc */
|
||||||
|
#undef HAVE_U__INT64
|
|
@ -0,0 +1,102 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="demo" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=demo - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "demo.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "demo.mak" CFG="demo - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "demo - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "demo - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "demo - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"Release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "demo - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /FR /YX /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "demo - Win32 Release"
|
||||||
|
# Name "demo - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\progs\demos\3dview\3dview.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
|
@ -0,0 +1,318 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="freeglut" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
|
||||||
|
CFG=freeglut - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "freeglut.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "freeglut.mak" CFG="freeglut - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "freeglut - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "freeglut - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "freeglut - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FREEGLUT_EXPORTS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FREEGLUT_EXPORTS" /D "HAVE_CONFIG_H" /D _WIN32_WINNT=0x0500 /D WINVER=0x0500 /YX /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "freeglut - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FREEGLUT_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /I "../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FREEGLUT_EXPORTS" /D "HAVE_CONFIG_H" /D _WIN32_WINNT=0x0500 /D WINVER=0x0500 /YX /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug/freeglutd.dll" /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "freeglut - Win32 Release"
|
||||||
|
# Name "freeglut - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\config.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_callback_macros.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_callbacks.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_cmap_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_cursor.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_cursor_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_display.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_display_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_ext.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_ext_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_font.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_font_data.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_gamemode.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_gamemode_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_geometry.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_gl2.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_gl2.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_init.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_init.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_init_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_input_devices.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_input_devices_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_internal.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_internal_mswin.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_joystick.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_joystick_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_main.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_main_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_menu.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_menu_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_misc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_overlay.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_spaceball.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_spaceball_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_state.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_state_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_stroke_mono_roman.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_stroke_roman.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_structure.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_structure_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_teapot.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_teapot_data.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_version.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_videoresize.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_window.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_window_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\freeglutdll.def
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\util\xparsegeometry_repl.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\util\xparsegeometry_repl.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\freeglut.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\freeglut_ext.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\freeglut_std.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\freeglut_ucall.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\glut.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
|
@ -0,0 +1,59 @@
|
||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "demo"=.\demo.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
Begin Project Dependency
|
||||||
|
Project_Dep_Name freeglut_static
|
||||||
|
End Project Dependency
|
||||||
|
Begin Project Dependency
|
||||||
|
Project_Dep_Name freeglut
|
||||||
|
End Project Dependency
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "freeglut"=.\freeglut.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "freeglut_static"=.\freeglut_static.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
|
@ -0,0 +1,304 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="freeglut_static" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||||
|
|
||||||
|
CFG=freeglut_static - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "freeglut_static.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "freeglut_static.mak" CFG="freeglut_static - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "freeglut_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE "freeglut_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "freeglut_static - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release_static"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release_static"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /I ".." /I "../include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "FREEGLUT_STATIC" /D "HAVE_CONFIG_H" /D _WIN32_WINNT=0x0500 /D WINVER=0x0500 /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "freeglut_static - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug_static"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug_static"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "../include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "FREEGLUT_STATIC" /D "HAVE_CONFIG_H" /D _WIN32_WINNT=0x0500 /D WINVER=0x0500 /YX /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo /out:"Debug\freeglut_staticd.lib"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "freeglut_static - Win32 Release"
|
||||||
|
# Name "freeglut_static - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\config.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_callback_macros.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_callbacks.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_cmap_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_cursor.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_cursor_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_display.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_display_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_ext.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_ext_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_font.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_font_data.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_gamemode.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_gamemode_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_geometry.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_gl2.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_gl2.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_init.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_init.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_init_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_input_devices.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_input_devices_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_internal.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_internal_mswin.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_joystick.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_joystick_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_main.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_main_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_menu.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_menu_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_misc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_overlay.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_spaceball.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_spaceball_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_state.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_state_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_stroke_mono_roman.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_stroke_roman.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_structure.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_structure_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_teapot.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_teapot_data.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_version.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_videoresize.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fg_window.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mswin\fg_window_mswin.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\util\xparsegeometry_repl.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\util\xparsegeometry_repl.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\freeglut.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\freeglut_ext.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\freeglut_std.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\freeglut_ucall.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\Gl\glut.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
|
@ -0,0 +1,165 @@
|
||||||
|
VERSION 3.4
|
||||||
|
EXPORTS
|
||||||
|
glutInit
|
||||||
|
glutInitWindowPosition
|
||||||
|
glutInitWindowSize
|
||||||
|
glutInitDisplayMode
|
||||||
|
glutInitDisplayString
|
||||||
|
glutMainLoop
|
||||||
|
glutMainLoopEvent
|
||||||
|
glutLeaveMainLoop
|
||||||
|
glutCreateWindow
|
||||||
|
glutCreateSubWindow
|
||||||
|
glutDestroyWindow
|
||||||
|
glutSetWindow
|
||||||
|
glutGetWindow
|
||||||
|
glutSetWindowData
|
||||||
|
glutGetWindowData
|
||||||
|
glutSetWindowTitle
|
||||||
|
glutSetIconTitle
|
||||||
|
glutReshapeWindow
|
||||||
|
glutPositionWindow
|
||||||
|
glutShowWindow
|
||||||
|
glutHideWindow
|
||||||
|
glutIconifyWindow
|
||||||
|
glutPushWindow
|
||||||
|
glutPopWindow
|
||||||
|
glutFullScreen
|
||||||
|
glutPostWindowRedisplay
|
||||||
|
glutPostRedisplay
|
||||||
|
glutSwapBuffers
|
||||||
|
glutWarpPointer
|
||||||
|
glutSetCursor
|
||||||
|
glutEstablishOverlay
|
||||||
|
glutRemoveOverlay
|
||||||
|
glutUseLayer
|
||||||
|
glutPostOverlayRedisplay
|
||||||
|
glutPostWindowOverlayRedisplay
|
||||||
|
glutShowOverlay
|
||||||
|
glutHideOverlay
|
||||||
|
glutCreateMenu
|
||||||
|
glutDestroyMenu
|
||||||
|
glutGetMenu
|
||||||
|
glutSetMenu
|
||||||
|
glutGetMenuData
|
||||||
|
glutSetMenuData
|
||||||
|
glutAddMenuEntry
|
||||||
|
glutAddSubMenu
|
||||||
|
glutChangeToMenuEntry
|
||||||
|
glutChangeToSubMenu
|
||||||
|
glutRemoveMenuItem
|
||||||
|
glutAttachMenu
|
||||||
|
glutDetachMenu
|
||||||
|
glutTimerFunc
|
||||||
|
glutIdleFunc
|
||||||
|
glutKeyboardFunc
|
||||||
|
glutSpecialFunc
|
||||||
|
glutReshapeFunc
|
||||||
|
glutPositionFunc
|
||||||
|
glutVisibilityFunc
|
||||||
|
glutDisplayFunc
|
||||||
|
glutMouseFunc
|
||||||
|
glutMouseWheelFunc
|
||||||
|
glutMotionFunc
|
||||||
|
glutPassiveMotionFunc
|
||||||
|
glutEntryFunc
|
||||||
|
glutCloseFunc
|
||||||
|
glutWMCloseFunc
|
||||||
|
glutKeyboardUpFunc
|
||||||
|
glutSpecialUpFunc
|
||||||
|
glutJoystickFunc
|
||||||
|
glutMenuStateFunc
|
||||||
|
glutMenuStatusFunc
|
||||||
|
glutMenuDestroyFunc
|
||||||
|
glutOverlayDisplayFunc
|
||||||
|
glutWindowStatusFunc
|
||||||
|
glutSpaceballMotionFunc
|
||||||
|
glutSpaceballRotateFunc
|
||||||
|
glutSpaceballButtonFunc
|
||||||
|
glutButtonBoxFunc
|
||||||
|
glutDialsFunc
|
||||||
|
glutTabletMotionFunc
|
||||||
|
glutTabletButtonFunc
|
||||||
|
glutSetOption
|
||||||
|
glutGet
|
||||||
|
glutDeviceGet
|
||||||
|
glutGetModifiers
|
||||||
|
glutLayerGet
|
||||||
|
glutBitmapCharacter
|
||||||
|
glutBitmapWidth
|
||||||
|
glutStrokeCharacter
|
||||||
|
glutStrokeWidth
|
||||||
|
glutBitmapLength
|
||||||
|
glutStrokeLength
|
||||||
|
glutBitmapHeight
|
||||||
|
glutStrokeHeight
|
||||||
|
glutBitmapString
|
||||||
|
glutStrokeString
|
||||||
|
glutWireCube
|
||||||
|
glutSolidCube
|
||||||
|
glutWireSphere
|
||||||
|
glutSolidSphere
|
||||||
|
glutWireCone
|
||||||
|
glutSolidCone
|
||||||
|
glutWireTorus
|
||||||
|
glutSolidTorus
|
||||||
|
glutWireDodecahedron
|
||||||
|
glutSolidDodecahedron
|
||||||
|
glutWireOctahedron
|
||||||
|
glutSolidOctahedron
|
||||||
|
glutWireTetrahedron
|
||||||
|
glutSolidTetrahedron
|
||||||
|
glutWireIcosahedron
|
||||||
|
glutSolidIcosahedron
|
||||||
|
glutWireRhombicDodecahedron
|
||||||
|
glutSolidRhombicDodecahedron
|
||||||
|
glutWireSierpinskiSponge
|
||||||
|
glutSolidSierpinskiSponge
|
||||||
|
glutWireTeapot
|
||||||
|
glutSolidTeapot
|
||||||
|
glutWireTeacup
|
||||||
|
glutSolidTeacup
|
||||||
|
glutWireTeaspoon
|
||||||
|
glutSolidTeaspoon
|
||||||
|
glutWireCylinder
|
||||||
|
glutSolidCylinder
|
||||||
|
glutGameModeString
|
||||||
|
glutEnterGameMode
|
||||||
|
glutLeaveGameMode
|
||||||
|
glutGameModeGet
|
||||||
|
glutVideoResizeGet
|
||||||
|
glutSetupVideoResizing
|
||||||
|
glutStopVideoResizing
|
||||||
|
glutVideoResize
|
||||||
|
glutVideoPan
|
||||||
|
glutSetColor
|
||||||
|
glutGetColor
|
||||||
|
glutCopyColormap
|
||||||
|
glutIgnoreKeyRepeat
|
||||||
|
glutSetKeyRepeat
|
||||||
|
glutForceJoystickFunc
|
||||||
|
glutExtensionSupported
|
||||||
|
glutReportErrors
|
||||||
|
glutGetProcAddress
|
||||||
|
glutExit
|
||||||
|
glutFullScreenToggle
|
||||||
|
glutLeaveFullScreen
|
||||||
|
glutSetMenuFont
|
||||||
|
glutGetModeValues
|
||||||
|
glutInitContextFlags
|
||||||
|
glutInitContextVersion
|
||||||
|
glutInitContextProfile
|
||||||
|
glutInitErrorFunc
|
||||||
|
glutInitWarningFunc
|
||||||
|
__glutInitWithExit
|
||||||
|
__glutCreateWindowWithExit
|
||||||
|
__glutCreateMenuWithExit
|
||||||
|
glutMultiButtonFunc
|
||||||
|
glutMultiEntryFunc
|
||||||
|
glutMultiMotionFunc
|
||||||
|
glutMultiPassiveFunc
|
||||||
|
glutInitContextFunc
|
||||||
|
glutAppStatusFunc
|
||||||
|
glutSetVertexAttribCoord3
|
||||||
|
glutSetVertexAttribNormal
|
||||||
|
glutSetVertexAttribTexCoord2
|
|
@ -0,0 +1,9 @@
|
||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := freeglut-gles
|
||||||
|
LOCAL_SRC_FILES := lib/libfreeglut-gles.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
|
||||||
|
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
|
@ -0,0 +1,2 @@
|
||||||
|
- Android.mk : used to create a module compatible with the NDK build
|
||||||
|
system. See ../README.android for details.
|
|
@ -0,0 +1,6 @@
|
||||||
|
# CMake toolchain file, cf. README.android
|
||||||
|
SET(CMAKE_SYSTEM_NAME Linux) # Tell CMake we're cross-compiling
|
||||||
|
include(CMakeForceCompiler)
|
||||||
|
# Prefix detection only works with compiler id "GNU"
|
||||||
|
CMAKE_FORCE_C_COMPILER(arm-linux-androideabi-gcc GNU)
|
||||||
|
SET(ANDROID TRUE)
|
|
@ -0,0 +1,244 @@
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# BlackBerry CMake toolchain file, for use with the BlackBerry 10 NDK
|
||||||
|
# Requires cmake 2.6.3 or newer (2.8.3 or newer is recommended).
|
||||||
|
#
|
||||||
|
# Usage Linux:
|
||||||
|
# $ source /absolute/path/to/the/bbndk/bbndk-env.sh
|
||||||
|
# $ mkdir build
|
||||||
|
# $ cd build
|
||||||
|
# $ cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles"
|
||||||
|
# $ make -j8
|
||||||
|
#
|
||||||
|
# Usage Mac:
|
||||||
|
# Same as the steps on Linux
|
||||||
|
#
|
||||||
|
# Usage Windows:
|
||||||
|
# > /absolute/path/to/the/bbndk/bbndk-env.bat
|
||||||
|
# > mkdir build
|
||||||
|
# > cd build
|
||||||
|
# > cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles"
|
||||||
|
# > make -j8
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required( VERSION 2.6.3 )
|
||||||
|
|
||||||
|
if( DEFINED CMAKE_CROSSCOMPILING )
|
||||||
|
# Subsequent toolchain loading is not really needed
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set( BLACKBERRY_TOOLCHAIN_ROOT "$ENV{QNX_HOST}" )
|
||||||
|
set( BLACKBERRY_TARGET_ROOT "$ENV{QNX_TARGET}" )
|
||||||
|
set( CMAKE_SYSTEM_NAME Linux )
|
||||||
|
set( CMAKE_SYSTEM_VERSION 1 )
|
||||||
|
|
||||||
|
# Check for PlayBook
|
||||||
|
if( EXISTS "${BLACKBERRY_TARGET_ROOT}/x86/lib/gcc/4.4.2" )
|
||||||
|
set( PLAYBOOK True )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for for GCC 4.8.2
|
||||||
|
if( EXISTS "${BLACKBERRY_TARGET_ROOT}/x86/lib/gcc/4.8.2" )
|
||||||
|
set( BB_GCC_482 True )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# STL version: by default gnustl_static will be used
|
||||||
|
set( BLACKBERRY_USE_STLPORT FALSE CACHE BOOL "Experimental: use stlport_static instead of gnustl_static")
|
||||||
|
mark_as_advanced( BLACKBERRY_USE_STLPORT )
|
||||||
|
|
||||||
|
# Detect host platform
|
||||||
|
set( TOOL_OS_SUFFIX "" )
|
||||||
|
if( CMAKE_HOST_APPLE )
|
||||||
|
set( BLACKBERRY_NDK_HOST_SYSTEM_NAME "darwin-x86" )
|
||||||
|
elseif( CMAKE_HOST_WIN32 )
|
||||||
|
set( BLACKBERRY_NDK_HOST_SYSTEM_NAME "windows" )
|
||||||
|
set( TOOL_OS_SUFFIX ".exe" )
|
||||||
|
elseif( CMAKE_HOST_UNIX )
|
||||||
|
set(BLACKBERRY_NDK_HOST_SYSTEM_NAME "linux-x86" )
|
||||||
|
else()
|
||||||
|
message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Specify the cross compiler
|
||||||
|
set( CMAKE_C_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "gcc" )
|
||||||
|
set( CMAKE_CXX_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "g++" )
|
||||||
|
set( CMAKE_ASM_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "Assembler" )
|
||||||
|
if( CMAKE_VERSION VERSION_LESS 2.8.5 )
|
||||||
|
set( CMAKE_ASM_COMPILER_ARG1 "-c" )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# There may be a way to make cmake reduce these TODO
|
||||||
|
if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" )
|
||||||
|
set( NEUTRINO_ARCH "v7" )
|
||||||
|
else()
|
||||||
|
set( NEUTRINO_ARCH "" )
|
||||||
|
endif()
|
||||||
|
set( CMAKE_STRIP "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" )
|
||||||
|
set( CMAKE_AR "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
|
||||||
|
set( CMAKE_LINKER "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" )
|
||||||
|
set( CMAKE_NM "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" )
|
||||||
|
set( CMAKE_OBJCOPY "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
|
||||||
|
set( CMAKE_OBJDUMP "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" )
|
||||||
|
set( CMAKE_RANLIB "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" )
|
||||||
|
|
||||||
|
# Installer
|
||||||
|
#if( APPLE )
|
||||||
|
# find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
|
||||||
|
# if( NOT CMAKE_INSTALL_NAME_TOOL )
|
||||||
|
# message( FATAL_ERROR "Could not find install_name_tool, please check your #installation." )
|
||||||
|
# endif()
|
||||||
|
# mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
|
||||||
|
# endif()
|
||||||
|
|
||||||
|
# Setup output directories
|
||||||
|
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
|
||||||
|
set( CMAKE_INSTALL_PREFIX "${BLACKBERRY_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
|
||||||
|
|
||||||
|
if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
|
||||||
|
set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
|
||||||
|
else()
|
||||||
|
set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Includes
|
||||||
|
if( PLAYBOOK )
|
||||||
|
list( APPEND BLACKBERRY_SYSTEM_INCLUDE_DIRS "${BLACKBERRY_TARGET_ROOT}/usr/include" )
|
||||||
|
else()
|
||||||
|
list( APPEND BLACKBERRY_SYSTEM_INCLUDE_DIRS "${BLACKBERRY_TARGET_ROOT}/qnx6/usr/include" )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Flags and preprocessor definitions
|
||||||
|
set( BB_USING_GCC_482 False )
|
||||||
|
if( PLAYBOOK )
|
||||||
|
set( BLACKBERRY_COMP_DEF "-D__PLAYBOOK__" )
|
||||||
|
set( BLACKBERRY_COMP_VERSION "4.4.2" )
|
||||||
|
else()
|
||||||
|
set( BLACKBERRY_COMP_DEF "-D__QNX__" )
|
||||||
|
if( BB_GCC_482 AND BLACKBERRY_USE_GCC_4_8 )
|
||||||
|
set( BLACKBERRY_COMP_VERSION "4.8.2" )
|
||||||
|
set( BB_USING_GCC_482 True )
|
||||||
|
else()
|
||||||
|
set( BLACKBERRY_COMP_VERSION "4.6.3" )
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" )
|
||||||
|
set( BLACKBERRY_COMP_TARGET "gcc_ntoarmv7le" )
|
||||||
|
else()
|
||||||
|
set( BLACKBERRY_COMP_TARGET "gcc_ntox86" )
|
||||||
|
endif()
|
||||||
|
set( BLACKBERRY_CXX_COMP_LIB "" )
|
||||||
|
if( BLACKBERRY_DINKUM )
|
||||||
|
set( DINKUM 1 )
|
||||||
|
if( BB_USING_GCC_482 )
|
||||||
|
set( BLACKBERRY_COMP_TARGET "${BLACKBERRY_COMP_TARGET}_cpp" )
|
||||||
|
else()
|
||||||
|
set( BLACKBERRY_CXX_COMP_LIB "-Y_cpp" )
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set( DINKUM 0 )
|
||||||
|
if( BB_USING_GCC_482 )
|
||||||
|
set( BLACKBERRY_COMP_TARGET "${BLACKBERRY_COMP_TARGET}_gpp" )
|
||||||
|
else()
|
||||||
|
set( BLACKBERRY_CXX_COMP_LIB "-Y_gpp" )
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
set( BLACKBERRY_CC_FLAGS " -V${BLACKBERRY_COMP_VERSION},${BLACKBERRY_COMP_TARGET} ${BLACKBERRY_COMP_DEF}" )
|
||||||
|
set( BLACKBERRY_CXX_FLAGS " -V${BLACKBERRY_COMP_VERSION},${BLACKBERRY_COMP_TARGET} ${BLACKBERRY_CXX_COMP_LIB} ${BLACKBERRY_COMP_DEF}" )
|
||||||
|
set( BLACKBERRY 1 )
|
||||||
|
|
||||||
|
# NDK flags
|
||||||
|
if( DINKUM )
|
||||||
|
set( CMAKE_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS} -DBLACKBERRY_DINKUM=1" )
|
||||||
|
set( CMAKE_C_FLAGS "${BLACKBERRY_CC_FLAGS} -DBLACKBERRY_DINKUM=1" )
|
||||||
|
else()
|
||||||
|
set( CMAKE_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS}" )
|
||||||
|
set( CMAKE_C_FLAGS "${BLACKBERRY_CC_FLAGS}" )
|
||||||
|
endif()
|
||||||
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions" )
|
||||||
|
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions" )
|
||||||
|
|
||||||
|
# Release and Debug flags
|
||||||
|
if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" )
|
||||||
|
set( CMAKE_CXX_FLAGS_RELEASE "-mthumb -O3" )
|
||||||
|
set( CMAKE_C_FLAGS_RELEASE "-mthumb -O3" )
|
||||||
|
set( CMAKE_CXX_FLAGS_DEBUG "-marm -Os -finline-limit=64" )
|
||||||
|
set( CMAKE_C_FLAGS_DEBUG "-marm -Os -finline-limit=64" )
|
||||||
|
else()
|
||||||
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i486" )
|
||||||
|
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i486" )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Cache flags
|
||||||
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags" )
|
||||||
|
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags" )
|
||||||
|
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "c++ Release flags" )
|
||||||
|
set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "c Release flags" )
|
||||||
|
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "c++ Debug flags" )
|
||||||
|
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "c Debug flags" )
|
||||||
|
set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "linker flags" )
|
||||||
|
SET( CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "" CACHE STRING "linker flags")
|
||||||
|
SET( CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "" CACHE STRING "linker flags")
|
||||||
|
set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "linker flags" )
|
||||||
|
set( CMAKE_EXE_LINKER_FLAGS "-lstdc++" CACHE STRING "linker flags" )
|
||||||
|
|
||||||
|
# Finish flags
|
||||||
|
set( BLACKBERRY_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS}" CACHE INTERNAL "Extra BlackBerry compiler flags")
|
||||||
|
set( BLACKBERRY_LINKER_FLAGS "${BLACKBERRY_LINKER_FLAGS}" CACHE INTERNAL "Extra BlackBerry linker flags")
|
||||||
|
set( CMAKE_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
|
||||||
|
set( CMAKE_C_FLAGS "${BLACKBERRY_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
|
||||||
|
|
||||||
|
# Global flags for cmake client scripts to change behavior
|
||||||
|
set( BLACKBERRY True )
|
||||||
|
# Find the Target environment
|
||||||
|
set( CMAKE_FIND_ROOT_PATH "${CMAKE_SOURCE_DIR}" "${BLACKBERRY_TARGET_ROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" )
|
||||||
|
# Search for libraries and includes in the ndk toolchain
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
|
||||||
|
|
||||||
|
# Macro to find packages on the host OS
|
||||||
|
macro( find_host_package )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
|
||||||
|
if( CMAKE_HOST_WIN32 )
|
||||||
|
SET( WIN32 1 )
|
||||||
|
SET( UNIX )
|
||||||
|
elseif( CMAKE_HOST_APPLE )
|
||||||
|
SET( APPLE 1 )
|
||||||
|
SET( UNIX )
|
||||||
|
endif()
|
||||||
|
find_package( ${ARGN} )
|
||||||
|
SET( WIN32 )
|
||||||
|
SET( APPLE )
|
||||||
|
SET( UNIX 1 )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Macro to find programs on the host OS
|
||||||
|
macro( find_host_program )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
|
||||||
|
if( CMAKE_HOST_WIN32 )
|
||||||
|
SET( WIN32 1 )
|
||||||
|
SET( UNIX )
|
||||||
|
elseif( CMAKE_HOST_APPLE )
|
||||||
|
SET( APPLE 1 )
|
||||||
|
SET( UNIX )
|
||||||
|
endif()
|
||||||
|
find_program( ${ARGN} )
|
||||||
|
SET( WIN32 )
|
||||||
|
SET( APPLE )
|
||||||
|
SET( UNIX 1 )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# We are doing cross compiling, reset the OS information of the Building system
|
||||||
|
UNSET( APPLE )
|
||||||
|
UNSET( WIN32 )
|
||||||
|
UNSET( UNIX )
|
|
@ -0,0 +1,24 @@
|
||||||
|
#cmakedefine HAVE_X11_EXTENSIONS_XF86VMODE_H
|
||||||
|
#cmakedefine HAVE_X11_EXTENSIONS_XRANDR_H
|
||||||
|
#cmakedefine HAVE_X11_EXTENSIONS_XINPUT2_H
|
||||||
|
#cmakedefine HAVE_SYS_TYPES_H
|
||||||
|
#cmakedefine HAVE_UNISTD_H
|
||||||
|
#cmakedefine HAVE_SYS_TIME_H
|
||||||
|
#cmakedefine HAVE_STDBOOL_H
|
||||||
|
#cmakedefine HAVE_SYS_PARAM_H
|
||||||
|
#cmakedefine HAVE_SYS_IOCTL_H
|
||||||
|
#cmakedefine HAVE_FCNTL_H
|
||||||
|
#cmakedefine HAVE_ERRNO_H
|
||||||
|
#cmakedefine HAVE_USBHID_H
|
||||||
|
#cmakedefine HAVE_GETTIMEOFDAY
|
||||||
|
#cmakedefine HAVE_VFPRINTF
|
||||||
|
#cmakedefine HAVE_DOPRNT
|
||||||
|
#cmakedefine NEED_XPARSEGEOMETRY_IMPL
|
||||||
|
#cmakedefine HAVE_STDINT_H
|
||||||
|
#cmakedefine HAVE_INTTYPES_H
|
||||||
|
#cmakedefine HAVE_ULONG_LONG
|
||||||
|
#cmakedefine HAVE_U__INT64
|
||||||
|
|
||||||
|
/* warning and errors printed? */
|
||||||
|
#cmakedefine FREEGLUT_PRINT_WARNINGS
|
||||||
|
#cmakedefine FREEGLUT_PRINT_ERRORS
|
|
@ -0,0 +1,10 @@
|
||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||||
|
includedir=${prefix}/include
|
||||||
|
|
||||||
|
Name: glut
|
||||||
|
Description: A freely licensed and improved alternative to the GLUT library
|
||||||
|
Version: @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@
|
||||||
|
Libs: -L${libdir} -l@PC_LIBNAME@
|
||||||
|
Libs.private: @PC_LIBS_PRIVATE@
|
||||||
|
Cflags: -I${includedir} @PC_CFLAGS@
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
/* 0 ICON DISCARDABLE "OpenGL.ico" */
|
||||||
|
|
||||||
|
1 VERSIONINFO
|
||||||
|
FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
|
||||||
|
PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x1L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "080904b0"
|
||||||
|
BEGIN
|
||||||
|
/* VALUE "Comments", "\0" */
|
||||||
|
/* VALUE "CompanyName", "\0" */
|
||||||
|
VALUE "FileDescription", "Freeglut OpenGL Utility Toolkit\0"
|
||||||
|
VALUE "FileVersion", "@VERSION_MAJOR@, @VERSION_MINOR@, @VERSION_PATCH@, 0\0"
|
||||||
|
VALUE "InternalName", "freeglutdll\0"
|
||||||
|
VALUE "LegalCopyright", "Copyright © 1999-2000 Pawel W. Olszta, 2000-2012 Stephen J. Baker\0"
|
||||||
|
/* VALUE "LegalTrademarks", "\0" */
|
||||||
|
VALUE "OriginalFilename", "freeglut.dll\0"
|
||||||
|
/* VALUE "PrivateBuild", "\0" */
|
||||||
|
VALUE "ProductName", "Freeglut OpenGL Utility Toolkit\0"
|
||||||
|
VALUE "ProductVersion", "@VERSION_MAJOR@, @VERSION_MINOR@, @VERSION_PATCH@, 0\0"
|
||||||
|
/* VALUE "SpecialBuild", "\0" */
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x809, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef __FREEGLUT_H__
|
||||||
|
#define __FREEGLUT_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* freeglut.h
|
||||||
|
*
|
||||||
|
* The freeglut library include file
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "freeglut_std.h"
|
||||||
|
#include "freeglut_ext.h"
|
||||||
|
|
||||||
|
/*** END OF FILE ***/
|
||||||
|
|
||||||
|
#endif /* __FREEGLUT_H__ */
|
|
@ -0,0 +1,295 @@
|
||||||
|
#ifndef __FREEGLUT_EXT_H__
|
||||||
|
#define __FREEGLUT_EXT_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* freeglut_ext.h
|
||||||
|
*
|
||||||
|
* The non-GLUT-compatible extensions to the freeglut library include file
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
|
||||||
|
* Creation date: Thu Dec 2 1999
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additional GLUT Key definitions for the Special key function
|
||||||
|
*/
|
||||||
|
#define GLUT_KEY_NUM_LOCK 0x006D
|
||||||
|
#define GLUT_KEY_BEGIN 0x006E
|
||||||
|
#define GLUT_KEY_DELETE 0x006F
|
||||||
|
#define GLUT_KEY_SHIFT_L 0x0070
|
||||||
|
#define GLUT_KEY_SHIFT_R 0x0071
|
||||||
|
#define GLUT_KEY_CTRL_L 0x0072
|
||||||
|
#define GLUT_KEY_CTRL_R 0x0073
|
||||||
|
#define GLUT_KEY_ALT_L 0x0074
|
||||||
|
#define GLUT_KEY_ALT_R 0x0075
|
||||||
|
#define GLUT_KEY_SUPER_L 0x0076
|
||||||
|
#define GLUT_KEY_SUPER_R 0x0077
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additional GLUT modifiers
|
||||||
|
*/
|
||||||
|
#define GLUT_ACTIVE_SUPER 0x0008
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API Extension macro definitions -- behaviour when the user clicks on an "x" to close a window
|
||||||
|
*/
|
||||||
|
#define GLUT_ACTION_EXIT 0
|
||||||
|
#define GLUT_ACTION_GLUTMAINLOOP_RETURNS 1
|
||||||
|
#define GLUT_ACTION_CONTINUE_EXECUTION 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new rendering context when the user opens a new window?
|
||||||
|
*/
|
||||||
|
#define GLUT_CREATE_NEW_CONTEXT 0
|
||||||
|
#define GLUT_USE_CURRENT_CONTEXT 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Direct/Indirect rendering context options (has meaning only in Unix/X11)
|
||||||
|
*/
|
||||||
|
#define GLUT_FORCE_INDIRECT_CONTEXT 0
|
||||||
|
#define GLUT_ALLOW_DIRECT_CONTEXT 1
|
||||||
|
#define GLUT_TRY_DIRECT_CONTEXT 2
|
||||||
|
#define GLUT_FORCE_DIRECT_CONTEXT 3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API Extension macro definitions -- the glutGet parameters
|
||||||
|
*/
|
||||||
|
#define GLUT_INIT_STATE 0x007C
|
||||||
|
|
||||||
|
#define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9
|
||||||
|
|
||||||
|
#define GLUT_WINDOW_BORDER_WIDTH 0x01FA
|
||||||
|
#define GLUT_WINDOW_BORDER_HEIGHT 0x01FB
|
||||||
|
#define GLUT_WINDOW_HEADER_HEIGHT 0x01FB /* Docs say it should always have been GLUT_WINDOW_BORDER_HEIGHT, keep this for backward compatibility */
|
||||||
|
|
||||||
|
#define GLUT_VERSION 0x01FC
|
||||||
|
|
||||||
|
#define GLUT_RENDERING_CONTEXT 0x01FD
|
||||||
|
#define GLUT_DIRECT_RENDERING 0x01FE
|
||||||
|
|
||||||
|
#define GLUT_FULL_SCREEN 0x01FF
|
||||||
|
|
||||||
|
#define GLUT_SKIP_STALE_MOTION_EVENTS 0x0204
|
||||||
|
|
||||||
|
#define GLUT_GEOMETRY_VISUALIZE_NORMALS 0x0205
|
||||||
|
|
||||||
|
#define GLUT_STROKE_FONT_DRAW_JOIN_DOTS 0x0206 /* Draw dots between line segments of stroke fonts? */
|
||||||
|
|
||||||
|
#define GLUT_ALLOW_NEGATIVE_WINDOW_POSITION 0x0207 /* GLUT doesn't allow negative window positions by default */
|
||||||
|
|
||||||
|
#define GLUT_WINDOW_SRGB 0x007D
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New tokens for glutInitDisplayMode.
|
||||||
|
* Only one GLUT_AUXn bit may be used at a time.
|
||||||
|
* Value 0x0400 is defined in OpenGLUT.
|
||||||
|
*/
|
||||||
|
#define GLUT_AUX 0x1000
|
||||||
|
|
||||||
|
#define GLUT_AUX1 0x1000
|
||||||
|
#define GLUT_AUX2 0x2000
|
||||||
|
#define GLUT_AUX3 0x4000
|
||||||
|
#define GLUT_AUX4 0x8000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Context-related flags, see fg_state.c
|
||||||
|
* Set the requested OpenGL version
|
||||||
|
*/
|
||||||
|
#define GLUT_INIT_MAJOR_VERSION 0x0200
|
||||||
|
#define GLUT_INIT_MINOR_VERSION 0x0201
|
||||||
|
#define GLUT_INIT_FLAGS 0x0202
|
||||||
|
#define GLUT_INIT_PROFILE 0x0203
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags for glutInitContextFlags, see fg_init.c
|
||||||
|
*/
|
||||||
|
#define GLUT_DEBUG 0x0001
|
||||||
|
#define GLUT_FORWARD_COMPATIBLE 0x0002
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags for glutInitContextProfile, see fg_init.c
|
||||||
|
*/
|
||||||
|
#define GLUT_CORE_PROFILE 0x0001
|
||||||
|
#define GLUT_COMPATIBILITY_PROFILE 0x0002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API Extension macro definitions -- Spaceball button definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GLUT_SPACEBALL_BUTTON_A 0x0001
|
||||||
|
#define GLUT_SPACEBALL_BUTTON_B 0x0002
|
||||||
|
#define GLUT_SPACEBALL_BUTTON_C 0x0004
|
||||||
|
#define GLUT_SPACEBALL_BUTTON_D 0x0008
|
||||||
|
#define GLUT_SPACEBALL_BUTTON_E 0x0010
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process loop function, see fg_main.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutMainLoopEvent( void );
|
||||||
|
FGAPI void FGAPIENTRY glutLeaveMainLoop( void );
|
||||||
|
FGAPI void FGAPIENTRY glutExit ( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Window management functions, see fg_window.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutFullScreenToggle( void );
|
||||||
|
FGAPI void FGAPIENTRY glutLeaveFullScreen( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Menu functions
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutSetMenuFont( int menuID, void* font );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Window-specific callback functions, see fg_callbacks.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutPositionFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutCloseFunc( void (* callback)( void ) );
|
||||||
|
FGAPI void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) );
|
||||||
|
/* And also a destruction callback for menus */
|
||||||
|
FGAPI void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* State setting and retrieval functions, see fg_state.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutSetOption ( GLenum option_flag, int value );
|
||||||
|
FGAPI int * FGAPIENTRY glutGetModeValues(GLenum mode, int * size);
|
||||||
|
/* A.Donev: User-data manipulation */
|
||||||
|
FGAPI void* FGAPIENTRY glutGetWindowData( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSetWindowData(void* data);
|
||||||
|
FGAPI void* FGAPIENTRY glutGetMenuData( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSetMenuData(void* data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Font stuff, see fg_font.c
|
||||||
|
*/
|
||||||
|
FGAPI int FGAPIENTRY glutBitmapHeight( void* font );
|
||||||
|
FGAPI GLfloat FGAPIENTRY glutStrokeHeight( void* font );
|
||||||
|
FGAPI void FGAPIENTRY glutBitmapString( void* font, const unsigned char *string );
|
||||||
|
FGAPI void FGAPIENTRY glutStrokeString( void* font, const unsigned char *string );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Geometry functions, see fg_geometry.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutWireRhombicDodecahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidRhombicDodecahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, double offset[3], double scale );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, double offset[3], double scale );
|
||||||
|
FGAPI void FGAPIENTRY glutWireCylinder( double radius, double height, GLint slices, GLint stacks);
|
||||||
|
FGAPI void FGAPIENTRY glutSolidCylinder( double radius, double height, GLint slices, GLint stacks);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rest of functions for rendering Newell's teaset, found in fg_teapot.c
|
||||||
|
* NB: front facing polygons have clockwise winding, not counter clockwise
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutWireTeacup( double size );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidTeacup( double size );
|
||||||
|
FGAPI void FGAPIENTRY glutWireTeaspoon( double size );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidTeaspoon( double size );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extension functions, see fg_ext.c
|
||||||
|
*/
|
||||||
|
typedef void (*GLUTproc)();
|
||||||
|
FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Multi-touch/multi-pointer extensions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GLUT_HAS_MULTI 1
|
||||||
|
|
||||||
|
/* TODO: add device_id parameter,
|
||||||
|
cf. http://sourceforge.net/mailarchive/forum.php?thread_name=20120518071314.GA28061%40perso.beuc.net&forum_name=freeglut-developer */
|
||||||
|
FGAPI void FGAPIENTRY glutMultiEntryFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutMultiButtonFunc( void (* callback)( int, int, int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutMultiMotionFunc( void (* callback)( int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutMultiPassiveFunc( void (* callback)( int, int, int ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Joystick functions, see fg_joystick.c
|
||||||
|
*/
|
||||||
|
/* USE OF THESE FUNCTIONS IS DEPRECATED !!!!! */
|
||||||
|
/* If you have a serious need for these functions in your application, please either
|
||||||
|
* contact the "freeglut" developer community at freeglut-developer@lists.sourceforge.net,
|
||||||
|
* switch to the OpenGLUT library, or else port your joystick functionality over to PLIB's
|
||||||
|
* "js" library.
|
||||||
|
*/
|
||||||
|
int glutJoystickGetNumAxes( int ident );
|
||||||
|
int glutJoystickGetNumButtons( int ident );
|
||||||
|
int glutJoystickNotWorking( int ident );
|
||||||
|
float glutJoystickGetDeadBand( int ident, int axis );
|
||||||
|
void glutJoystickSetDeadBand( int ident, int axis, float db );
|
||||||
|
float glutJoystickGetSaturation( int ident, int axis );
|
||||||
|
void glutJoystickSetSaturation( int ident, int axis, float st );
|
||||||
|
void glutJoystickSetMinRange( int ident, float *axes );
|
||||||
|
void glutJoystickSetMaxRange( int ident, float *axes );
|
||||||
|
void glutJoystickSetCenter( int ident, float *axes );
|
||||||
|
void glutJoystickGetMinRange( int ident, float *axes );
|
||||||
|
void glutJoystickGetMaxRange( int ident, float *axes );
|
||||||
|
void glutJoystickGetCenter( int ident, float *axes );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization functions, see fg_init.c
|
||||||
|
*/
|
||||||
|
/* to get the typedef for va_list */
|
||||||
|
#include <stdarg.h>
|
||||||
|
FGAPI void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion );
|
||||||
|
FGAPI void FGAPIENTRY glutInitContextFlags( int flags );
|
||||||
|
FGAPI void FGAPIENTRY glutInitContextProfile( int profile );
|
||||||
|
FGAPI void FGAPIENTRY glutInitErrorFunc( void (* callback)( const char *fmt, va_list ap ) );
|
||||||
|
FGAPI void FGAPIENTRY glutInitWarningFunc( void (* callback)( const char *fmt, va_list ap ) );
|
||||||
|
|
||||||
|
/* OpenGL >= 2.0 support */
|
||||||
|
FGAPI void FGAPIENTRY glutSetVertexAttribCoord3( GLint attrib );
|
||||||
|
FGAPI void FGAPIENTRY glutSetVertexAttribNormal( GLint attrib );
|
||||||
|
FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2( GLint attrib );
|
||||||
|
|
||||||
|
/* Mobile platforms lifecycle */
|
||||||
|
FGAPI void FGAPIENTRY glutInitContextFunc( void (* callback)( void ) );
|
||||||
|
FGAPI void FGAPIENTRY glutAppStatusFunc( void (* callback)( int ) );
|
||||||
|
/* state flags that can be passed to callback set by glutAppStatusFunc */
|
||||||
|
#define GLUT_APPSTATUS_PAUSE 0x0001
|
||||||
|
#define GLUT_APPSTATUS_RESUME 0x0002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the display mode definitions
|
||||||
|
*/
|
||||||
|
#define GLUT_CAPTIONLESS 0x0400
|
||||||
|
#define GLUT_BORDERLESS 0x0800
|
||||||
|
#define GLUT_SRGB 0x1000
|
||||||
|
|
||||||
|
/* User-argument callbacks and implementation */
|
||||||
|
#include "freeglut_ucall.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*** END OF FILE ***/
|
||||||
|
|
||||||
|
#endif /* __FREEGLUT_EXT_H__ */
|
|
@ -0,0 +1,653 @@
|
||||||
|
#ifndef __FREEGLUT_STD_H__
|
||||||
|
#define __FREEGLUT_STD_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* freeglut_std.h
|
||||||
|
*
|
||||||
|
* The GLUT-compatible part of the freeglut library include file
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
|
||||||
|
* Creation date: Thu Dec 2 1999
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Under windows, we have to differentiate between static and dynamic libraries
|
||||||
|
*/
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* #pragma may not be supported by some compilers.
|
||||||
|
* Discussion by FreeGLUT developers suggests that
|
||||||
|
* Visual C++ specific code involving pragmas may
|
||||||
|
* need to move to a separate header. 24th Dec 2003
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define FREEGLUT_LIB_PRAGMAS to 1 to include library
|
||||||
|
* pragmas or to 0 to exclude library pragmas.
|
||||||
|
* The default behavior depends on the compiler/platform.
|
||||||
|
*/
|
||||||
|
# ifndef FREEGLUT_LIB_PRAGMAS
|
||||||
|
# if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(_WIN32_WCE)
|
||||||
|
# define FREEGLUT_LIB_PRAGMAS 1
|
||||||
|
# else
|
||||||
|
# define FREEGLUT_LIB_PRAGMAS 0
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
# define WIN32_LEAN_AND_MEAN 1
|
||||||
|
# endif
|
||||||
|
# ifndef NOMINMAX
|
||||||
|
# define NOMINMAX
|
||||||
|
# endif
|
||||||
|
# include <windows.h>
|
||||||
|
|
||||||
|
/* Windows static library */
|
||||||
|
# ifdef FREEGLUT_STATIC
|
||||||
|
|
||||||
|
# define FGAPI
|
||||||
|
# define FGAPIENTRY
|
||||||
|
|
||||||
|
/* Link with Win32 static freeglut lib */
|
||||||
|
# if FREEGLUT_LIB_PRAGMAS
|
||||||
|
# ifdef NDEBUG
|
||||||
|
# pragma comment (lib, "freeglut_static.lib")
|
||||||
|
# else
|
||||||
|
# pragma comment (lib, "freeglut_staticd.lib")
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Windows shared library (DLL) */
|
||||||
|
# else
|
||||||
|
|
||||||
|
# define FGAPIENTRY __stdcall
|
||||||
|
# if defined(FREEGLUT_EXPORTS)
|
||||||
|
# define FGAPI __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define FGAPI __declspec(dllimport)
|
||||||
|
|
||||||
|
/* Link with Win32 shared freeglut lib */
|
||||||
|
# if FREEGLUT_LIB_PRAGMAS
|
||||||
|
# ifdef NDEBUG
|
||||||
|
# pragma comment (lib, "freeglut.lib")
|
||||||
|
# else
|
||||||
|
# pragma comment (lib, "freeglutd.lib")
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Drag in other Windows libraries as required by FreeGLUT */
|
||||||
|
# if FREEGLUT_LIB_PRAGMAS
|
||||||
|
# pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib */
|
||||||
|
# pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib */
|
||||||
|
# pragma comment (lib, "gdi32.lib") /* link Windows GDI lib */
|
||||||
|
# pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib */
|
||||||
|
# pragma comment (lib, "user32.lib") /* link Windows user lib */
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* Non-Windows definition of FGAPI and FGAPIENTRY */
|
||||||
|
# define FGAPI
|
||||||
|
# define FGAPIENTRY
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The freeglut and GLUT API versions
|
||||||
|
*/
|
||||||
|
#define FREEGLUT 1
|
||||||
|
#define GLUT_API_VERSION 4
|
||||||
|
#define GLUT_XLIB_IMPLEMENTATION 13
|
||||||
|
/* Deprecated:
|
||||||
|
cf. http://sourceforge.net/mailarchive/forum.php?thread_name=CABcAi1hw7cr4xtigckaGXB5X8wddLfMcbA_rZ3NAuwMrX_zmsw%40mail.gmail.com&forum_name=freeglut-developer */
|
||||||
|
#define FREEGLUT_VERSION_2_0 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always include OpenGL and GLU headers
|
||||||
|
*/
|
||||||
|
/* Note: FREEGLUT_GLES is only used to cleanly bootstrap headers
|
||||||
|
inclusion here; use GLES constants directly
|
||||||
|
(e.g. GL_ES_VERSION_2_0) for all other needs */
|
||||||
|
#ifdef FREEGLUT_GLES
|
||||||
|
# include <EGL/egl.h>
|
||||||
|
# include <GLES/gl.h>
|
||||||
|
# include <GLES2/gl2.h>
|
||||||
|
#elif __APPLE__
|
||||||
|
# include <OpenGL/gl.h>
|
||||||
|
# include <OpenGL/glu.h>
|
||||||
|
#else
|
||||||
|
# include <GL/gl.h>
|
||||||
|
# include <GL/glu.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the special key codes:
|
||||||
|
*/
|
||||||
|
#define GLUT_KEY_F1 0x0001
|
||||||
|
#define GLUT_KEY_F2 0x0002
|
||||||
|
#define GLUT_KEY_F3 0x0003
|
||||||
|
#define GLUT_KEY_F4 0x0004
|
||||||
|
#define GLUT_KEY_F5 0x0005
|
||||||
|
#define GLUT_KEY_F6 0x0006
|
||||||
|
#define GLUT_KEY_F7 0x0007
|
||||||
|
#define GLUT_KEY_F8 0x0008
|
||||||
|
#define GLUT_KEY_F9 0x0009
|
||||||
|
#define GLUT_KEY_F10 0x000A
|
||||||
|
#define GLUT_KEY_F11 0x000B
|
||||||
|
#define GLUT_KEY_F12 0x000C
|
||||||
|
#define GLUT_KEY_LEFT 0x0064
|
||||||
|
#define GLUT_KEY_UP 0x0065
|
||||||
|
#define GLUT_KEY_RIGHT 0x0066
|
||||||
|
#define GLUT_KEY_DOWN 0x0067
|
||||||
|
#define GLUT_KEY_PAGE_UP 0x0068
|
||||||
|
#define GLUT_KEY_PAGE_DOWN 0x0069
|
||||||
|
#define GLUT_KEY_HOME 0x006A
|
||||||
|
#define GLUT_KEY_END 0x006B
|
||||||
|
#define GLUT_KEY_INSERT 0x006C
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- mouse state definitions
|
||||||
|
*/
|
||||||
|
#define GLUT_LEFT_BUTTON 0x0000
|
||||||
|
#define GLUT_MIDDLE_BUTTON 0x0001
|
||||||
|
#define GLUT_RIGHT_BUTTON 0x0002
|
||||||
|
#define GLUT_DOWN 0x0000
|
||||||
|
#define GLUT_UP 0x0001
|
||||||
|
#define GLUT_LEFT 0x0000
|
||||||
|
#define GLUT_ENTERED 0x0001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the display mode definitions
|
||||||
|
*/
|
||||||
|
#define GLUT_RGB 0x0000
|
||||||
|
#define GLUT_RGBA 0x0000
|
||||||
|
#define GLUT_INDEX 0x0001
|
||||||
|
#define GLUT_SINGLE 0x0000
|
||||||
|
#define GLUT_DOUBLE 0x0002
|
||||||
|
#define GLUT_ACCUM 0x0004
|
||||||
|
#define GLUT_ALPHA 0x0008
|
||||||
|
#define GLUT_DEPTH 0x0010
|
||||||
|
#define GLUT_STENCIL 0x0020
|
||||||
|
#define GLUT_MULTISAMPLE 0x0080
|
||||||
|
#define GLUT_STEREO 0x0100
|
||||||
|
#define GLUT_LUMINANCE 0x0200
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- windows and menu related definitions
|
||||||
|
*/
|
||||||
|
#define GLUT_MENU_NOT_IN_USE 0x0000
|
||||||
|
#define GLUT_MENU_IN_USE 0x0001
|
||||||
|
#define GLUT_NOT_VISIBLE 0x0000
|
||||||
|
#define GLUT_VISIBLE 0x0001
|
||||||
|
#define GLUT_HIDDEN 0x0000
|
||||||
|
#define GLUT_FULLY_RETAINED 0x0001
|
||||||
|
#define GLUT_PARTIALLY_RETAINED 0x0002
|
||||||
|
#define GLUT_FULLY_COVERED 0x0003
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- fonts definitions
|
||||||
|
*
|
||||||
|
* Steve Baker suggested to make it binary compatible with GLUT:
|
||||||
|
*/
|
||||||
|
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WATCOMC__)
|
||||||
|
# define GLUT_STROKE_ROMAN ((void *)0x0000)
|
||||||
|
# define GLUT_STROKE_MONO_ROMAN ((void *)0x0001)
|
||||||
|
# define GLUT_BITMAP_9_BY_15 ((void *)0x0002)
|
||||||
|
# define GLUT_BITMAP_8_BY_13 ((void *)0x0003)
|
||||||
|
# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *)0x0004)
|
||||||
|
# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *)0x0005)
|
||||||
|
# define GLUT_BITMAP_HELVETICA_10 ((void *)0x0006)
|
||||||
|
# define GLUT_BITMAP_HELVETICA_12 ((void *)0x0007)
|
||||||
|
# define GLUT_BITMAP_HELVETICA_18 ((void *)0x0008)
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* I don't really know if it's a good idea... But here it goes:
|
||||||
|
*/
|
||||||
|
extern void* glutStrokeRoman;
|
||||||
|
extern void* glutStrokeMonoRoman;
|
||||||
|
extern void* glutBitmap9By15;
|
||||||
|
extern void* glutBitmap8By13;
|
||||||
|
extern void* glutBitmapTimesRoman10;
|
||||||
|
extern void* glutBitmapTimesRoman24;
|
||||||
|
extern void* glutBitmapHelvetica10;
|
||||||
|
extern void* glutBitmapHelvetica12;
|
||||||
|
extern void* glutBitmapHelvetica18;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Those pointers will be used by following definitions:
|
||||||
|
*/
|
||||||
|
# define GLUT_STROKE_ROMAN ((void *) &glutStrokeRoman)
|
||||||
|
# define GLUT_STROKE_MONO_ROMAN ((void *) &glutStrokeMonoRoman)
|
||||||
|
# define GLUT_BITMAP_9_BY_15 ((void *) &glutBitmap9By15)
|
||||||
|
# define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13)
|
||||||
|
# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *) &glutBitmapTimesRoman10)
|
||||||
|
# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *) &glutBitmapTimesRoman24)
|
||||||
|
# define GLUT_BITMAP_HELVETICA_10 ((void *) &glutBitmapHelvetica10)
|
||||||
|
# define GLUT_BITMAP_HELVETICA_12 ((void *) &glutBitmapHelvetica12)
|
||||||
|
# define GLUT_BITMAP_HELVETICA_18 ((void *) &glutBitmapHelvetica18)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the glutGet parameters
|
||||||
|
*/
|
||||||
|
#define GLUT_WINDOW_X 0x0064
|
||||||
|
#define GLUT_WINDOW_Y 0x0065
|
||||||
|
#define GLUT_WINDOW_WIDTH 0x0066
|
||||||
|
#define GLUT_WINDOW_HEIGHT 0x0067
|
||||||
|
#define GLUT_WINDOW_BUFFER_SIZE 0x0068
|
||||||
|
#define GLUT_WINDOW_STENCIL_SIZE 0x0069
|
||||||
|
#define GLUT_WINDOW_DEPTH_SIZE 0x006A
|
||||||
|
#define GLUT_WINDOW_RED_SIZE 0x006B
|
||||||
|
#define GLUT_WINDOW_GREEN_SIZE 0x006C
|
||||||
|
#define GLUT_WINDOW_BLUE_SIZE 0x006D
|
||||||
|
#define GLUT_WINDOW_ALPHA_SIZE 0x006E
|
||||||
|
#define GLUT_WINDOW_ACCUM_RED_SIZE 0x006F
|
||||||
|
#define GLUT_WINDOW_ACCUM_GREEN_SIZE 0x0070
|
||||||
|
#define GLUT_WINDOW_ACCUM_BLUE_SIZE 0x0071
|
||||||
|
#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 0x0072
|
||||||
|
#define GLUT_WINDOW_DOUBLEBUFFER 0x0073
|
||||||
|
#define GLUT_WINDOW_RGBA 0x0074
|
||||||
|
#define GLUT_WINDOW_PARENT 0x0075
|
||||||
|
#define GLUT_WINDOW_NUM_CHILDREN 0x0076
|
||||||
|
#define GLUT_WINDOW_COLORMAP_SIZE 0x0077
|
||||||
|
#define GLUT_WINDOW_NUM_SAMPLES 0x0078
|
||||||
|
#define GLUT_WINDOW_STEREO 0x0079
|
||||||
|
#define GLUT_WINDOW_CURSOR 0x007A
|
||||||
|
|
||||||
|
#define GLUT_SCREEN_WIDTH 0x00C8
|
||||||
|
#define GLUT_SCREEN_HEIGHT 0x00C9
|
||||||
|
#define GLUT_SCREEN_WIDTH_MM 0x00CA
|
||||||
|
#define GLUT_SCREEN_HEIGHT_MM 0x00CB
|
||||||
|
#define GLUT_MENU_NUM_ITEMS 0x012C
|
||||||
|
#define GLUT_DISPLAY_MODE_POSSIBLE 0x0190
|
||||||
|
#define GLUT_INIT_WINDOW_X 0x01F4
|
||||||
|
#define GLUT_INIT_WINDOW_Y 0x01F5
|
||||||
|
#define GLUT_INIT_WINDOW_WIDTH 0x01F6
|
||||||
|
#define GLUT_INIT_WINDOW_HEIGHT 0x01F7
|
||||||
|
#define GLUT_INIT_DISPLAY_MODE 0x01F8
|
||||||
|
#define GLUT_ELAPSED_TIME 0x02BC
|
||||||
|
#define GLUT_WINDOW_FORMAT_ID 0x007B
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the glutDeviceGet parameters
|
||||||
|
*/
|
||||||
|
#define GLUT_HAS_KEYBOARD 0x0258
|
||||||
|
#define GLUT_HAS_MOUSE 0x0259
|
||||||
|
#define GLUT_HAS_SPACEBALL 0x025A
|
||||||
|
#define GLUT_HAS_DIAL_AND_BUTTON_BOX 0x025B
|
||||||
|
#define GLUT_HAS_TABLET 0x025C
|
||||||
|
#define GLUT_NUM_MOUSE_BUTTONS 0x025D
|
||||||
|
#define GLUT_NUM_SPACEBALL_BUTTONS 0x025E
|
||||||
|
#define GLUT_NUM_BUTTON_BOX_BUTTONS 0x025F
|
||||||
|
#define GLUT_NUM_DIALS 0x0260
|
||||||
|
#define GLUT_NUM_TABLET_BUTTONS 0x0261
|
||||||
|
#define GLUT_DEVICE_IGNORE_KEY_REPEAT 0x0262
|
||||||
|
#define GLUT_DEVICE_KEY_REPEAT 0x0263
|
||||||
|
#define GLUT_HAS_JOYSTICK 0x0264
|
||||||
|
#define GLUT_OWNS_JOYSTICK 0x0265
|
||||||
|
#define GLUT_JOYSTICK_BUTTONS 0x0266
|
||||||
|
#define GLUT_JOYSTICK_AXES 0x0267
|
||||||
|
#define GLUT_JOYSTICK_POLL_RATE 0x0268
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the glutLayerGet parameters
|
||||||
|
*/
|
||||||
|
#define GLUT_OVERLAY_POSSIBLE 0x0320
|
||||||
|
#define GLUT_LAYER_IN_USE 0x0321
|
||||||
|
#define GLUT_HAS_OVERLAY 0x0322
|
||||||
|
#define GLUT_TRANSPARENT_INDEX 0x0323
|
||||||
|
#define GLUT_NORMAL_DAMAGED 0x0324
|
||||||
|
#define GLUT_OVERLAY_DAMAGED 0x0325
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the glutVideoResizeGet parameters
|
||||||
|
*/
|
||||||
|
#define GLUT_VIDEO_RESIZE_POSSIBLE 0x0384
|
||||||
|
#define GLUT_VIDEO_RESIZE_IN_USE 0x0385
|
||||||
|
#define GLUT_VIDEO_RESIZE_X_DELTA 0x0386
|
||||||
|
#define GLUT_VIDEO_RESIZE_Y_DELTA 0x0387
|
||||||
|
#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 0x0388
|
||||||
|
#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 0x0389
|
||||||
|
#define GLUT_VIDEO_RESIZE_X 0x038A
|
||||||
|
#define GLUT_VIDEO_RESIZE_Y 0x038B
|
||||||
|
#define GLUT_VIDEO_RESIZE_WIDTH 0x038C
|
||||||
|
#define GLUT_VIDEO_RESIZE_HEIGHT 0x038D
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the glutUseLayer parameters
|
||||||
|
*/
|
||||||
|
#define GLUT_NORMAL 0x0000
|
||||||
|
#define GLUT_OVERLAY 0x0001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the glutGetModifiers parameters
|
||||||
|
*/
|
||||||
|
#define GLUT_ACTIVE_SHIFT 0x0001
|
||||||
|
#define GLUT_ACTIVE_CTRL 0x0002
|
||||||
|
#define GLUT_ACTIVE_ALT 0x0004
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- the glutSetCursor parameters
|
||||||
|
*/
|
||||||
|
#define GLUT_CURSOR_RIGHT_ARROW 0x0000
|
||||||
|
#define GLUT_CURSOR_LEFT_ARROW 0x0001
|
||||||
|
#define GLUT_CURSOR_INFO 0x0002
|
||||||
|
#define GLUT_CURSOR_DESTROY 0x0003
|
||||||
|
#define GLUT_CURSOR_HELP 0x0004
|
||||||
|
#define GLUT_CURSOR_CYCLE 0x0005
|
||||||
|
#define GLUT_CURSOR_SPRAY 0x0006
|
||||||
|
#define GLUT_CURSOR_WAIT 0x0007
|
||||||
|
#define GLUT_CURSOR_TEXT 0x0008
|
||||||
|
#define GLUT_CURSOR_CROSSHAIR 0x0009
|
||||||
|
#define GLUT_CURSOR_UP_DOWN 0x000A
|
||||||
|
#define GLUT_CURSOR_LEFT_RIGHT 0x000B
|
||||||
|
#define GLUT_CURSOR_TOP_SIDE 0x000C
|
||||||
|
#define GLUT_CURSOR_BOTTOM_SIDE 0x000D
|
||||||
|
#define GLUT_CURSOR_LEFT_SIDE 0x000E
|
||||||
|
#define GLUT_CURSOR_RIGHT_SIDE 0x000F
|
||||||
|
#define GLUT_CURSOR_TOP_LEFT_CORNER 0x0010
|
||||||
|
#define GLUT_CURSOR_TOP_RIGHT_CORNER 0x0011
|
||||||
|
#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 0x0012
|
||||||
|
#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 0x0013
|
||||||
|
#define GLUT_CURSOR_INHERIT 0x0064
|
||||||
|
#define GLUT_CURSOR_NONE 0x0065
|
||||||
|
#define GLUT_CURSOR_FULL_CROSSHAIR 0x0066
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- RGB color component specification definitions
|
||||||
|
*/
|
||||||
|
#define GLUT_RED 0x0000
|
||||||
|
#define GLUT_GREEN 0x0001
|
||||||
|
#define GLUT_BLUE 0x0002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- additional keyboard and joystick definitions
|
||||||
|
*/
|
||||||
|
#define GLUT_KEY_REPEAT_OFF 0x0000
|
||||||
|
#define GLUT_KEY_REPEAT_ON 0x0001
|
||||||
|
#define GLUT_KEY_REPEAT_DEFAULT 0x0002
|
||||||
|
|
||||||
|
#define GLUT_JOYSTICK_BUTTON_A 0x0001
|
||||||
|
#define GLUT_JOYSTICK_BUTTON_B 0x0002
|
||||||
|
#define GLUT_JOYSTICK_BUTTON_C 0x0004
|
||||||
|
#define GLUT_JOYSTICK_BUTTON_D 0x0008
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GLUT API macro definitions -- game mode definitions
|
||||||
|
*/
|
||||||
|
#define GLUT_GAME_MODE_ACTIVE 0x0000
|
||||||
|
#define GLUT_GAME_MODE_POSSIBLE 0x0001
|
||||||
|
#define GLUT_GAME_MODE_WIDTH 0x0002
|
||||||
|
#define GLUT_GAME_MODE_HEIGHT 0x0003
|
||||||
|
#define GLUT_GAME_MODE_PIXEL_DEPTH 0x0004
|
||||||
|
#define GLUT_GAME_MODE_REFRESH_RATE 0x0005
|
||||||
|
#define GLUT_GAME_MODE_DISPLAY_CHANGED 0x0006
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization functions, see fglut_init.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv );
|
||||||
|
FGAPI void FGAPIENTRY glutInitWindowPosition( int x, int y );
|
||||||
|
FGAPI void FGAPIENTRY glutInitWindowSize( int width, int height );
|
||||||
|
FGAPI void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode );
|
||||||
|
FGAPI void FGAPIENTRY glutInitDisplayString( const char* displayMode );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process loop function, see fg_main.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutMainLoop( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Window management functions, see fg_window.c
|
||||||
|
*/
|
||||||
|
FGAPI int FGAPIENTRY glutCreateWindow( const char* title );
|
||||||
|
FGAPI int FGAPIENTRY glutCreateSubWindow( int window, int x, int y, int width, int height );
|
||||||
|
FGAPI void FGAPIENTRY glutDestroyWindow( int window );
|
||||||
|
FGAPI void FGAPIENTRY glutSetWindow( int window );
|
||||||
|
FGAPI int FGAPIENTRY glutGetWindow( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSetWindowTitle( const char* title );
|
||||||
|
FGAPI void FGAPIENTRY glutSetIconTitle( const char* title );
|
||||||
|
FGAPI void FGAPIENTRY glutReshapeWindow( int width, int height );
|
||||||
|
FGAPI void FGAPIENTRY glutPositionWindow( int x, int y );
|
||||||
|
FGAPI void FGAPIENTRY glutShowWindow( void );
|
||||||
|
FGAPI void FGAPIENTRY glutHideWindow( void );
|
||||||
|
FGAPI void FGAPIENTRY glutIconifyWindow( void );
|
||||||
|
FGAPI void FGAPIENTRY glutPushWindow( void );
|
||||||
|
FGAPI void FGAPIENTRY glutPopWindow( void );
|
||||||
|
FGAPI void FGAPIENTRY glutFullScreen( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display-related functions, see fg_display.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutPostWindowRedisplay( int window );
|
||||||
|
FGAPI void FGAPIENTRY glutPostRedisplay( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSwapBuffers( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mouse cursor functions, see fg_cursor.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutWarpPointer( int x, int y );
|
||||||
|
FGAPI void FGAPIENTRY glutSetCursor( int cursor );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overlay stuff, see fg_overlay.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutEstablishOverlay( void );
|
||||||
|
FGAPI void FGAPIENTRY glutRemoveOverlay( void );
|
||||||
|
FGAPI void FGAPIENTRY glutUseLayer( GLenum layer );
|
||||||
|
FGAPI void FGAPIENTRY glutPostOverlayRedisplay( void );
|
||||||
|
FGAPI void FGAPIENTRY glutPostWindowOverlayRedisplay( int window );
|
||||||
|
FGAPI void FGAPIENTRY glutShowOverlay( void );
|
||||||
|
FGAPI void FGAPIENTRY glutHideOverlay( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Menu stuff, see fg_menu.c
|
||||||
|
*/
|
||||||
|
FGAPI int FGAPIENTRY glutCreateMenu( void (* callback)( int menu ) );
|
||||||
|
FGAPI void FGAPIENTRY glutDestroyMenu( int menu );
|
||||||
|
FGAPI int FGAPIENTRY glutGetMenu( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSetMenu( int menu );
|
||||||
|
FGAPI void FGAPIENTRY glutAddMenuEntry( const char* label, int value );
|
||||||
|
FGAPI void FGAPIENTRY glutAddSubMenu( const char* label, int subMenu );
|
||||||
|
FGAPI void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value );
|
||||||
|
FGAPI void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int value );
|
||||||
|
FGAPI void FGAPIENTRY glutRemoveMenuItem( int item );
|
||||||
|
FGAPI void FGAPIENTRY glutAttachMenu( int button );
|
||||||
|
FGAPI void FGAPIENTRY glutDetachMenu( int button );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global callback functions, see fg_callbacks.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutTimerFunc( unsigned int time, void (* callback)( int ), int value );
|
||||||
|
FGAPI void FGAPIENTRY glutIdleFunc( void (* callback)( void ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Window-specific callback functions, see fg_callbacks.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutKeyboardFunc( void (* callback)( unsigned char, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) );
|
||||||
|
FGAPI void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutEntryFunc( void (* callback)( int ) );
|
||||||
|
|
||||||
|
FGAPI void FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval );
|
||||||
|
FGAPI void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) );
|
||||||
|
FGAPI void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) );
|
||||||
|
|
||||||
|
FGAPI void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) );
|
||||||
|
FGAPI void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* State setting and retrieval functions, see fg_state.c
|
||||||
|
*/
|
||||||
|
FGAPI int FGAPIENTRY glutGet( GLenum query );
|
||||||
|
FGAPI int FGAPIENTRY glutDeviceGet( GLenum query );
|
||||||
|
FGAPI int FGAPIENTRY glutGetModifiers( void );
|
||||||
|
FGAPI int FGAPIENTRY glutLayerGet( GLenum query );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Font stuff, see fg_font.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutBitmapCharacter( void* font, int character );
|
||||||
|
FGAPI int FGAPIENTRY glutBitmapWidth( void* font, int character );
|
||||||
|
FGAPI void FGAPIENTRY glutStrokeCharacter( void* font, int character );
|
||||||
|
FGAPI int FGAPIENTRY glutStrokeWidth( void* font, int character );
|
||||||
|
FGAPI GLfloat FGAPIENTRY glutStrokeWidthf( void* font, int character ); /* GLUT 3.8 */
|
||||||
|
FGAPI int FGAPIENTRY glutBitmapLength( void* font, const unsigned char* string );
|
||||||
|
FGAPI int FGAPIENTRY glutStrokeLength( void* font, const unsigned char* string );
|
||||||
|
FGAPI GLfloat FGAPIENTRY glutStrokeLengthf( void* font, const unsigned char *string ); /* GLUT 3.8 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Geometry functions, see fg_geometry.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
FGAPI void FGAPIENTRY glutWireCube( double size );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidCube( double size );
|
||||||
|
FGAPI void FGAPIENTRY glutWireSphere( double radius, GLint slices, GLint stacks );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidSphere( double radius, GLint slices, GLint stacks );
|
||||||
|
FGAPI void FGAPIENTRY glutWireCone( double base, double height, GLint slices, GLint stacks );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidCone( double base, double height, GLint slices, GLint stacks );
|
||||||
|
FGAPI void FGAPIENTRY glutWireTorus( double innerRadius, double outerRadius, GLint sides, GLint rings );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidTorus( double innerRadius, double outerRadius, GLint sides, GLint rings );
|
||||||
|
FGAPI void FGAPIENTRY glutWireDodecahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidDodecahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutWireOctahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidOctahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutWireTetrahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidTetrahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutWireIcosahedron( void );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidIcosahedron( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Teapot rendering functions, found in fg_teapot.c
|
||||||
|
* NB: front facing polygons have clockwise winding, not counter clockwise
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutWireTeapot( double size );
|
||||||
|
FGAPI void FGAPIENTRY glutSolidTeapot( double size );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Game mode functions, see fg_gamemode.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutGameModeString( const char* string );
|
||||||
|
FGAPI int FGAPIENTRY glutEnterGameMode( void );
|
||||||
|
FGAPI void FGAPIENTRY glutLeaveGameMode( void );
|
||||||
|
FGAPI int FGAPIENTRY glutGameModeGet( GLenum query );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Video resize functions, see fg_videoresize.c
|
||||||
|
*/
|
||||||
|
FGAPI int FGAPIENTRY glutVideoResizeGet( GLenum query );
|
||||||
|
FGAPI void FGAPIENTRY glutSetupVideoResizing( void );
|
||||||
|
FGAPI void FGAPIENTRY glutStopVideoResizing( void );
|
||||||
|
FGAPI void FGAPIENTRY glutVideoResize( int x, int y, int width, int height );
|
||||||
|
FGAPI void FGAPIENTRY glutVideoPan( int x, int y, int width, int height );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Colormap functions, see fg_misc.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutSetColor( int color, GLfloat red, GLfloat green, GLfloat blue );
|
||||||
|
FGAPI GLfloat FGAPIENTRY glutGetColor( int color, int component );
|
||||||
|
FGAPI void FGAPIENTRY glutCopyColormap( int window );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Misc keyboard and joystick functions, see fg_misc.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutIgnoreKeyRepeat( int ignore );
|
||||||
|
FGAPI void FGAPIENTRY glutSetKeyRepeat( int repeatMode );
|
||||||
|
FGAPI void FGAPIENTRY glutForceJoystickFunc( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Misc functions, see fg_misc.c
|
||||||
|
*/
|
||||||
|
FGAPI int FGAPIENTRY glutExtensionSupported( const char* extension );
|
||||||
|
FGAPI void FGAPIENTRY glutReportErrors( void );
|
||||||
|
|
||||||
|
/* Comment from glut.h of classic GLUT:
|
||||||
|
|
||||||
|
Win32 has an annoying issue where there are multiple C run-time
|
||||||
|
libraries (CRTs). If the executable is linked with a different CRT
|
||||||
|
from the GLUT DLL, the GLUT DLL will not share the same CRT static
|
||||||
|
data seen by the executable. In particular, atexit callbacks registered
|
||||||
|
in the executable will not be called if GLUT calls its (different)
|
||||||
|
exit routine). GLUT is typically built with the
|
||||||
|
"/MD" option (the CRT with multithreading DLL support), but the Visual
|
||||||
|
C++ linker default is "/ML" (the single threaded CRT).
|
||||||
|
|
||||||
|
One workaround to this issue is requiring users to always link with
|
||||||
|
the same CRT as GLUT is compiled with. That requires users supply a
|
||||||
|
non-standard option. GLUT 3.7 has its own built-in workaround where
|
||||||
|
the executable's "exit" function pointer is covertly passed to GLUT.
|
||||||
|
GLUT then calls the executable's exit function pointer to ensure that
|
||||||
|
any "atexit" calls registered by the application are called if GLUT
|
||||||
|
needs to exit.
|
||||||
|
|
||||||
|
Note that the __glut*WithExit routines should NEVER be called directly.
|
||||||
|
To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */
|
||||||
|
|
||||||
|
/* to get the prototype for exit() */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__)
|
||||||
|
FGAPI void FGAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int));
|
||||||
|
FGAPI int FGAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int));
|
||||||
|
FGAPI int FGAPIENTRY __glutCreateMenuWithExit(void (* func)(int), void (__cdecl *exitfunc)(int));
|
||||||
|
#ifndef FREEGLUT_BUILDING_LIB
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define FGUNUSED __attribute__((unused))
|
||||||
|
#else
|
||||||
|
#define FGUNUSED
|
||||||
|
#endif
|
||||||
|
static void FGAPIENTRY FGUNUSED glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
|
||||||
|
#define glutInit glutInit_ATEXIT_HACK
|
||||||
|
static int FGAPIENTRY FGUNUSED glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); }
|
||||||
|
#define glutCreateWindow glutCreateWindow_ATEXIT_HACK
|
||||||
|
static int FGAPIENTRY FGUNUSED glutCreateMenu_ATEXIT_HACK(void (* func)(int)) { return __glutCreateMenuWithExit(func, exit); }
|
||||||
|
#define glutCreateMenu glutCreateMenu_ATEXIT_HACK
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*** END OF FILE ***/
|
||||||
|
|
||||||
|
#endif /* __FREEGLUT_STD_H__ */
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
#ifndef __FREEGLUT_UCALL_H__
|
||||||
|
#define __FREEGLUT_UCALL_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* freeglut_ucall.h
|
||||||
|
*
|
||||||
|
* Callbacks with user data arguments.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Menu stuff, see fg_menu.c
|
||||||
|
*/
|
||||||
|
FGAPI int FGAPIENTRY glutCreateMenuUcall( void (* callback)( int menu, void* user_data ), void* user_data );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global callback functions, see fg_callbacks.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutTimerFuncUcall( unsigned int time, void (* callback)( int, void* ), int value, void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutIdleFuncUcall( void (* callback)( void* ), void* user_data );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Window-specific callback functions, see fg_callbacks.c
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutKeyboardFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutSpecialFuncUcall( void (* callback)( int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutReshapeFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutVisibilityFuncUcall( void (* callback)( int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutDisplayFuncUcall( void (* callback)( void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutMouseFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutPassiveMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutEntryFuncUcall( void (* callback)( int, void* ), void* user_data );
|
||||||
|
|
||||||
|
FGAPI void FGAPIENTRY glutKeyboardUpFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutSpecialUpFuncUcall( void (* callback)( int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutJoystickFuncUcall( void (* callback)( unsigned int, int, int, int, void* ), int pollInterval, void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutMenuStatusFuncUcall( void (* callback)( int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutOverlayDisplayFuncUcall( void (* callback)( void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutWindowStatusFuncUcall( void (* callback)( int, void* ), void* user_data );
|
||||||
|
|
||||||
|
FGAPI void FGAPIENTRY glutSpaceballMotionFuncUcall( void (* callback)( int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutSpaceballRotateFuncUcall( void (* callback)( int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutSpaceballButtonFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutButtonBoxFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutDialsFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutTabletMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutTabletButtonFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data );
|
||||||
|
|
||||||
|
FGAPI void FGAPIENTRY glutMouseWheelFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutPositionFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutCloseFuncUcall( void (* callback)( void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutWMCloseFuncUcall( void (* callback)( void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutMenuDestroyFuncUcall( void (* callback)( void* ), void* user_data );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Multi-touch/multi-pointer extensions
|
||||||
|
*/
|
||||||
|
FGAPI void FGAPIENTRY glutMultiEntryFuncUcall( void (* callback)( int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutMultiButtonFuncUcall( void (* callback)( int, int, int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutMultiMotionFuncUcall( void (* callback)( int, int, int, void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutMultiPassiveFuncUcall( void (* callback)( int, int, int, void* ), void* user_data );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization functions, see fg_init.c
|
||||||
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
FGAPI void FGAPIENTRY glutInitErrorFuncUcall( void (* callback)( const char *fmt, va_list ap, void* user_data ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutInitWarningFuncUcall( void (* callback)( const char *fmt, va_list ap, void* user_data ), void* user_data );
|
||||||
|
|
||||||
|
/* Mobile platforms lifecycle */
|
||||||
|
FGAPI void FGAPIENTRY glutInitContextFuncUcall( void (* callback)( void* ), void* user_data );
|
||||||
|
FGAPI void FGAPIENTRY glutAppStatusFuncUcall( void (* callback)( int, void* ), void* user_data );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Continued "hack" from GLUT applied to Ucall functions.
|
||||||
|
* For more info, see bottom of freeglut_std.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* to get the prototype for exit() */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__)
|
||||||
|
FGAPI int FGAPIENTRY __glutCreateMenuUcallWithExit(void(*func)(int, void*), void(__cdecl *exitfunc)(int), void* user_data);
|
||||||
|
#ifndef FREEGLUT_BUILDING_LIB
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define FGUNUSED __attribute__((unused))
|
||||||
|
#else
|
||||||
|
#define FGUNUSED
|
||||||
|
#endif
|
||||||
|
static int FGAPIENTRY FGUNUSED glutCreateMenuUcall_ATEXIT_HACK(void(*func)(int, void*), void* user_data) { return __glutCreateMenuUcallWithExit(func, exit, user_data); }
|
||||||
|
#define glutCreateMenuUcall glutCreateMenuUcall_ATEXIT_HACK
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*** END OF FILE ***/
|
||||||
|
|
||||||
|
#endif /* __FREEGLUT_UCALL_H__ */
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef __GLUT_H__
|
||||||
|
#define __GLUT_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* glut.h
|
||||||
|
*
|
||||||
|
* The freeglut library include file
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "freeglut_std.h"
|
||||||
|
|
||||||
|
/*** END OF FILE ***/
|
||||||
|
|
||||||
|
#endif /* __GLUT_H__ */
|
|
@ -0,0 +1,7 @@
|
||||||
|
# CMake toolchain file, cf. README.mingw_cross
|
||||||
|
SET(CMAKE_SYSTEM_NAME Windows)
|
||||||
|
IF("${GNU_HOST}" STREQUAL "")
|
||||||
|
SET(GNU_HOST x86_64-w64-mingw32)
|
||||||
|
ENDIF()
|
||||||
|
SET(CMAKE_C_COMPILER ${GNU_HOST}-gcc)
|
||||||
|
SET(CMAKE_RC_COMPILER ${GNU_HOST}-windres)
|
|
@ -0,0 +1,309 @@
|
||||||
|
/* 3D view manipulation demo
|
||||||
|
* Written by John Tsiombikas <nuclear@member.fsf.org>
|
||||||
|
*
|
||||||
|
* Demonstrates how to use freeglut callbacks to manipulate a 3D view, similarly
|
||||||
|
* to how a modelling program or a model viewer would operate.
|
||||||
|
*
|
||||||
|
* Rotate: drag with the left mouse button.
|
||||||
|
* Scale: drag up/down with the right mouse button.
|
||||||
|
* Pan: drag with the middle mouse button.
|
||||||
|
*
|
||||||
|
* Press space to animate the scene and update the display continuously, press
|
||||||
|
* again to return to updating only when the view needs to change.
|
||||||
|
* Press escape or q to exit.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable: 4305 4244)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char *helpprompt[] = {"Press F1 for help", 0};
|
||||||
|
static const char *helptext[] = {
|
||||||
|
"Rotate: left mouse drag",
|
||||||
|
" Scale: right mouse drag up/down",
|
||||||
|
" Pan: middle mouse drag",
|
||||||
|
"",
|
||||||
|
"Toggle fullscreen: f",
|
||||||
|
"Toggle animation: space",
|
||||||
|
"Quit: escape",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
void idle(void);
|
||||||
|
void display(void);
|
||||||
|
void print_help(void);
|
||||||
|
void reshape(int x, int y);
|
||||||
|
void keypress(unsigned char key, int x, int y);
|
||||||
|
void skeypress(int key, int x, int y);
|
||||||
|
void mouse(int bn, int st, int x, int y);
|
||||||
|
void motion(int x, int y);
|
||||||
|
|
||||||
|
int win_width, win_height;
|
||||||
|
float cam_theta, cam_phi = 25, cam_dist = 8;
|
||||||
|
float cam_pan[3];
|
||||||
|
int mouse_x, mouse_y;
|
||||||
|
int bnstate[8];
|
||||||
|
int anim, help;
|
||||||
|
long anim_start;
|
||||||
|
long nframes;
|
||||||
|
|
||||||
|
#ifndef GL_FRAMEBUFFER_SRGB
|
||||||
|
#define GL_FRAMEBUFFER_SRGB 0x8db9
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_MULTISAMPLE
|
||||||
|
#define GL_MULTISAMPLE 0x809d
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitWindowSize(800, 600);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
|
||||||
|
glutCreateWindow("freeglut 3D view demo");
|
||||||
|
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutReshapeFunc(reshape);
|
||||||
|
glutKeyboardFunc(keypress);
|
||||||
|
glutSpecialFunc(skeypress);
|
||||||
|
glutMouseFunc(mouse);
|
||||||
|
glutMotionFunc(motion);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idle(void)
|
||||||
|
{
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void display(void)
|
||||||
|
{
|
||||||
|
long tm;
|
||||||
|
float lpos[] = {-1, 2, 3, 0};
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(0, 0, -cam_dist);
|
||||||
|
glRotatef(cam_phi, 1, 0, 0);
|
||||||
|
glRotatef(cam_theta, 0, 1, 0);
|
||||||
|
glTranslatef(cam_pan[0], cam_pan[1], cam_pan[2]);
|
||||||
|
|
||||||
|
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
if(anim) {
|
||||||
|
tm = glutGet(GLUT_ELAPSED_TIME) - anim_start;
|
||||||
|
glRotatef(tm / 10.0f, 1, 0, 0);
|
||||||
|
glRotatef(tm / 10.0f, 0, 1, 0);
|
||||||
|
}
|
||||||
|
glutSolidTorus(0.3, 1, 16, 24);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glutSolidSphere(0.4, 16, 8);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(-2.5, 0, 0);
|
||||||
|
glutSolidCube(1.5);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(2.5, -1, 0);
|
||||||
|
glRotatef(-90, 1, 0, 0);
|
||||||
|
glutSolidCone(1.1, 2, 16, 2);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(0, -0.5, 2.5);
|
||||||
|
glFrontFace(GL_CW);
|
||||||
|
glutSolidTeapot(1.0);
|
||||||
|
glFrontFace(GL_CCW);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glNormal3f(0, 1, 0);
|
||||||
|
glVertex3f(-5, -1.3, 5);
|
||||||
|
glVertex3f(5, -1.3, 5);
|
||||||
|
glVertex3f(5, -1.3, -5);
|
||||||
|
glVertex3f(-5, -1.3, -5);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
print_help();
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
nframes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_help(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char *s, **text;
|
||||||
|
|
||||||
|
glPushAttrib(GL_ENABLE_BIT);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, win_width, 0, win_height, -1, 1);
|
||||||
|
|
||||||
|
text = help ? helptext : helpprompt;
|
||||||
|
|
||||||
|
for(i=0; text[i]; i++) {
|
||||||
|
glColor3f(0, 0.1, 0);
|
||||||
|
glRasterPos2f(7, win_height - (i + 1) * 20 - 2);
|
||||||
|
s = text[i];
|
||||||
|
while(*s) {
|
||||||
|
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++);
|
||||||
|
}
|
||||||
|
glColor3f(0, 0.9, 0);
|
||||||
|
glRasterPos2f(5, win_height - (i + 1) * 20);
|
||||||
|
s = text[i];
|
||||||
|
while(*s) {
|
||||||
|
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|
||||||
|
glPopAttrib();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ZNEAR 0.5f
|
||||||
|
void reshape(int x, int y)
|
||||||
|
{
|
||||||
|
float vsz, aspect = (float)x / (float)y;
|
||||||
|
win_width = x;
|
||||||
|
win_height = y;
|
||||||
|
|
||||||
|
glViewport(0, 0, x, y);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
vsz = 0.4663f * ZNEAR;
|
||||||
|
glFrustum(-aspect * vsz, aspect * vsz, -vsz, vsz, 0.5, 500.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keypress(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
static int fullscr;
|
||||||
|
static int prev_xsz, prev_ysz;
|
||||||
|
|
||||||
|
switch(key) {
|
||||||
|
case 27:
|
||||||
|
case 'q':
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ' ':
|
||||||
|
anim ^= 1;
|
||||||
|
glutIdleFunc(anim ? idle : 0);
|
||||||
|
glutPostRedisplay();
|
||||||
|
|
||||||
|
if(anim) {
|
||||||
|
anim_start = glutGet(GLUT_ELAPSED_TIME);
|
||||||
|
nframes = 0;
|
||||||
|
} else {
|
||||||
|
long tm = glutGet(GLUT_ELAPSED_TIME) - anim_start;
|
||||||
|
long fps = (nframes * 100000) / tm;
|
||||||
|
printf("framerate: %ld.%ld fps\n", fps / 100, fps % 100);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
if(!(glutGetModifiers() & GLUT_ACTIVE_ALT)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'f':
|
||||||
|
fullscr ^= 1;
|
||||||
|
if(fullscr) {
|
||||||
|
prev_xsz = glutGet(GLUT_WINDOW_WIDTH);
|
||||||
|
prev_ysz = glutGet(GLUT_WINDOW_HEIGHT);
|
||||||
|
glutFullScreen();
|
||||||
|
} else {
|
||||||
|
glutReshapeWindow(prev_xsz, prev_ysz);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skeypress(int key, int x, int y)
|
||||||
|
{
|
||||||
|
switch(key) {
|
||||||
|
case GLUT_KEY_F1:
|
||||||
|
help ^= 1;
|
||||||
|
glutPostRedisplay();
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse(int bn, int st, int x, int y)
|
||||||
|
{
|
||||||
|
int bidx = bn - GLUT_LEFT_BUTTON;
|
||||||
|
bnstate[bidx] = st == GLUT_DOWN;
|
||||||
|
mouse_x = x;
|
||||||
|
mouse_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void motion(int x, int y)
|
||||||
|
{
|
||||||
|
int dx = x - mouse_x;
|
||||||
|
int dy = y - mouse_y;
|
||||||
|
mouse_x = x;
|
||||||
|
mouse_y = y;
|
||||||
|
|
||||||
|
if(!(dx | dy)) return;
|
||||||
|
|
||||||
|
if(bnstate[0]) {
|
||||||
|
cam_theta += dx * 0.5;
|
||||||
|
cam_phi += dy * 0.5;
|
||||||
|
if(cam_phi < -90) cam_phi = -90;
|
||||||
|
if(cam_phi > 90) cam_phi = 90;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
if(bnstate[1]) {
|
||||||
|
float up[3], right[3];
|
||||||
|
float theta = cam_theta * M_PI / 180.0f;
|
||||||
|
float phi = cam_phi * M_PI / 180.0f;
|
||||||
|
|
||||||
|
up[0] = -sin(theta) * sin(phi);
|
||||||
|
up[1] = -cos(phi);
|
||||||
|
up[2] = cos(theta) * sin(phi);
|
||||||
|
right[0] = cos(theta);
|
||||||
|
right[1] = 0;
|
||||||
|
right[2] = sin(theta);
|
||||||
|
|
||||||
|
cam_pan[0] += (right[0] * dx + up[0] * dy) * 0.01;
|
||||||
|
cam_pan[1] += up[1] * dy * 0.01;
|
||||||
|
cam_pan[2] += (right[2] * dx + up[2] * dy) * 0.01;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
if(bnstate[2]) {
|
||||||
|
cam_dist += dy * 0.1;
|
||||||
|
if(cam_dist < 0) cam_dist = 0;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,740 @@
|
||||||
|
/* CallbackMaker.c */
|
||||||
|
/*
|
||||||
|
* Program to invoke all the callbacks that "freeglut" supports
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int sequence_number = 0 ;
|
||||||
|
|
||||||
|
#define CALLBACKMAKER_N_WINDOWS 4
|
||||||
|
int windows[CALLBACKMAKER_N_WINDOWS] = {0};
|
||||||
|
|
||||||
|
/* define status vars showing whether given callback has been called for given window */
|
||||||
|
#define CALLBACK_CALLED_VAR(name) int name##_called[CALLBACKMAKER_N_WINDOWS] = {0}
|
||||||
|
#define CALLBACK_0V(name) int name##_seq[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_CALLED_VAR(name)
|
||||||
|
#define CALLBACK_1V(name,field) int name##_##field[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_0V(name)
|
||||||
|
#define CALLBACK_2V(name,field1,field2) int name##_##field2[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_1V(name,field1)
|
||||||
|
#define CALLBACK_3V(name,field1,field2,field3) int name##_##field3[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_2V(name,field1,field2)
|
||||||
|
#define CALLBACK_4V(name,field1,field2,field3,field4) int name##_##field4[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_3V(name,field1,field2,field3)
|
||||||
|
#define CALLBACK_5V(name,field1,field2,field3,field4,field5) int name##_##field5[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_4V(name,field1,field2,field3,field4)
|
||||||
|
CALLBACK_2V(reshape,width,height);
|
||||||
|
CALLBACK_2V(position,top,left);
|
||||||
|
CALLBACK_1V(visibility,vis);
|
||||||
|
CALLBACK_1V(windowStatus,state);
|
||||||
|
CALLBACK_4V(key,key,x,y,mod);
|
||||||
|
CALLBACK_4V(keyup,key,x,y,mod);
|
||||||
|
CALLBACK_4V(special,key,x,y,mod);
|
||||||
|
CALLBACK_4V(specialup,key,x,y,mod);
|
||||||
|
CALLBACK_4V(joystick,a,b,c,d);
|
||||||
|
CALLBACK_5V(mouse,button,updown,x,y,mod);
|
||||||
|
CALLBACK_5V(mousewheel,number,direction,x,y,mod);
|
||||||
|
CALLBACK_3V(motion,x,y,mod);
|
||||||
|
CALLBACK_3V(passivemotion,x,y,mod);
|
||||||
|
CALLBACK_1V(entry,state);
|
||||||
|
CALLBACK_0V(close);
|
||||||
|
/* menudestroy is registered on each menu, not a window */
|
||||||
|
int menudestroy_called = 0;
|
||||||
|
/* menustatus and menustate are global callbacks, set for all menus at the same time */
|
||||||
|
int menustatus_called = 0;
|
||||||
|
int menustate_called = 0;
|
||||||
|
|
||||||
|
#define STRING_LENGTH 10
|
||||||
|
|
||||||
|
static void
|
||||||
|
bitmapPrintf (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
static char buf[256];
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||||
|
(void) _vsnprintf (buf, sizeof(buf), fmt, args);
|
||||||
|
#else
|
||||||
|
(void) vsnprintf (buf, sizeof(buf), fmt, args);
|
||||||
|
#endif
|
||||||
|
va_end(args);
|
||||||
|
glutBitmapString ( GLUT_BITMAP_HELVETICA_12, (unsigned char*)buf ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getWindowAndIdx(int *winIdx)
|
||||||
|
{
|
||||||
|
int window = glutGetWindow();
|
||||||
|
|
||||||
|
if (winIdx)
|
||||||
|
(*winIdx) = window==windows[0] ? 0 :
|
||||||
|
window==windows[1] ? 1 :
|
||||||
|
window==windows[2] ? 2 : 3;
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Mod2Text(int mods, char *text)
|
||||||
|
{
|
||||||
|
if (mods&GLUT_ACTIVE_CTRL)
|
||||||
|
strcat(text,"CTRL");
|
||||||
|
if (mods&GLUT_ACTIVE_SHIFT)
|
||||||
|
{
|
||||||
|
if (text[0])
|
||||||
|
strcat(text,"+SHIFT");
|
||||||
|
else
|
||||||
|
strcat(text,"SHIFT");
|
||||||
|
}
|
||||||
|
if (mods&GLUT_ACTIVE_ALT)
|
||||||
|
{
|
||||||
|
if (text[0])
|
||||||
|
strcat(text,"+ALT");
|
||||||
|
else
|
||||||
|
strcat(text,"ALT");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!text[0])
|
||||||
|
strcat(text,"none");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Display(void)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
glClear ( GL_COLOR_BUFFER_BIT );
|
||||||
|
|
||||||
|
glDisable ( GL_DEPTH_TEST );
|
||||||
|
glMatrixMode ( GL_PROJECTION );
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, glutGet ( GLUT_WINDOW_WIDTH ),
|
||||||
|
0, glutGet ( GLUT_WINDOW_HEIGHT ), -1, 1 );
|
||||||
|
glMatrixMode ( GL_MODELVIEW );
|
||||||
|
glPushMatrix ();
|
||||||
|
glLoadIdentity ();
|
||||||
|
glColor3ub ( 0, 0, 0 );
|
||||||
|
glRasterPos2i ( 10, glutGet ( GLUT_WINDOW_HEIGHT ) - 20 ); /* 10pt margin above 10pt letters */
|
||||||
|
|
||||||
|
if ( entry_called[winIdx] )
|
||||||
|
{
|
||||||
|
bitmapPrintf ( "Entry %d: %d\n", entry_seq[winIdx], entry_state[winIdx] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( visibility_called[winIdx] )
|
||||||
|
{
|
||||||
|
bitmapPrintf ( "Visibility %d: %d\n", visibility_seq[winIdx], visibility_vis[winIdx] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( windowStatus_called[winIdx] )
|
||||||
|
{
|
||||||
|
bitmapPrintf ( "WindowStatus %d: %d\n", windowStatus_seq[winIdx], windowStatus_state[winIdx] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( reshape_called[winIdx] )
|
||||||
|
{
|
||||||
|
bitmapPrintf ( "Reshape %d: %d %d\n", reshape_seq[winIdx], reshape_width[winIdx], reshape_height[winIdx] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( position_called[winIdx] )
|
||||||
|
{
|
||||||
|
bitmapPrintf ( "Position %d: %d %d\n", position_seq[winIdx], position_left[winIdx], position_top[winIdx] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( key_called[winIdx] )
|
||||||
|
{
|
||||||
|
char mods[50] = {0};
|
||||||
|
Mod2Text(key_mod[winIdx],mods);
|
||||||
|
bitmapPrintf ( "Key %d: %d(%c) %d %d (mod: %s)\n", key_seq[winIdx], key_key[winIdx], key_key[winIdx], key_x[winIdx], key_y[winIdx], mods );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( keyup_called[winIdx] )
|
||||||
|
{
|
||||||
|
char mods[50] = {0};
|
||||||
|
Mod2Text(keyup_mod[winIdx],mods);
|
||||||
|
bitmapPrintf ( "Key Up %d: %d(%c) %d %d (mod: %s)\n", keyup_seq[winIdx], keyup_key[winIdx], keyup_key[winIdx], keyup_x[winIdx], keyup_y[winIdx], mods );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( special_called[winIdx] )
|
||||||
|
{
|
||||||
|
char mods[50] = {0};
|
||||||
|
Mod2Text(special_mod[winIdx],mods);
|
||||||
|
bitmapPrintf ( "Special %d: %d(%c) %d %d (mod: %s)\n", special_seq[winIdx], special_key[winIdx], special_key[winIdx], special_x[winIdx], special_y[winIdx], mods );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( specialup_called[winIdx] )
|
||||||
|
{
|
||||||
|
char mods[50] = {0};
|
||||||
|
Mod2Text(specialup_mod[winIdx],mods);
|
||||||
|
bitmapPrintf ( "Special Up %d: %d(%c) %d %d (mod: %s)\n", specialup_seq[winIdx], specialup_key[winIdx], specialup_key[winIdx], specialup_x[winIdx], specialup_y[winIdx], mods );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( joystick_called[winIdx] )
|
||||||
|
{
|
||||||
|
bitmapPrintf ( "Joystick %d: %d %d %d %d\n", joystick_seq[winIdx], joystick_a[winIdx], joystick_b[winIdx], joystick_c[winIdx], joystick_d[winIdx] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mouse_called[winIdx] )
|
||||||
|
{
|
||||||
|
char mods[50] = {0};
|
||||||
|
Mod2Text(mouse_mod[winIdx],mods);
|
||||||
|
bitmapPrintf ( "Mouse %d: %d %d %d %d (mod: %s)\n", mouse_seq[winIdx], mouse_button[winIdx], mouse_updown[winIdx], mouse_x[winIdx], mouse_y[winIdx], mods );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mousewheel_called[winIdx] )
|
||||||
|
{
|
||||||
|
char mods[50] = {0};
|
||||||
|
Mod2Text(mousewheel_mod[winIdx],mods);
|
||||||
|
bitmapPrintf ( "Mouse Wheel %d: %d %d %d %d (mod: %s)\n", mousewheel_seq[winIdx], mousewheel_number[winIdx], mousewheel_direction[winIdx], mousewheel_x[winIdx], mousewheel_y[winIdx], mods );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( motion_called[winIdx] )
|
||||||
|
{
|
||||||
|
char mods[50] = {0};
|
||||||
|
Mod2Text(motion_mod[winIdx],mods);
|
||||||
|
bitmapPrintf ( "Motion %d: %d %d (mod: %s)\n", motion_seq[winIdx], motion_x[winIdx], motion_y[winIdx], mods );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( passivemotion_called[winIdx] )
|
||||||
|
{
|
||||||
|
char mods[50] = {0};
|
||||||
|
Mod2Text(passivemotion_mod[winIdx],mods);
|
||||||
|
bitmapPrintf ( "Passive Motion %d: %d %d (mod: %s)\n", passivemotion_seq[winIdx], passivemotion_x[winIdx], passivemotion_y[winIdx], mods );
|
||||||
|
}
|
||||||
|
|
||||||
|
glMatrixMode ( GL_PROJECTION );
|
||||||
|
glPopMatrix ();
|
||||||
|
glMatrixMode ( GL_MODELVIEW );
|
||||||
|
glPopMatrix ();
|
||||||
|
glEnable ( GL_DEPTH_TEST );
|
||||||
|
|
||||||
|
printf ( "%6d Window %d Display Callback\n",
|
||||||
|
++sequence_number, window ) ;
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Warning(const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
printf("%6d Warning callback:\n",++sequence_number);
|
||||||
|
|
||||||
|
/* print warning message */
|
||||||
|
vprintf(fmt, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Error(const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char dummy_string[STRING_LENGTH];
|
||||||
|
printf("%6d Error callback:\n",++sequence_number);
|
||||||
|
|
||||||
|
/* print warning message */
|
||||||
|
vprintf(fmt, ap);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
/* terminate program, after pause for input so user can see */
|
||||||
|
printf ( "Please enter something to exit: " );
|
||||||
|
fgets ( dummy_string, STRING_LENGTH, stdin );
|
||||||
|
|
||||||
|
/* Call exit directly as freeglut is messed
|
||||||
|
* up internally when an error is called.
|
||||||
|
*/
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Reshape(int width, int height)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Reshape Callback: %d %d\n",
|
||||||
|
++sequence_number, window, width, height ) ;
|
||||||
|
reshape_called[winIdx] = 1 ;
|
||||||
|
reshape_width[winIdx] = width ;
|
||||||
|
reshape_height[winIdx] = height ;
|
||||||
|
reshape_seq[winIdx] = sequence_number ;
|
||||||
|
glViewport(0,0,width,height);
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Position(int left, int top)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Position Callback: %d %d\n",
|
||||||
|
++sequence_number, window, left, top ) ;
|
||||||
|
position_called[winIdx] = 1 ;
|
||||||
|
position_left[winIdx] = left ;
|
||||||
|
position_top[winIdx] = top ;
|
||||||
|
position_seq[winIdx] = sequence_number ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Key(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Keyboard Callback: %d %d %d\n",
|
||||||
|
++sequence_number, window, key, x, y ) ;
|
||||||
|
key_called[winIdx] = 1 ;
|
||||||
|
key_key[winIdx] = key ;
|
||||||
|
key_x[winIdx] = x ;
|
||||||
|
key_y[winIdx] = y ;
|
||||||
|
key_seq[winIdx] = sequence_number ;
|
||||||
|
key_mod[winIdx] = glutGetModifiers() ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
KeyUp(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Key Release Callback: %d %d %d\n",
|
||||||
|
++sequence_number, window, key, x, y ) ;
|
||||||
|
keyup_called[winIdx] = 1 ;
|
||||||
|
keyup_key[winIdx] = key ;
|
||||||
|
keyup_x[winIdx] = x ;
|
||||||
|
keyup_y[winIdx] = y ;
|
||||||
|
keyup_seq[winIdx] = sequence_number ;
|
||||||
|
keyup_mod[winIdx] = glutGetModifiers() ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Special(int key, int x, int y)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Special Key Callback: %d %d %d\n",
|
||||||
|
++sequence_number, window, key, x, y ) ;
|
||||||
|
special_called[winIdx] = 1 ;
|
||||||
|
special_key[winIdx] = key ;
|
||||||
|
special_x[winIdx] = x ;
|
||||||
|
special_y[winIdx] = y ;
|
||||||
|
special_seq[winIdx] = sequence_number ;
|
||||||
|
special_mod[winIdx] = glutGetModifiers() ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SpecialUp(int key, int x, int y)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Special Key Release Callback: %d %d %d\n",
|
||||||
|
++sequence_number, window, key, x, y ) ;
|
||||||
|
specialup_called[winIdx] = 1 ;
|
||||||
|
specialup_key[winIdx] = key ;
|
||||||
|
specialup_x[winIdx] = x ;
|
||||||
|
specialup_y[winIdx] = y ;
|
||||||
|
specialup_seq[winIdx] = sequence_number ;
|
||||||
|
specialup_mod[winIdx] = glutGetModifiers() ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Joystick( unsigned int a, int b, int c, int d) /* Need meaningful names */
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Joystick Callback: %d %d %d %d\n",
|
||||||
|
++sequence_number, window, a, b, c, d ) ;
|
||||||
|
joystick_called[winIdx] = 1 ;
|
||||||
|
joystick_a[winIdx] = a ;
|
||||||
|
joystick_b[winIdx] = b ;
|
||||||
|
joystick_c[winIdx] = c ;
|
||||||
|
joystick_d[winIdx] = d ;
|
||||||
|
joystick_seq[winIdx] = sequence_number ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Mouse(int button, int updown, int x, int y)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Mouse Click Callback: %d %d %d %d\n",
|
||||||
|
++sequence_number, window, button, updown, x, y ) ;
|
||||||
|
mouse_called[winIdx] = 1 ;
|
||||||
|
mouse_button[winIdx] = button ;
|
||||||
|
mouse_updown[winIdx] = updown ;
|
||||||
|
mouse_x[winIdx] = x ;
|
||||||
|
mouse_y[winIdx] = y ;
|
||||||
|
mouse_seq[winIdx] = sequence_number ;
|
||||||
|
mouse_mod[winIdx] = glutGetModifiers() ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MouseWheel(int wheel_number, int direction, int x, int y)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Mouse Wheel Callback: %d %d %d %d\n",
|
||||||
|
++sequence_number, window, wheel_number, direction, x, y ) ;
|
||||||
|
mousewheel_called[winIdx] = 1 ;
|
||||||
|
mousewheel_number[winIdx] = wheel_number ;
|
||||||
|
mousewheel_direction[winIdx] = direction ;
|
||||||
|
mousewheel_x[winIdx] = x ;
|
||||||
|
mousewheel_y[winIdx] = y ;
|
||||||
|
mousewheel_seq[winIdx] = sequence_number ;
|
||||||
|
mousewheel_mod[winIdx] = glutGetModifiers() ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Motion(int x, int y)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Mouse Motion Callback: %d %d\n",
|
||||||
|
++sequence_number, window, x, y ) ;
|
||||||
|
motion_called[winIdx] = 1 ;
|
||||||
|
motion_x[winIdx] = x ;
|
||||||
|
motion_y[winIdx] = y ;
|
||||||
|
motion_seq[winIdx] = sequence_number ;
|
||||||
|
motion_mod[winIdx] = glutGetModifiers() ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PassiveMotion(int x, int y)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Mouse Passive Motion Callback: %d %d\n",
|
||||||
|
++sequence_number, window, x, y ) ;
|
||||||
|
passivemotion_called[winIdx] = 1 ;
|
||||||
|
passivemotion_x[winIdx] = x ;
|
||||||
|
passivemotion_y[winIdx] = y ;
|
||||||
|
passivemotion_seq[winIdx] = sequence_number ;
|
||||||
|
passivemotion_mod[winIdx] = glutGetModifiers() ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Entry(int state)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Entry Callback: %d\n",
|
||||||
|
++sequence_number, window, state ) ;
|
||||||
|
entry_called[winIdx] = 1 ;
|
||||||
|
entry_seq[winIdx] = sequence_number;
|
||||||
|
entry_state[winIdx] = state;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Close(void)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d Close Callback\n",
|
||||||
|
++sequence_number, window ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
OverlayDisplay(void)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d OverlayDisplay Callback\n",
|
||||||
|
++sequence_number, window ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Visibility(int vis)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d Visibility Callback: %d\n",
|
||||||
|
++sequence_number, window, vis ) ;
|
||||||
|
visibility_called[winIdx] = 1 ;
|
||||||
|
visibility_vis[winIdx] = vis ;
|
||||||
|
visibility_seq[winIdx] = sequence_number ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
WindowStatus(int state)
|
||||||
|
{
|
||||||
|
int winIdx;
|
||||||
|
int window = getWindowAndIdx(&winIdx);
|
||||||
|
printf ( "%6d Window %d WindowStatus Callback: %d\n",
|
||||||
|
++sequence_number, window, state ) ;
|
||||||
|
windowStatus_called[winIdx] = 1 ;
|
||||||
|
windowStatus_state[winIdx] = state ;
|
||||||
|
windowStatus_seq[winIdx] = sequence_number ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SpaceMotion(int x, int y, int z)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d SpaceMotion Callback: %d %d %d\n",
|
||||||
|
++sequence_number, window, x, y, z ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SpaceRotation(int x, int y, int z)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d SpaceRotation Callback: %d %d %d\n",
|
||||||
|
++sequence_number, window, x, y, z ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SpaceButton(int button, int updown)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d SpaceButton Callback: %d %d\n",
|
||||||
|
++sequence_number, window, button, updown ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Dials(int x, int y)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d Dials Callback: %d %d\n",
|
||||||
|
++sequence_number, window, x, y ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ButtonBox(int button, int updown)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d ButtonBox Callback: %d %d\n",
|
||||||
|
++sequence_number, window, button, updown ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TabletMotion(int x, int y)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d TabletMotion Callback: %d %d\n",
|
||||||
|
++sequence_number, window, x, y ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TabletButton(int button, int updown, int x, int y)
|
||||||
|
{
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf ( "%6d Window %d TabletButton Callback: %d %d %d %d\n",
|
||||||
|
++sequence_number, window, button, updown, x, y ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MenuCallback ( int value )
|
||||||
|
{
|
||||||
|
int menu = glutGetMenu();
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
printf( "%6d Menu %d MenuCallback for menu opened in Window %d - value is %d\n",
|
||||||
|
++sequence_number, menu, window, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MenuDestroy( void )
|
||||||
|
{
|
||||||
|
int menu = glutGetMenu();
|
||||||
|
menudestroy_called = 1 ;
|
||||||
|
printf ( "%6d Menu %d MenuDestroy Callback\n",
|
||||||
|
++sequence_number, menu ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MenuStatus( int status, int x, int y )
|
||||||
|
{
|
||||||
|
/* Menu and window for which this event is triggered are current when the callback is called */
|
||||||
|
int menu = glutGetMenu();
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
menustatus_called = 1 ;
|
||||||
|
printf ( "%6d Menu %d MenuStatus Callback in Window %d: %d %d %d\n",
|
||||||
|
++sequence_number, menu, window, status, x, y ) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
MenuState( int status )
|
||||||
|
{
|
||||||
|
/* Menu and window for which this event is triggered are current when the callback is called */
|
||||||
|
int menu = glutGetMenu();
|
||||||
|
int window = getWindowAndIdx(NULL);
|
||||||
|
menustate_called = 1 ;
|
||||||
|
printf ( "%6d Menu %d MenuState Callback in Window %d: %d\n",
|
||||||
|
++sequence_number, menu, window, status) ;
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Idle ( void )
|
||||||
|
{
|
||||||
|
++sequence_number ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetWindowCallbacks( int first )
|
||||||
|
{
|
||||||
|
/* All these callbacks are set for only the current window */
|
||||||
|
glutDisplayFunc( Display );
|
||||||
|
glutReshapeFunc( Reshape );
|
||||||
|
glutPositionFunc( Position );
|
||||||
|
glutKeyboardFunc( Key );
|
||||||
|
glutSpecialFunc( Special );
|
||||||
|
glutKeyboardUpFunc( KeyUp );
|
||||||
|
glutSpecialUpFunc( SpecialUp );
|
||||||
|
if (first)
|
||||||
|
glutJoystickFunc( Joystick, 100 );
|
||||||
|
glutMouseFunc ( Mouse ) ;
|
||||||
|
glutMouseWheelFunc ( MouseWheel ) ;
|
||||||
|
glutMotionFunc ( Motion ) ;
|
||||||
|
glutPassiveMotionFunc ( PassiveMotion ) ;
|
||||||
|
glutEntryFunc ( Entry ) ;
|
||||||
|
glutCloseFunc ( Close ) ;
|
||||||
|
glutOverlayDisplayFunc ( OverlayDisplay ) ;
|
||||||
|
glutSpaceballMotionFunc ( SpaceMotion ) ;
|
||||||
|
glutSpaceballRotateFunc ( SpaceRotation ) ;
|
||||||
|
glutSpaceballButtonFunc ( SpaceButton ) ;
|
||||||
|
glutButtonBoxFunc ( ButtonBox ) ;
|
||||||
|
glutDialsFunc ( Dials ) ;
|
||||||
|
glutTabletMotionFunc ( TabletMotion ) ;
|
||||||
|
glutTabletButtonFunc ( TabletButton ) ;
|
||||||
|
/* glutVisibilityFunc is deprecated in favor of glutWindowStatusFunc, which provides more detail.
|
||||||
|
* Setting one of these overwrites the other (see docs).
|
||||||
|
*/
|
||||||
|
glutVisibilityFunc ( Visibility ); /* This will thus never be called, as glutWindowStatusFunc is set afterwards */
|
||||||
|
glutWindowStatusFunc ( WindowStatus ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char dummy_string[STRING_LENGTH];
|
||||||
|
|
||||||
|
int subMenuA, subMenuB;
|
||||||
|
|
||||||
|
glutInitWarningFunc(Warning);
|
||||||
|
glutInitErrorFunc(Error);
|
||||||
|
glutInitWindowSize(500, 250);
|
||||||
|
glutInitWindowPosition ( 140, 140 );
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE );
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
/* global setting: mainloop does not return when a window is closed, only returns when all windows are closed */
|
||||||
|
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_CONTINUE_EXECUTION);
|
||||||
|
/* global setting: repeated keys generating by keeping the key pressed down are passed on to the keyboard callback */
|
||||||
|
/* There are two functions to control this behavior, glutSetKeyRepeat to set it globally, and glutIgnoreKeyRepeat to set it per window.
|
||||||
|
* These two interact however. If key repeat is globally switched off (glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF)), it cannot be overridden
|
||||||
|
* (switched back on) for a specific window with glutIgnoreKeyRepeat. However, if key repeat is globally switched on
|
||||||
|
* (glutSetKeyRepeat(GLUT_KEY_REPEAT_ON)), it can be overridden (switched off) with glutIgnoreKeyRepeat on a per-window basis. That is
|
||||||
|
* what we demonstrate here.
|
||||||
|
*/
|
||||||
|
glutSetKeyRepeat(GLUT_KEY_REPEAT_ON);
|
||||||
|
|
||||||
|
/* Set other global callback (global as in not associated with any specific menu or window) */
|
||||||
|
glutIdleFunc ( Idle );
|
||||||
|
glutMenuStatusFunc ( MenuStatus );
|
||||||
|
glutMenuStateFunc ( MenuState ); /* Note that glutMenuStatusFunc is an enhanced version of the deprecated glutMenuStateFunc. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Open first window */
|
||||||
|
windows[0] = glutCreateWindow( "Callback Demo" );
|
||||||
|
printf ( "Creating window %d as 'Callback Demo'\n", windows[0] ) ;
|
||||||
|
|
||||||
|
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
/* callbacks, settings and menus for this window */
|
||||||
|
SetWindowCallbacks( 1 );
|
||||||
|
glutIgnoreKeyRepeat(GL_TRUE);
|
||||||
|
glutSetIconTitle("Icon Test - Callback Demo");
|
||||||
|
|
||||||
|
subMenuA = glutCreateMenu( MenuCallback );
|
||||||
|
glutAddMenuEntry( "Sub menu A1 (01)", 11 );
|
||||||
|
glutAddMenuEntry( "Sub menu A2 (02)", 12 );
|
||||||
|
glutAddMenuEntry( "Sub menu A3 (03)", 13 );
|
||||||
|
glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
|
||||||
|
/* Change font for this menu */
|
||||||
|
glutSetMenuFont(subMenuA, GLUT_BITMAP_HELVETICA_12);
|
||||||
|
|
||||||
|
subMenuB = glutCreateMenu( MenuCallback );
|
||||||
|
glutAddMenuEntry( "Sub menu B1 (04)", 14 );
|
||||||
|
glutAddMenuEntry( "Sub menu B2 (05)", 15 );
|
||||||
|
glutAddMenuEntry( "Sub menu B3 (06)", 16 );
|
||||||
|
glutAddSubMenu( "Going to sub menu A", subMenuA );
|
||||||
|
glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
|
||||||
|
glutSetMenuFont(subMenuB, GLUT_BITMAP_9_BY_15);
|
||||||
|
|
||||||
|
glutCreateMenu( MenuCallback );
|
||||||
|
glutAddMenuEntry( "Entry one", 21 );
|
||||||
|
glutAddMenuEntry( "Entry two", 22 );
|
||||||
|
glutAddMenuEntry( "Entry three", 23 );
|
||||||
|
glutAddMenuEntry( "Entry four", 24 );
|
||||||
|
glutAddMenuEntry( "Entry five", 25 );
|
||||||
|
glutAddSubMenu( "Enter sub menu A", subMenuA );
|
||||||
|
glutAddSubMenu( "Enter sub menu B", subMenuB );
|
||||||
|
glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
|
||||||
|
|
||||||
|
glutAttachMenu( GLUT_LEFT_BUTTON );
|
||||||
|
|
||||||
|
|
||||||
|
/* Position second window right next to the first */
|
||||||
|
glutInitWindowPosition ( 140+500+2*glutGet(GLUT_WINDOW_BORDER_WIDTH), 140 );
|
||||||
|
glutInitWindowSize(600, 600);
|
||||||
|
windows[1] = glutCreateWindow( "Second Window" );
|
||||||
|
printf ( "Creating window %d as 'Second Window'\n", windows[1] ) ;
|
||||||
|
|
||||||
|
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
/* callbacks, settings and menus for this window */
|
||||||
|
SetWindowCallbacks( 0 );
|
||||||
|
glutIgnoreKeyRepeat(GL_TRUE);
|
||||||
|
|
||||||
|
glutSetMenu(subMenuB);
|
||||||
|
glutAttachMenu( GLUT_RIGHT_BUTTON );
|
||||||
|
|
||||||
|
|
||||||
|
/* position a third window as a subwindow of the second */
|
||||||
|
windows[2] = glutCreateSubWindow(windows[1],0,300,600,300);
|
||||||
|
printf ( "Creating window %d as subwindow to 'Second Window'\n", windows[2] ) ;
|
||||||
|
|
||||||
|
glClearColor(0.7f, 0.7f, 0.7f, 1.0);
|
||||||
|
|
||||||
|
/* callbacks, settings and menus for this window */
|
||||||
|
SetWindowCallbacks( 0 );
|
||||||
|
glutSetCursor(GLUT_CURSOR_CROSSHAIR); /* Cursors are per window */
|
||||||
|
|
||||||
|
glutSetMenu(subMenuA);
|
||||||
|
glutAttachMenu( GLUT_RIGHT_BUTTON );
|
||||||
|
|
||||||
|
|
||||||
|
/* position a fourth window as a subsubwindow (grandchild) of the second */
|
||||||
|
windows[3] = glutCreateSubWindow(windows[2],300,0,300,300);
|
||||||
|
printf ( "Creating window %d as subsubwindow to 'Second Window'\n", windows[3] ) ;
|
||||||
|
|
||||||
|
glClearColor(0.4f, 0.4f, 0.4f, 1.0);
|
||||||
|
|
||||||
|
/* callbacks and menus for this window */
|
||||||
|
SetWindowCallbacks( 0 );
|
||||||
|
glutSetCursor(GLUT_CURSOR_INHERIT); /* Inherit cursor look from parent (this is default on window creation) - comment the below to see in action */
|
||||||
|
glutSetCursor(GLUT_CURSOR_CYCLE);
|
||||||
|
|
||||||
|
|
||||||
|
printf ( "Please enter something to continue: " );
|
||||||
|
fgets ( dummy_string, STRING_LENGTH, stdin );
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
|
||||||
|
printf ( "Back from the 'freeglut' main loop\n" ) ;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,342 @@
|
||||||
|
/* fractals.c */
|
||||||
|
/*
|
||||||
|
* Program to draw a fractal by Michael Barnsley's deterministic algorithm.
|
||||||
|
* Algorithm:
|
||||||
|
* (1) Define the affine transformations (of the form r(i+1) = A r(i) + b )
|
||||||
|
* (2) Find the stationary point for each transformation
|
||||||
|
* (3) To draw:
|
||||||
|
* - If you are at the lowest level, draw lines connecting all the stationary points
|
||||||
|
* - If not, call the draw function recursively with each affine transformation applied
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* User Commands:
|
||||||
|
* +,- - increment/decrement number of levels
|
||||||
|
* PgUp, PgDn - increase/decrease scaling
|
||||||
|
* Arrow keys - translate viewing section
|
||||||
|
* r - reset view
|
||||||
|
* Escape - quit
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#define FGH_PI 3.14159265358979323846
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double a00, a01, a10, a11 ; /* Transformation matrix */
|
||||||
|
double b0, b1 ; /* Constant vector added on */
|
||||||
|
double statx, staty ; /* Coordinates of the stationary point */
|
||||||
|
}
|
||||||
|
AffineTrans ;
|
||||||
|
|
||||||
|
/* Number of levels to draw the fractal */
|
||||||
|
static int num_levels = 4 ;
|
||||||
|
|
||||||
|
/* The definition of the fractal */
|
||||||
|
static int num_trans ;
|
||||||
|
static AffineTrans *affine ;
|
||||||
|
|
||||||
|
/* Flag telling us to keep executing the main loop */
|
||||||
|
static int continue_in_main_loop = 1;
|
||||||
|
|
||||||
|
/* the window title */
|
||||||
|
char window_title [ 80 ] ;
|
||||||
|
|
||||||
|
/* The amount the view is translated and scaled */
|
||||||
|
double xwin = 0.0, ywin = 0.0 ;
|
||||||
|
double scale_factor = 1.0 ;
|
||||||
|
|
||||||
|
static void draw_level ( int num, double m00, double m01, double m10, double m11, double n0, double n1 )
|
||||||
|
{
|
||||||
|
/* Draw a fractal transformed by "M", "N" as passed in */
|
||||||
|
int i ;
|
||||||
|
|
||||||
|
if ( num == 0 )
|
||||||
|
{
|
||||||
|
double x0 = m00 * affine[0].statx + m01 * affine[0].staty + n0 ;
|
||||||
|
double y0 = m10 * affine[0].statx + m11 * affine[0].staty + n1 ;
|
||||||
|
|
||||||
|
for ( i = 1; i < num_trans; i++ )
|
||||||
|
{
|
||||||
|
double x1 = m00 * affine[i].statx + m01 * affine[i].staty + n0 ;
|
||||||
|
double y1 = m10 * affine[i].statx + m11 * affine[i].staty + n1 ;
|
||||||
|
|
||||||
|
glVertex2d ( x0, y0 ) ;
|
||||||
|
glVertex2d ( x1, y1 ) ;
|
||||||
|
|
||||||
|
x0 = x1 ;
|
||||||
|
y0 = y1 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Map each affine transformation in the fractal through the one passed in and call "draw_level" */
|
||||||
|
|
||||||
|
for ( i = 0; i < num_trans; i++ )
|
||||||
|
{
|
||||||
|
draw_level ( num-1, m00*affine[i].a00+m01*affine[i].a10, m00*affine[i].a01+m01*affine[i].a11,
|
||||||
|
m10*affine[i].a00+m11*affine[i].a10, m10*affine[i].a01+m11*affine[i].a11,
|
||||||
|
m00*affine[i].b0 +m01*affine[i].b1 + n0, m10*affine[i].b0 +m11*affine[i].b1 + n1 ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Display(void)
|
||||||
|
{
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
|
||||||
|
/* the curve */
|
||||||
|
glPushMatrix();
|
||||||
|
glScalef(2.5, 2.5, 2.5);
|
||||||
|
|
||||||
|
glColor4f(0.0, 0.0, 0.0, 1.0);
|
||||||
|
glBegin ( GL_LINES ) ;
|
||||||
|
draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 );
|
||||||
|
glEnd () ;
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Reshape(int width, int height)
|
||||||
|
{
|
||||||
|
float ar;
|
||||||
|
glViewport ( 0, 0, width, height ) ;
|
||||||
|
glMatrixMode ( GL_PROJECTION ) ;
|
||||||
|
glLoadIdentity();
|
||||||
|
ar = (float) width / (float) height ;
|
||||||
|
if( ar > 1 )
|
||||||
|
glFrustum ( -ar, ar, -1.0, 1.0, 2.0, 100.0 ) ;
|
||||||
|
else
|
||||||
|
glFrustum ( -1.0, 1.0, -1/ar, 1/ar, 2.0, 100.0 );
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
glLoadIdentity () ;
|
||||||
|
xwin = -1.0 ;
|
||||||
|
ywin = 0.0 ;
|
||||||
|
glTranslated ( xwin, ywin, -5.0 ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Key(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
int need_redisplay = 1;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case 27: /* Escape key */
|
||||||
|
continue_in_main_loop = 0 ;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '+' :
|
||||||
|
++num_levels ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case '-' :
|
||||||
|
if ( num_levels > 0 )
|
||||||
|
--num_levels ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 'r' : case 'R' :
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
glLoadIdentity();
|
||||||
|
xwin = -1.0 ;
|
||||||
|
ywin = 0.0 ;
|
||||||
|
glTranslated ( xwin, ywin, -5.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
default:
|
||||||
|
need_redisplay = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (need_redisplay)
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Special(int key, int x, int y)
|
||||||
|
{
|
||||||
|
int need_redisplay = 1;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case GLUT_KEY_UP :
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
ywin += 0.1 * scale_factor ;
|
||||||
|
glTranslated ( 0.0, 0.1 * scale_factor, 0.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_DOWN :
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
ywin -= 0.1 * scale_factor ;
|
||||||
|
glTranslated ( 0.0, -0.1 * scale_factor, 0.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_LEFT :
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
xwin -= 0.1 * scale_factor ;
|
||||||
|
glTranslated ( -0.1 * scale_factor, 0.0, 0.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_RIGHT :
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
xwin += 0.1 * scale_factor ;
|
||||||
|
glTranslated ( 0.1 * scale_factor, 0.0, 0.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_PAGE_UP :
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
glTranslated ( -xwin, -ywin, 0.0 ) ;
|
||||||
|
glScaled ( 1.25, 1.25, 1.25 ) ;
|
||||||
|
glTranslated ( xwin, ywin, 0.0 ) ;
|
||||||
|
scale_factor *= 0.8 ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_PAGE_DOWN :
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
glTranslated ( -xwin, -ywin, 0.0 ) ;
|
||||||
|
glScaled ( 0.8, 0.8, 0.8 ) ;
|
||||||
|
glTranslated ( xwin, ywin, 0.0 ) ;
|
||||||
|
scale_factor *= 1.25 ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
default:
|
||||||
|
need_redisplay = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (need_redisplay)
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
checkedFGets ( char *s, int size, FILE *stream )
|
||||||
|
{
|
||||||
|
if ( fgets ( s, size, stream ) == NULL ) {
|
||||||
|
fprintf ( stderr, "fgets failed\n");
|
||||||
|
exit ( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void readConfigFile ( char *fnme )
|
||||||
|
{
|
||||||
|
FILE *fptr = fopen ( fnme, "rt" ) ;
|
||||||
|
int i ;
|
||||||
|
char inputline [ 256 ] ;
|
||||||
|
|
||||||
|
if ( fptr )
|
||||||
|
{
|
||||||
|
/* Read a header line */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
|
||||||
|
/* Read a comment line */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
|
||||||
|
/* Read the window title */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
/* We assume here that this line will not exceed 79 characters plus a
|
||||||
|
newline (window_title is 80 characters long). That'll cause a buffer
|
||||||
|
overflow. For a simple program like this, though, we're letting it
|
||||||
|
slide!
|
||||||
|
*/
|
||||||
|
sscanf ( inputline, "%[a-zA-Z0-9!@#$%^&*()+=/\\_-\" ]", window_title ) ;
|
||||||
|
|
||||||
|
/* Read a comment line */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
|
||||||
|
/* Read the number of affine transformations */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
sscanf ( inputline, "%d", &num_trans ) ;
|
||||||
|
|
||||||
|
affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ;
|
||||||
|
|
||||||
|
/* Read a comment line */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
|
||||||
|
for ( i = 0; i < num_trans; i++ )
|
||||||
|
{
|
||||||
|
/* Read an affine transformation definition */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
sscanf ( inputline, "%lf %lf %lf %lf %lf %lf", &affine[i].a00, &affine[i].a01,
|
||||||
|
&affine[i].a10, &affine[i].a11, &affine[i].b0, &affine[i].b1 ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* No data file, set a default */
|
||||||
|
{
|
||||||
|
printf ( "ERROR opening file <%s>\n", fnme ) ;
|
||||||
|
strcpy ( window_title, "Koch Snowflake" ) ;
|
||||||
|
num_trans = 4 ;
|
||||||
|
affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ;
|
||||||
|
affine[0].a00 = 1/3. ; affine[0].a01 = 0.00 ; affine[0].a10 = 0.00 ; affine[0].a11 = 1/3. ;
|
||||||
|
affine[0].b0 = 0.0 ; affine[0].b1 = 0.0 ;
|
||||||
|
|
||||||
|
affine[1].a00 = 1/6. ; affine[1].a01 = -1/3.*sin(FGH_PI/3.) ; affine[1].a10 = 1/3.*sin(FGH_PI/3.) ; affine[1].a11 = 1/6. ;
|
||||||
|
affine[1].b0 = 1/3. ; affine[1].b1 = 0.0 ;
|
||||||
|
|
||||||
|
affine[2].a00 = 1/6. ; affine[2].a01 = -1/3.*sin(-FGH_PI/3.) ; affine[2].a10 = 1/3.*sin(-FGH_PI/3.) ; affine[2].a11 = 1/6. ;
|
||||||
|
affine[2].b0 = 0.5 ; affine[2].b1 = sqrt(3)/6. ;
|
||||||
|
|
||||||
|
affine[3].a00 = 1/3. ; affine[3].a01 = 0.00 ; affine[3].a10 = 0.00 ; affine[3].a11 = 1/3. ;
|
||||||
|
affine[3].b0 = 2/3. ; affine[3].b1 = 0.0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; i < num_trans; i++ )
|
||||||
|
{
|
||||||
|
double m00, m01, m10, m11 ; /* Matrix "I" minus "A" */
|
||||||
|
double determ ; /* Determinant of this matrix */
|
||||||
|
|
||||||
|
/* Calculate the stationary point */
|
||||||
|
|
||||||
|
m00 = 1.0 - affine[i].a00 ;
|
||||||
|
m01 = - affine[i].a01 ;
|
||||||
|
m10 = - affine[i].a10 ;
|
||||||
|
m11 = 1.0 - affine[i].a11 ;
|
||||||
|
|
||||||
|
determ = m00 * m11 - m01 * m10 ;
|
||||||
|
|
||||||
|
if ( fabs ( determ ) > 1.e-6 )
|
||||||
|
{
|
||||||
|
affine[i].statx = ( m11 * affine[i].b0 - m01 * affine[i].b1 ) / determ ;
|
||||||
|
affine[i].staty = ( -m10 * affine[i].b0 + m00 * affine[i].b1 ) / determ ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
affine[i].statx = affine[i].staty = 0.0 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
glutInitWindowSize(500, 250);
|
||||||
|
glutInitWindowPosition ( 140, 140 );
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE );
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
|
||||||
|
if ( argc > 1 )
|
||||||
|
readConfigFile ( argv[1] ) ;
|
||||||
|
else
|
||||||
|
readConfigFile ( "fractals.dat" ) ;
|
||||||
|
|
||||||
|
glutCreateWindow( window_title );
|
||||||
|
|
||||||
|
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
glutReshapeFunc(Reshape);
|
||||||
|
glutKeyboardFunc(Key);
|
||||||
|
glutSpecialFunc(Special);
|
||||||
|
glutDisplayFunc(Display);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while ( continue_in_main_loop )
|
||||||
|
glutMainLoopEvent();
|
||||||
|
|
||||||
|
printf ( "Back from the 'freeglut' main loop\n" ) ;
|
||||||
|
|
||||||
|
return 0; /* ANSI C requires main to return int. */
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
Koch Snowflake Fractal
|
||||||
|
Title of window
|
||||||
|
"Koch Snowflake"
|
||||||
|
Number of transformations
|
||||||
|
4
|
||||||
|
A00 A01 A10 A11 B0 B1
|
||||||
|
0.33333 0.0 0.0 0.33333 0.0 0.0
|
||||||
|
0.16667 -.28868 0.28868 0.16667 0.33333 0.0
|
||||||
|
0.16667 0.28868 -.28868 0.16667 0.5 0.28868
|
||||||
|
0.33333 0.0 0.0 0.33333 0.66667 0.0
|
|
@ -0,0 +1,10 @@
|
||||||
|
Koch Snowflake Fractal
|
||||||
|
Title of window
|
||||||
|
"Koch Snowflake"
|
||||||
|
Number of transformations
|
||||||
|
4
|
||||||
|
A00 A01 A10 A11 B0 B1
|
||||||
|
0.33333 0.0 0.0 0.33333 0.0 0.0
|
||||||
|
0.16667 -.28868 0.28868 0.16667 0.33333 0.0
|
||||||
|
0.16667 0.28868 -.28868 0.16667 0.5 0.28868
|
||||||
|
0.33333 0.0 0.0 0.33333 0.66667 0.0
|
|
@ -0,0 +1,393 @@
|
||||||
|
/* fractals_random.c */
|
||||||
|
/* This demo shows a single-buffering "freeglut" example. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Program to draw a fractal by Michael Barnsley's stochastic algorithm.
|
||||||
|
* Algorithm:
|
||||||
|
* (1) Define the affine transformations (of the form r(i+1) = A r(i) + b )
|
||||||
|
* (2) Find the stationary point for the first transformation
|
||||||
|
* (3) To draw:
|
||||||
|
* - Pick a random integer between 1 and the number of transformations (inclusive)
|
||||||
|
* - Send the current point through the transformation to create the new current point
|
||||||
|
* - Plot the new current point
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* User Commands:
|
||||||
|
* PgUp, PgDn - increase/decrease scaling
|
||||||
|
* Arrow keys - translate viewing section
|
||||||
|
* r - reset view
|
||||||
|
* Escape - quit
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#define FGH_PI 3.14159265358979323846
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAKS */
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double a00, a01, a10, a11 ; /* Transformation matrix */
|
||||||
|
double b0, b1 ; /* Constant vector added on */
|
||||||
|
double statx, staty ; /* Coordinates of the stationary point */
|
||||||
|
}
|
||||||
|
AffineTrans ;
|
||||||
|
|
||||||
|
/* Number of levels to draw the fractal */
|
||||||
|
static int num_levels = 0 ;
|
||||||
|
|
||||||
|
/* The definition of the fractal */
|
||||||
|
static int num_trans ;
|
||||||
|
static AffineTrans *affine ;
|
||||||
|
|
||||||
|
/* the window title */
|
||||||
|
char window_title [ 80 ] ;
|
||||||
|
|
||||||
|
/* The amount the view is translated */
|
||||||
|
double xwin = 0.0, ywin = 0.0 ;
|
||||||
|
double scale_factor = 1.0 ;
|
||||||
|
|
||||||
|
/* The current point */
|
||||||
|
double current_x = 0.0, current_y = 0.0 ;
|
||||||
|
|
||||||
|
/* Signals when a glClear is needed */
|
||||||
|
static GLboolean needClear = GL_TRUE;
|
||||||
|
|
||||||
|
static void draw_level ( int num, double m00, double m01, double m10, double m11, double n0, double n1 )
|
||||||
|
{
|
||||||
|
/* Draw a fractal transformed by "M", "N" as passed in */
|
||||||
|
int i ;
|
||||||
|
|
||||||
|
for ( i = 0; i < 10; i++ )
|
||||||
|
{
|
||||||
|
int random = ( rand( ) >> 10 ) % num_trans;
|
||||||
|
double new_x = affine[random].a00 * current_x + affine[random].a01 * current_y + affine[random].b0 ;
|
||||||
|
double new_y = affine[random].a10 * current_x + affine[random].a11 * current_y + affine[random].b1 ;
|
||||||
|
|
||||||
|
glVertex2d ( new_x, new_y ) ;
|
||||||
|
current_x = new_x ;
|
||||||
|
current_y = new_y ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Display(void)
|
||||||
|
{
|
||||||
|
if (needClear) {
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
needClear = GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the curve */
|
||||||
|
glPushMatrix();
|
||||||
|
glScaled(2.5, 2.5, 2.5);
|
||||||
|
|
||||||
|
glColor4f(0.0, 0.0, 0.0, 1.0);
|
||||||
|
glBegin ( GL_POINTS ) ;
|
||||||
|
draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 );
|
||||||
|
glEnd () ;
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glFlush();
|
||||||
|
glutPostRedisplay(); /* Needed so that this function will be called again */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Reshape(int width, int height)
|
||||||
|
{
|
||||||
|
float ar;
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
ar = (float) width / (float) height;
|
||||||
|
if( ar > 1 )
|
||||||
|
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
|
||||||
|
else
|
||||||
|
glFrustum(-1.0, 1.0, -1/ar, 1/ar, 2.0, 100.0);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
xwin = -1.0 ;
|
||||||
|
ywin = 0.0 ;
|
||||||
|
glTranslated(xwin, ywin, -5.0);
|
||||||
|
needClear = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Key(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
int changed_settings = 1;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case 27: /* Escape key */
|
||||||
|
glutLeaveMainLoop ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r' : case 'R' :
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
xwin = -1.0 ;
|
||||||
|
ywin = 0.0 ;
|
||||||
|
glTranslated(xwin, ywin, -5.0);
|
||||||
|
break ;
|
||||||
|
|
||||||
|
default:
|
||||||
|
changed_settings = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (changed_settings)
|
||||||
|
needClear = GL_TRUE;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Special(int key, int x, int y)
|
||||||
|
{
|
||||||
|
int changed_settings = 1;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case GLUT_KEY_UP :
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
ywin += 0.1 * scale_factor ;
|
||||||
|
glTranslated(0.0, 0.1 * scale_factor, 0.0);
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_DOWN :
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
ywin -= 0.1 * scale_factor ;
|
||||||
|
glTranslated(0.0, -0.1 * scale_factor, 0.0);
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_LEFT :
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
xwin -= 0.1 * scale_factor ;
|
||||||
|
glTranslated(-0.1 * scale_factor, 0.0, 0.0);
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_RIGHT :
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
xwin += 0.1 * scale_factor ;
|
||||||
|
glTranslated(0.1 * scale_factor, 0.0, 0.0);
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_PAGE_UP :
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glTranslated ( -xwin, -ywin, 0.0 ) ;
|
||||||
|
glScaled(1.25, 1.25, 1.25);
|
||||||
|
glTranslated ( xwin, ywin, 0.0 ) ;
|
||||||
|
scale_factor *= 0.8 ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_PAGE_DOWN :
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glTranslated ( -xwin, -ywin, 0.0 ) ;
|
||||||
|
glScaled(0.8, 0.8, 0.8);
|
||||||
|
glTranslated ( xwin, ywin, 0.0 ) ;
|
||||||
|
scale_factor *= 1.25 ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
default:
|
||||||
|
changed_settings = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (changed_settings)
|
||||||
|
needClear = GL_TRUE;
|
||||||
|
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int mouse_x = 0, mouse_y = 0 ;
|
||||||
|
static int button_down = GLUT_DOWN ;
|
||||||
|
|
||||||
|
static void
|
||||||
|
Mouse ( int button, int updown, int x, int y )
|
||||||
|
{
|
||||||
|
button_down = updown ;
|
||||||
|
|
||||||
|
if ( updown == GLUT_DOWN )
|
||||||
|
{
|
||||||
|
mouse_x = x ;
|
||||||
|
mouse_y = y ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MouseMotion ( int x, int y )
|
||||||
|
{
|
||||||
|
int window_width = glutGet ( GLUT_WINDOW_WIDTH ) ;
|
||||||
|
int window_height = glutGet ( GLUT_WINDOW_HEIGHT ) ;
|
||||||
|
int window_size = ( window_width < window_height ) ? window_width : window_height ;
|
||||||
|
|
||||||
|
double delta_x = 5.0 * (double)(x - mouse_x) / (double)(window_size) ;
|
||||||
|
double delta_y = 5.0 * (double)(y - mouse_y) / (double)(window_size) ;
|
||||||
|
|
||||||
|
xwin += delta_x * scale_factor ;
|
||||||
|
ywin -= delta_y * scale_factor ;
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
glTranslated ( delta_x * scale_factor, -delta_y * scale_factor, 0.0 ) ;
|
||||||
|
|
||||||
|
needClear = GL_TRUE;
|
||||||
|
glutPostRedisplay();
|
||||||
|
|
||||||
|
mouse_x = x ;
|
||||||
|
mouse_y = y ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MouseWheel ( int wheel_number, int direction, int x, int y )
|
||||||
|
{
|
||||||
|
double scale = ( direction > 0 ) ? 1.25 : 0.8 ;
|
||||||
|
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
glTranslated ( -xwin, -ywin, 0.0 ) ;
|
||||||
|
glScaled ( scale, scale, scale ) ;
|
||||||
|
glTranslated ( xwin, ywin, 0.0 ) ;
|
||||||
|
scale_factor /= scale ;
|
||||||
|
|
||||||
|
needClear = GL_TRUE;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
checkedFGets ( char *s, int size, FILE *stream )
|
||||||
|
{
|
||||||
|
if ( fgets ( s, size, stream ) == NULL ) {
|
||||||
|
fprintf ( stderr, "fgets failed\n");
|
||||||
|
exit ( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void readConfigFile ( char *fnme )
|
||||||
|
{
|
||||||
|
FILE *fptr = fopen ( fnme, "rt" ) ;
|
||||||
|
int i ;
|
||||||
|
char inputline [ 256 ] ;
|
||||||
|
|
||||||
|
if ( fptr )
|
||||||
|
{
|
||||||
|
/* Read a header line */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
|
||||||
|
/* Read a comment line */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
|
||||||
|
/* Read the window title */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
/* We assume here that this line will not exceed 79 characters plus a
|
||||||
|
newline (window_title is 80 characters long). That'll cause a buffer
|
||||||
|
overflow. For a simple program like this, though, we're letting it
|
||||||
|
slide!
|
||||||
|
*/
|
||||||
|
sscanf ( inputline, "%[a-zA-Z0-9!@#$%^&*()+=/\\_-\" ]", window_title ) ;
|
||||||
|
|
||||||
|
/* Read a comment line */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
|
||||||
|
/* Read the number of affine transformations */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
sscanf ( inputline, "%d", &num_trans ) ;
|
||||||
|
|
||||||
|
affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ;
|
||||||
|
|
||||||
|
/* Read a comment line */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
|
||||||
|
for ( i = 0; i < num_trans; i++ )
|
||||||
|
{
|
||||||
|
/* Read an affine transformation definition */
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), fptr ) ;
|
||||||
|
sscanf ( inputline, "%lf %lf %lf %lf %lf %lf", &affine[i].a00, &affine[i].a01,
|
||||||
|
&affine[i].a10, &affine[i].a11, &affine[i].b0, &affine[i].b1 ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* No data file, set a default */
|
||||||
|
{
|
||||||
|
printf ( "ERROR opening file <%s>\n", fnme ) ;
|
||||||
|
strcpy ( window_title, "Koch Snowflake" ) ;
|
||||||
|
num_trans = 4 ;
|
||||||
|
affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ;
|
||||||
|
affine[0].a00 = 1/3. ; affine[0].a01 = 0.00 ; affine[0].a10 = 0.00 ; affine[0].a11 = 1/3. ;
|
||||||
|
affine[0].b0 = 0.0 ; affine[0].b1 = 0.0 ;
|
||||||
|
|
||||||
|
affine[1].a00 = 1/6. ; affine[1].a01 = -1/3.*sin(FGH_PI/3.) ; affine[1].a10 = 1/3.*sin(FGH_PI/3.) ; affine[1].a11 = 1/6. ;
|
||||||
|
affine[1].b0 = 1/3. ; affine[1].b1 = 0.0 ;
|
||||||
|
|
||||||
|
affine[2].a00 = 1/6. ; affine[2].a01 = -1/3.*sin(-FGH_PI/3.) ; affine[2].a10 = 1/3.*sin(-FGH_PI/3.) ; affine[2].a11 = 1/6. ;
|
||||||
|
affine[2].b0 = 0.5 ; affine[2].b1 = sqrt(3)/6. ;
|
||||||
|
|
||||||
|
affine[3].a00 = 1/3. ; affine[3].a01 = 0.00 ; affine[3].a10 = 0.00 ; affine[3].a11 = 1/3. ;
|
||||||
|
affine[3].b0 = 2/3. ; affine[3].b1 = 0.0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; i < num_trans; i++ )
|
||||||
|
{
|
||||||
|
double m00, m01, m10, m11 ; /* Matrix "I" minus "A" */
|
||||||
|
double determ ; /* Determinant of this matrix */
|
||||||
|
|
||||||
|
/* Calculate the stationary point */
|
||||||
|
|
||||||
|
m00 = 1.0 - affine[i].a00 ;
|
||||||
|
m01 = - affine[i].a01 ;
|
||||||
|
m10 = - affine[i].a10 ;
|
||||||
|
m11 = 1.0 - affine[i].a11 ;
|
||||||
|
|
||||||
|
determ = m00 * m11 - m01 * m10 ;
|
||||||
|
|
||||||
|
if ( fabs ( determ ) > 1.e-6 )
|
||||||
|
{
|
||||||
|
affine[i].statx = ( m11 * affine[i].b0 - m01 * affine[i].b1 ) / determ ;
|
||||||
|
affine[i].staty = ( -m10 * affine[i].b0 + m00 * affine[i].b1 ) / determ ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
affine[i].statx = affine[i].staty = 0.0 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE );
|
||||||
|
|
||||||
|
glutInitWindowSize(500, 250);
|
||||||
|
glutInitWindowPosition ( 140, 140 ) ;
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
|
||||||
|
if ( argc > 1 )
|
||||||
|
readConfigFile ( argv[1] ) ;
|
||||||
|
else
|
||||||
|
readConfigFile ( "fractals.dat" ) ;
|
||||||
|
|
||||||
|
glutCreateWindow( window_title );
|
||||||
|
|
||||||
|
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
glutReshapeFunc(Reshape);
|
||||||
|
glutKeyboardFunc(Key);
|
||||||
|
glutSpecialFunc(Special);
|
||||||
|
glutDisplayFunc(Display);
|
||||||
|
glutMouseFunc(Mouse);
|
||||||
|
glutMotionFunc(MouseMotion);
|
||||||
|
glutMouseWheelFunc(MouseWheel);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
|
||||||
|
printf ( "Back from the 'freeglut' main loop\n" ) ;
|
||||||
|
|
||||||
|
free ( affine ) ;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAK INFORMATION */
|
||||||
|
_CrtDumpMemoryLeaks () ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0; /* ANSI C requires main to return int. */
|
||||||
|
}
|
|
@ -0,0 +1,378 @@
|
||||||
|
/*
|
||||||
|
* Lorenz Strange Attractor
|
||||||
|
*
|
||||||
|
* Written by John F. Fay in honor of the "freeglut" 2.0.0 release in July 2003
|
||||||
|
*
|
||||||
|
* What it does:
|
||||||
|
* This program starts with two particles right next to each other. The particles
|
||||||
|
* move through a three-dimensional phase space governed by the following equations:
|
||||||
|
* dx/dt = sigma * ( y - x )
|
||||||
|
* dy/dt = r * x - y + x * z
|
||||||
|
* dz/dt = x * y + b * z
|
||||||
|
* These are the Lorenz equations and define the "Lorenz Attractor." Any two particles
|
||||||
|
* arbitrarily close together will move apart as time increases, but their tracks are
|
||||||
|
* confined within a region of the space.
|
||||||
|
*
|
||||||
|
* Commands:
|
||||||
|
* Arrow keys: Rotate the view
|
||||||
|
* PgUp, PgDn: Zoom in and out
|
||||||
|
* Mouse click: Center on the nearest point on a particle trajectory
|
||||||
|
*
|
||||||
|
* 'r'/'R': Reset the simulation
|
||||||
|
* 'm'/'M': Modify the Lorenz parameters (in the text window)
|
||||||
|
* 's'/'S': Stop (the advancement in time)
|
||||||
|
* 'g'/'G': Go
|
||||||
|
* <spacebar>: Single-step
|
||||||
|
* <Escape>: Quit
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include Files */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAKS */
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/************************************** Defined Constants ***************************************/
|
||||||
|
/* Number of points to draw in the curves */
|
||||||
|
#define NUM_POINTS 512
|
||||||
|
|
||||||
|
/* Angle to rotate when the user presses an arrow key */
|
||||||
|
#define ROTATION_ANGLE 5.0
|
||||||
|
|
||||||
|
/* Amount to scale bu when the user presses PgUp or PgDn */
|
||||||
|
#define SCALE_FACTOR 0.8
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************** Global Variables ***************************************/
|
||||||
|
/* Lorenz Attractor variables */
|
||||||
|
double s0 = 10.0, r0 = 28.0, b0 = 8.0/3.0 ; /* Default Lorenz attactor parameters */
|
||||||
|
double time_step = 0.03 ; /* Time step in the simulation */
|
||||||
|
double sigma = 10.0, r = 28.0, b = 8.0/3.0 ; /* Lorenz attactor parameters */
|
||||||
|
double red_position[NUM_POINTS][3] ; /* Path of the red point */
|
||||||
|
double grn_position[NUM_POINTS][3] ; /* Path of the green point */
|
||||||
|
int array_index ; /* Position in *_position arrays of most recent point */
|
||||||
|
double distance = 0.0 ; /* Distance between the two points */
|
||||||
|
|
||||||
|
/* GLUT variables */
|
||||||
|
double yaw = 0.0, pit = 0.0 ; /* Euler angles of the viewing rotation */
|
||||||
|
double scale = 1.0 ; /* Scale factor */
|
||||||
|
double xcen = 0.0, ycen = 0.0, zcen = 0.0 ; /* Coordinates of the point looked at */
|
||||||
|
|
||||||
|
int animate = 1 ; /* 0 - stop, 1 = go, 2 = single-step */
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************* Functions ******************************************/
|
||||||
|
|
||||||
|
/* The Lorenz Attractor */
|
||||||
|
void calc_deriv ( double position[3], double deriv[3] )
|
||||||
|
{
|
||||||
|
/* Calculate the Lorenz attractor derivatives */
|
||||||
|
deriv[0] = sigma * ( position[1] - position[0] ) ;
|
||||||
|
deriv[1] = ( r + position[2] ) * position[0] - position[1] ;
|
||||||
|
deriv[2] = -position[0] * position[1] - b * position[2] ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void advance_in_time ( double time_step, double position[3], double new_position[3] )
|
||||||
|
{
|
||||||
|
/* Move a point along the Lorenz attractor */
|
||||||
|
double deriv0[3], deriv1[3], deriv2[3], deriv3[3] ;
|
||||||
|
int i ;
|
||||||
|
memcpy ( new_position, position, 3 * sizeof(double) ) ; /* Save the present values */
|
||||||
|
|
||||||
|
/* First pass in a Fourth-Order Runge-Kutta integration method */
|
||||||
|
calc_deriv ( position, deriv0 ) ;
|
||||||
|
for ( i = 0; i < 3; i++ )
|
||||||
|
new_position[i] = position[i] + 0.5 * time_step * deriv0[i] ;
|
||||||
|
|
||||||
|
/* Second pass */
|
||||||
|
calc_deriv ( new_position, deriv1 ) ;
|
||||||
|
for ( i = 0; i < 3; i++ )
|
||||||
|
new_position[i] = position[i] + 0.5 * time_step * deriv1[i] ;
|
||||||
|
|
||||||
|
/* Third pass */
|
||||||
|
calc_deriv ( position, deriv2 ) ;
|
||||||
|
for ( i = 0; i < 3; i++ )
|
||||||
|
new_position[i] = position[i] + time_step * deriv2[i] ;
|
||||||
|
|
||||||
|
/* Second pass */
|
||||||
|
calc_deriv ( new_position, deriv3 ) ;
|
||||||
|
for ( i = 0; i < 3; i++ )
|
||||||
|
new_position[i] = position[i] + 0.1666666666666666667 * time_step *
|
||||||
|
( deriv0[i] + 2.0 * ( deriv1[i] + deriv2[i] ) + deriv3[i] ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
checkedFGets ( char *s, int size, FILE *stream )
|
||||||
|
{
|
||||||
|
if ( fgets ( s, size, stream ) == NULL ) {
|
||||||
|
fprintf ( stderr, "fgets failed\n");
|
||||||
|
exit ( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* GLUT callbacks */
|
||||||
|
|
||||||
|
#define INPUT_LINE_LENGTH 80
|
||||||
|
|
||||||
|
void key_cb ( unsigned char key, int x, int y )
|
||||||
|
{
|
||||||
|
int i ;
|
||||||
|
char inputline [ INPUT_LINE_LENGTH ] ;
|
||||||
|
|
||||||
|
switch ( key )
|
||||||
|
{
|
||||||
|
case 'r' : case 'R' : /* Reset the simulation */
|
||||||
|
/* Reset the Lorenz parameters */
|
||||||
|
sigma = s0 ;
|
||||||
|
b = b0 ;
|
||||||
|
r = r0 ;
|
||||||
|
/* Set an initial position */
|
||||||
|
red_position[0][0] = (double)rand() / (double)RAND_MAX ;
|
||||||
|
red_position[0][1] = (double)rand() / (double)RAND_MAX ;
|
||||||
|
red_position[0][2] = (double)rand() / (double)RAND_MAX ;
|
||||||
|
grn_position[0][0] = (double)rand() / (double)RAND_MAX ;
|
||||||
|
grn_position[0][1] = (double)rand() / (double)RAND_MAX ;
|
||||||
|
grn_position[0][2] = (double)rand() / (double)RAND_MAX ;
|
||||||
|
array_index = 0 ;
|
||||||
|
/* Initialize the arrays */
|
||||||
|
for ( i = 1; i < NUM_POINTS; i++ )
|
||||||
|
{
|
||||||
|
memcpy ( red_position[i], red_position[0], 3 * sizeof(double) ) ;
|
||||||
|
memcpy ( grn_position[i], grn_position[0], 3 * sizeof(double) ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 'm' : case 'M' : /* Modify the Lorenz parameters */
|
||||||
|
printf ( "Please enter new value for <sigma> (default %f, currently %f): ", s0, sigma ) ;
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), stdin ) ;
|
||||||
|
sscanf ( inputline, "%lf", &sigma ) ;
|
||||||
|
|
||||||
|
printf ( "Please enter new value for <b> (default %f, currently %f): ", b0, b ) ;
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), stdin ) ;
|
||||||
|
sscanf ( inputline, "%lf", &b ) ;
|
||||||
|
|
||||||
|
printf ( "Please enter new value for <r> (default %f, currently %f): ", r0, r ) ;
|
||||||
|
checkedFGets ( inputline, sizeof ( inputline ), stdin ) ;
|
||||||
|
sscanf ( inputline, "%lf", &r ) ;
|
||||||
|
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 's' : case 'S' : /* Stop the animation */
|
||||||
|
animate = 0 ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 'g' : case 'G' : /* Start the animation */
|
||||||
|
animate = 1 ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case ' ' : /* Spacebar: Single step */
|
||||||
|
animate = 2 ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 27 : /* Escape key */
|
||||||
|
glutLeaveMainLoop () ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void special_cb ( int key, int x, int y )
|
||||||
|
{
|
||||||
|
switch ( key )
|
||||||
|
{
|
||||||
|
case GLUT_KEY_UP : /* Rotate up a little */
|
||||||
|
glRotated ( ROTATION_ANGLE, 0.0, 1.0, 0.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_DOWN : /* Rotate down a little */
|
||||||
|
glRotated ( -ROTATION_ANGLE, 0.0, 1.0, 0.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_LEFT : /* Rotate left a little */
|
||||||
|
glRotated ( ROTATION_ANGLE, 0.0, 0.0, 1.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_RIGHT : /* Rotate right a little */
|
||||||
|
glRotated ( -ROTATION_ANGLE, 0.0, 0.0, 1.0 ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_PAGE_UP : /* Zoom in a little */
|
||||||
|
glScaled ( 1.0 / SCALE_FACTOR, 1.0 / SCALE_FACTOR, 1.0 / SCALE_FACTOR ) ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_KEY_PAGE_DOWN : /* Zoom out a little */
|
||||||
|
glScaled ( SCALE_FACTOR, SCALE_FACTOR, SCALE_FACTOR ) ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_cb ( int button, int updown, int x, int y )
|
||||||
|
{
|
||||||
|
if ( updown == GLUT_DOWN )
|
||||||
|
{
|
||||||
|
/*double dist = 1.0e20 ; A very large number */
|
||||||
|
/* The idea here is that we go into "pick" mode and pick the nearest point
|
||||||
|
to the mouse click position. Unfortunately I don't have the time to implement
|
||||||
|
it at the moment. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_curve ( int index, double position [ NUM_POINTS ][3] )
|
||||||
|
{
|
||||||
|
int i = index ;
|
||||||
|
|
||||||
|
glBegin ( GL_LINE_STRIP ) ;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i = ( i == NUM_POINTS-1 ) ? 0 : i + 1 ;
|
||||||
|
glVertex3dv ( position[i] ) ;
|
||||||
|
}
|
||||||
|
while ( i != index ) ;
|
||||||
|
|
||||||
|
glEnd () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitmapPrintf (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
static char buf[256];
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||||
|
(void) _vsnprintf (buf, sizeof(buf), fmt, args);
|
||||||
|
#else
|
||||||
|
(void) vsnprintf (buf, sizeof(buf), fmt, args);
|
||||||
|
#endif
|
||||||
|
va_end(args);
|
||||||
|
glutBitmapString ( GLUT_BITMAP_HELVETICA_12, (unsigned char*)buf ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_cb ( void )
|
||||||
|
{
|
||||||
|
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
|
||||||
|
|
||||||
|
glColor3d ( 1.0, 1.0, 1.0 ) ; /* White */
|
||||||
|
/* Draw some axes */
|
||||||
|
glBegin ( GL_LINES ) ;
|
||||||
|
glVertex3d ( 0.0, 0.0, 0.0 ) ;
|
||||||
|
glVertex3d ( 2.0, 0.0, 0.0 ) ;
|
||||||
|
glVertex3d ( 0.0, 0.0, 0.0 ) ;
|
||||||
|
glVertex3d ( 0.0, 1.0, 0.0 ) ;
|
||||||
|
glVertex3d ( 0.0, 0.0, 0.0 ) ;
|
||||||
|
glVertex3d ( 0.0, 0.0, 1.0 ) ;
|
||||||
|
glEnd () ;
|
||||||
|
|
||||||
|
glColor3d ( 1.0, 0.0, 0.0 ) ; /* Red */
|
||||||
|
draw_curve ( array_index, red_position ) ;
|
||||||
|
|
||||||
|
glColor3d ( 0.0, 1.0, 0.0 ) ; /* Green */
|
||||||
|
draw_curve ( array_index, grn_position ) ;
|
||||||
|
|
||||||
|
/* Print the distance between the two points */
|
||||||
|
glColor3d ( 1.0, 1.0, 1.0 ) ; /* White */
|
||||||
|
glRasterPos2i ( 1, 1 ) ;
|
||||||
|
bitmapPrintf ( "Distance: %10.6f", distance ) ;
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reshape_cb ( int width, int height )
|
||||||
|
{
|
||||||
|
float ar;
|
||||||
|
glViewport ( 0, 0, width, height ) ;
|
||||||
|
glMatrixMode ( GL_PROJECTION ) ;
|
||||||
|
glLoadIdentity () ;
|
||||||
|
ar = (float) width / (float) height ;
|
||||||
|
glFrustum ( -ar, ar, -1.0, 1.0, 10.0, 100.0 ) ;
|
||||||
|
glMatrixMode ( GL_MODELVIEW ) ;
|
||||||
|
glLoadIdentity () ;
|
||||||
|
xcen = 0.0 ;
|
||||||
|
ycen = 0.0 ;
|
||||||
|
zcen = 0.0 ;
|
||||||
|
glTranslated ( xcen, ycen, zcen - 50.0 ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void timer_cb ( int value )
|
||||||
|
{
|
||||||
|
/* Function called at regular intervals to update the positions of the points */
|
||||||
|
double deltax, deltay, deltaz ;
|
||||||
|
int new_index = array_index + 1 ;
|
||||||
|
|
||||||
|
/* Set the next timed callback */
|
||||||
|
glutTimerFunc ( 30, timer_cb, 0 ) ;
|
||||||
|
|
||||||
|
if ( animate > 0 )
|
||||||
|
{
|
||||||
|
if ( new_index == NUM_POINTS ) new_index = 0 ;
|
||||||
|
advance_in_time ( time_step, red_position[array_index], red_position[new_index] ) ;
|
||||||
|
advance_in_time ( time_step, grn_position[array_index], grn_position[new_index] ) ;
|
||||||
|
array_index = new_index ;
|
||||||
|
|
||||||
|
deltax = red_position[array_index][0] - grn_position[array_index][0] ;
|
||||||
|
deltay = red_position[array_index][1] - grn_position[array_index][1] ;
|
||||||
|
deltaz = red_position[array_index][2] - grn_position[array_index][2] ;
|
||||||
|
distance = sqrt ( deltax * deltax + deltay * deltay + deltaz * deltaz ) ;
|
||||||
|
|
||||||
|
if ( animate == 2 ) animate = 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
glutPostRedisplay () ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* The Main Program */
|
||||||
|
|
||||||
|
int main ( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
int pargc = argc ;
|
||||||
|
|
||||||
|
/* Initialize the random number generator */
|
||||||
|
srand ( 1023 ) ;
|
||||||
|
|
||||||
|
/* Set up the OpenGL parameters */
|
||||||
|
glEnable ( GL_DEPTH_TEST ) ;
|
||||||
|
glClearColor ( 0.0, 0.0, 0.0, 0.0 ) ;
|
||||||
|
glClearDepth ( 1.0 ) ;
|
||||||
|
|
||||||
|
/* Initialize GLUT */
|
||||||
|
glutInitWindowSize ( 600, 600 ) ;
|
||||||
|
glutInit ( &pargc, argv ) ;
|
||||||
|
glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ;
|
||||||
|
|
||||||
|
/* Create the window */
|
||||||
|
glutCreateWindow ( "Lorenz Attractor" ) ;
|
||||||
|
glutKeyboardFunc ( key_cb ) ;
|
||||||
|
glutMouseFunc ( mouse_cb ) ;
|
||||||
|
glutSpecialFunc ( special_cb ) ;
|
||||||
|
glutDisplayFunc ( display_cb ) ;
|
||||||
|
glutReshapeFunc ( reshape_cb ) ;
|
||||||
|
glutTimerFunc ( 30, timer_cb, 0 ) ;
|
||||||
|
|
||||||
|
/* Initialize the attractor: The easiest way is to call the keyboard callback with an
|
||||||
|
* argument of 'r' for Reset.
|
||||||
|
*/
|
||||||
|
key_cb ( 'r', 0, 0 ) ;
|
||||||
|
|
||||||
|
/* Enter the GLUT main loop */
|
||||||
|
glutMainLoop () ;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAK INFORMATION */
|
||||||
|
_CrtDumpMemoryLeaks () ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,405 @@
|
||||||
|
/*
|
||||||
|
* one.c
|
||||||
|
*
|
||||||
|
* Hey! This was the original file where freeglut development started. Just
|
||||||
|
* note what I have written here at the time. And see the creation date :)
|
||||||
|
*
|
||||||
|
* : This is a wrapper. I still have to figure out
|
||||||
|
* : how to build shared libraries under *nix :)
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999 by Pawel W. Olszta
|
||||||
|
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
|
||||||
|
* Creation date: czw gru 2 11:58:41 CET 1999
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
int g_LeaveGameMode = 0;
|
||||||
|
int g_InGameMode = 0;
|
||||||
|
int g_mainwin1, g_mainwin2, g_sw1, g_sw2, g_gamemodewin;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call this function to have some text drawn at given coordinates
|
||||||
|
*/
|
||||||
|
void PrintText( int nX, int nY, char* pszText )
|
||||||
|
{
|
||||||
|
int lines;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare the OpenGL state
|
||||||
|
*/
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
glDisable( GL_DEPTH_TEST );
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have an orthogonal projection matrix set
|
||||||
|
*/
|
||||||
|
glOrtho( 0, glutGet( GLUT_WINDOW_WIDTH ),
|
||||||
|
0, glutGet( GLUT_WINDOW_HEIGHT ),
|
||||||
|
-1, +1
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now the matrix mode
|
||||||
|
*/
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now the main text
|
||||||
|
*/
|
||||||
|
glColor3ub( 0, 0, 0 );
|
||||||
|
glRasterPos2i( nX, nY );
|
||||||
|
|
||||||
|
for( p=pszText, lines=0; *p; p++ )
|
||||||
|
{
|
||||||
|
if( *p == '\n' )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
glRasterPos2i( nX, nY-(lines*18) );
|
||||||
|
}
|
||||||
|
|
||||||
|
glutBitmapCharacter( GLUT_BITMAP_HELVETICA_18, *p );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Revert to the old matrix modes
|
||||||
|
*/
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore the old OpenGL states
|
||||||
|
*/
|
||||||
|
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the display routine for our sample FreeGLUT windows
|
||||||
|
*/
|
||||||
|
void SampleDisplay( void )
|
||||||
|
{
|
||||||
|
int win = glutGetWindow();
|
||||||
|
|
||||||
|
if (g_InGameMode && win!=g_gamemodewin)
|
||||||
|
/* Don't draw other windows when in gamemode, those aren't visible
|
||||||
|
* anyway. Drawing them continuously nonetheless can cause flicker trouble
|
||||||
|
* on my machine. This only seems to occur only when there are child windows
|
||||||
|
* among the non-visible windows
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (win==g_sw1)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Clear the screen
|
||||||
|
*/
|
||||||
|
glClearColor(0.7f,0.7f,0.7f,1);
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
|
glutPostWindowRedisplay(g_mainwin2);
|
||||||
|
}
|
||||||
|
else if (win==g_sw2)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Clear the screen
|
||||||
|
*/
|
||||||
|
glClearColor(0.3f,0.3f,0.3f,1);
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
|
glutPostWindowRedisplay(g_mainwin2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const GLfloat time = glutGet(GLUT_ELAPSED_TIME) / 1000.f * 40;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the screen
|
||||||
|
*/
|
||||||
|
glClearColor( 0, 0.5, 1, 1 );
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have the cube rotated
|
||||||
|
*/
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
glRotatef( time, 0, 0, 1 );
|
||||||
|
glRotatef( time, 0, 1, 0 );
|
||||||
|
glRotatef( time, 1, 0, 0 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* And then drawn...
|
||||||
|
*/
|
||||||
|
glColor3f( 1, 1, 0 );
|
||||||
|
/* glutWireCube( 20.0 ); */
|
||||||
|
glutWireTeapot( 20.0 );
|
||||||
|
/* glutWireSphere( 15.0, 15, 15 ); */
|
||||||
|
/* glColor3f( 0, 1, 0 ); */
|
||||||
|
/* glutWireCube( 30.0 ); */
|
||||||
|
/* glutSolidCone( 10, 20, 10, 2 ); */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't forget about the model-view matrix
|
||||||
|
*/
|
||||||
|
glPopMatrix( );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw a silly text
|
||||||
|
*/
|
||||||
|
if( g_InGameMode == 0 )
|
||||||
|
PrintText( 20, 20, "Hello there cruel world!" );
|
||||||
|
else
|
||||||
|
PrintText( 20, 20, "Press ESC to leave the game mode!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* And swap this context's buffers
|
||||||
|
*/
|
||||||
|
glutSwapBuffers( );
|
||||||
|
glutPostWindowRedisplay(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a sample idle function
|
||||||
|
*/
|
||||||
|
void SampleIdle( void )
|
||||||
|
{
|
||||||
|
if( g_LeaveGameMode == 1 )
|
||||||
|
{
|
||||||
|
/* One could do all this just as well in SampleGameModeKeyboard... */
|
||||||
|
printf("leaving gamemode...\n");
|
||||||
|
glutLeaveGameMode( );
|
||||||
|
g_LeaveGameMode = 0;
|
||||||
|
g_InGameMode = 0;
|
||||||
|
glutPostWindowRedisplay(g_mainwin1);
|
||||||
|
glutPostWindowRedisplay(g_mainwin2);
|
||||||
|
glutPostWindowRedisplay(g_sw1);
|
||||||
|
glutPostWindowRedisplay(g_sw2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SampleEntry(int state)
|
||||||
|
{
|
||||||
|
int window = glutGetWindow () ;
|
||||||
|
printf ( "Window %d Entry Callback: %d\n", window, state ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The reshape function
|
||||||
|
*/
|
||||||
|
void SampleReshape( int nWidth, int nHeight )
|
||||||
|
{
|
||||||
|
GLfloat fAspect = (GLfloat) nHeight / (GLfloat) nWidth;
|
||||||
|
GLfloat fPos[ 4 ] = { 0.0f, 0.0f, 10.0f, 0.0f };
|
||||||
|
GLfloat fCol[ 4 ] = { 0.5f, 1.0f, 0.0f, 1.0f };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the viewport first
|
||||||
|
*/
|
||||||
|
glViewport( 0, 0, nWidth, nHeight );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Then the projection matrix
|
||||||
|
*/
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glLoadIdentity();
|
||||||
|
glFrustum( -1.0, 1.0, -fAspect, fAspect, 1.0, 80.0 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move back the camera a bit
|
||||||
|
*/
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity( );
|
||||||
|
glTranslatef( 0.0, 0.0, -40.0f );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable some features...
|
||||||
|
*/
|
||||||
|
glEnable( GL_CULL_FACE );
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
glEnable( GL_NORMALIZE );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up some lighting
|
||||||
|
*/
|
||||||
|
glLightfv( GL_LIGHT0, GL_POSITION, fPos );
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
glEnable( GL_LIGHT0 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up a sample material
|
||||||
|
*/
|
||||||
|
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, fCol );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A sample keyboard callback
|
||||||
|
*/
|
||||||
|
void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
|
||||||
|
{
|
||||||
|
printf( "SampleKeyboard(): keypress '%c' at (%i,%i)\n",
|
||||||
|
cChar, nMouseX, nMouseY );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A sample keyboard callback (for game mode window)
|
||||||
|
*/
|
||||||
|
void SampleGameModeKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
|
||||||
|
{
|
||||||
|
if( cChar == 27 )
|
||||||
|
g_LeaveGameMode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A sample special callback
|
||||||
|
*/
|
||||||
|
void SampleSpecial( int nSpecial, int nMouseX, int nMouseY )
|
||||||
|
{
|
||||||
|
printf( "SampleSpecial(): special keypress %i at (%i,%i)\n",
|
||||||
|
nSpecial, nMouseX, nMouseY );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A sample menu callback
|
||||||
|
*/
|
||||||
|
void SampleMenu( int menuID )
|
||||||
|
{
|
||||||
|
printf( "SampleMenu() callback executed, menuID is %i\n", menuID );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A sample menu status callback
|
||||||
|
*/
|
||||||
|
void SampleMenuStatus( int status, int x, int y )
|
||||||
|
{
|
||||||
|
printf ( "SampleMenu() callback executed, MenuStatus is %i at (%i,%i)\n", status, x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The sample's entry point
|
||||||
|
*/
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
int menuID, subMenuA, subMenuB;
|
||||||
|
|
||||||
|
glutInitDisplayString( "stencil~2 rgb double depth>=16 samples" );
|
||||||
|
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
|
||||||
|
glutInitWindowPosition( 100, 100 );
|
||||||
|
|
||||||
|
glutInit( &argc, argv );
|
||||||
|
|
||||||
|
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS);
|
||||||
|
glutMenuStatusFunc( SampleMenuStatus );
|
||||||
|
glutIdleFunc( SampleIdle );
|
||||||
|
|
||||||
|
subMenuA = glutCreateMenu( SampleMenu );
|
||||||
|
glutAddMenuEntry( "Sub menu A1 (01)", 1 );
|
||||||
|
glutAddMenuEntry( "Sub menu A2 (02)", 2 );
|
||||||
|
glutAddMenuEntry( "Sub menu A3 (03)", 3 );
|
||||||
|
|
||||||
|
subMenuB = glutCreateMenu( SampleMenu );
|
||||||
|
glutAddMenuEntry( "Sub menu B1 (04)", 4 );
|
||||||
|
glutAddMenuEntry( "Sub menu B2 (05)", 5 );
|
||||||
|
glutAddMenuEntry( "Sub menu B3 (06)", 6 );
|
||||||
|
glutAddSubMenu( "Going to sub menu A", subMenuA );
|
||||||
|
|
||||||
|
menuID = glutCreateMenu( SampleMenu );
|
||||||
|
glutAddMenuEntry( "Entry one", 1 );
|
||||||
|
glutAddMenuEntry( "Entry two", 2 );
|
||||||
|
glutAddMenuEntry( "Entry three", 3 );
|
||||||
|
glutAddMenuEntry( "Entry four", 4 );
|
||||||
|
glutAddMenuEntry( "Entry five", 5 );
|
||||||
|
glutAddSubMenu( "Enter sub menu A", subMenuA );
|
||||||
|
glutAddSubMenu( "Enter sub menu B", subMenuB );
|
||||||
|
|
||||||
|
g_mainwin1 = glutCreateWindow( "Hello world!" );
|
||||||
|
glutDisplayFunc( SampleDisplay );
|
||||||
|
glutReshapeFunc( SampleReshape );
|
||||||
|
glutKeyboardFunc( SampleKeyboard );
|
||||||
|
glutSpecialFunc( SampleSpecial );
|
||||||
|
glutEntryFunc( SampleEntry );
|
||||||
|
glutAttachMenu( GLUT_LEFT_BUTTON );
|
||||||
|
|
||||||
|
glutInitWindowPosition( 200, 200 );
|
||||||
|
g_mainwin2 = glutCreateWindow( "I am not Jan B." );
|
||||||
|
glutDisplayFunc( SampleDisplay );
|
||||||
|
glutReshapeFunc( SampleReshape );
|
||||||
|
glutKeyboardFunc( SampleKeyboard );
|
||||||
|
glutSpecialFunc( SampleSpecial );
|
||||||
|
glutEntryFunc( SampleEntry );
|
||||||
|
glutAttachMenu( GLUT_LEFT_BUTTON );
|
||||||
|
glutSetMenu(subMenuA);
|
||||||
|
glutAttachMenu( GLUT_RIGHT_BUTTON );
|
||||||
|
|
||||||
|
g_sw1=glutCreateSubWindow(g_mainwin2,200,0,100,100);
|
||||||
|
glutDisplayFunc( SampleDisplay );
|
||||||
|
glutSetMenu(subMenuB);
|
||||||
|
glutAttachMenu( GLUT_LEFT_BUTTON );
|
||||||
|
|
||||||
|
g_sw2=glutCreateSubWindow(g_sw1,50,0,50,50);
|
||||||
|
glutDisplayFunc( SampleDisplay );
|
||||||
|
glutSetMenu(menuID);
|
||||||
|
glutAttachMenu( GLUT_RIGHT_BUTTON );
|
||||||
|
|
||||||
|
printf( "Testing game mode string parsing, don't panic!\n" );
|
||||||
|
glutGameModeString( "320x240:32@100" );
|
||||||
|
glutGameModeString( "640x480:16@72" );
|
||||||
|
glutGameModeString( "1024x768" );
|
||||||
|
glutGameModeString( ":32@120" );
|
||||||
|
glutGameModeString( "Toudi glupcze, Danwin bedzie moj!" );
|
||||||
|
|
||||||
|
glutGameModeString( "640x480:37@300" ); /* this one should fail */
|
||||||
|
glutEnterGameMode();
|
||||||
|
|
||||||
|
glutGameModeString( "800x600" ); /* this one is likely to succeed */
|
||||||
|
g_gamemodewin = glutEnterGameMode();
|
||||||
|
|
||||||
|
if (glutGameModeGet(GLUT_GAME_MODE_ACTIVE))
|
||||||
|
g_InGameMode = 1;
|
||||||
|
glutDisplayFunc( SampleDisplay );
|
||||||
|
glutReshapeFunc( SampleReshape );
|
||||||
|
glutKeyboardFunc( SampleGameModeKeyboard );
|
||||||
|
glutEntryFunc( SampleEntry );
|
||||||
|
glutSetMenu(menuID);
|
||||||
|
glutAttachMenu( GLUT_LEFT_BUTTON );
|
||||||
|
|
||||||
|
printf( "current window is %ix%i at (%i,%i)\n",
|
||||||
|
glutGet( GLUT_WINDOW_WIDTH ), glutGet( GLUT_WINDOW_HEIGHT ),
|
||||||
|
glutGet( GLUT_WINDOW_X ), glutGet( GLUT_WINDOW_Y )
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Describe pixel format
|
||||||
|
*/
|
||||||
|
printf("The current window has %i red bits, %i green bits, %i blue bits and %i alpha bits for a total buffer size of %i bits\n",glutGet(GLUT_WINDOW_RED_SIZE),glutGet(GLUT_WINDOW_GREEN_SIZE),glutGet(GLUT_WINDOW_BLUE_SIZE),glutGet(GLUT_WINDOW_ALPHA_SIZE),glutGet(GLUT_WINDOW_BUFFER_SIZE));
|
||||||
|
printf("It furthermore has %i depth bits and %i stencil bits\n",glutGet(GLUT_WINDOW_DEPTH_SIZE),glutGet(GLUT_WINDOW_STENCIL_SIZE));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enter the main FreeGLUT processing loop
|
||||||
|
*/
|
||||||
|
glutMainLoop();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returned from mainloop after window closed
|
||||||
|
* see glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS); above
|
||||||
|
*/
|
||||||
|
printf( "glutMainLoop() termination works fine!\n" );
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** END OF FILE ***/
|
|
@ -0,0 +1 @@
|
||||||
|
GLUT_ICON ICON DISCARDABLE "objects.ico"
|
|
@ -0,0 +1,175 @@
|
||||||
|
/* Indexed color mode demo
|
||||||
|
* Written by John Tsiombikas <nuclear@member.fsf.org>
|
||||||
|
*
|
||||||
|
* Demonstrates how to create an indexed color OpenGL context, manipulate the
|
||||||
|
* colormap, and do lighting in indexed color mode.
|
||||||
|
*
|
||||||
|
* Obviously none of this will work if your OpenGL implementation and/or
|
||||||
|
* window system does not support indexed color.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
void display(void);
|
||||||
|
void reshape(int x, int y);
|
||||||
|
void keyb(unsigned char key, int x, int y);
|
||||||
|
void mouse(int bn, int st, int x, int y);
|
||||||
|
void motion(int x, int y);
|
||||||
|
|
||||||
|
float cam_theta, cam_phi, cam_dist = 6;
|
||||||
|
|
||||||
|
int prev_x, prev_y;
|
||||||
|
int bnstate[8];
|
||||||
|
|
||||||
|
int sphere, torus;
|
||||||
|
int redramp[3], blueramp[3];
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i, ncolors, rampsz, maxdif;
|
||||||
|
float x;
|
||||||
|
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
/* request an indexed color visual, this will fail on most modern systems */
|
||||||
|
glutInitDisplayMode(GLUT_INDEX | GLUT_DEPTH | GLUT_DOUBLE);
|
||||||
|
glutInitWindowSize(640, 480);
|
||||||
|
glutCreateWindow("FreeGLUT indexed color demo");
|
||||||
|
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutReshapeFunc(reshape);
|
||||||
|
glutKeyboardFunc(keyb);
|
||||||
|
glutMouseFunc(mouse);
|
||||||
|
glutMotionFunc(motion);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
ncolors = glutGet(GLUT_WINDOW_COLORMAP_SIZE);
|
||||||
|
printf("Colormap size: %d\n", ncolors);
|
||||||
|
|
||||||
|
rampsz = ncolors / 2;
|
||||||
|
maxdif = (int)(rampsz * 0.75f);
|
||||||
|
|
||||||
|
/* prepare a palette with two color ramps for a red and a blue object */
|
||||||
|
for(i=0; i<rampsz; i++) {
|
||||||
|
if(i < maxdif) {
|
||||||
|
x = (float)i / (maxdif - 1);
|
||||||
|
glutSetColor(i, x, 0, 0);
|
||||||
|
glutSetColor(i + rampsz, 0, 0, x);
|
||||||
|
} else {
|
||||||
|
x = (float)(i - maxdif) / (rampsz - maxdif - 1);
|
||||||
|
glutSetColor(i, 1, x, x);
|
||||||
|
glutSetColor(i + rampsz, x, x, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* prepare the indexed color lighting descriptors needed by OpenGL to
|
||||||
|
* compute lighting in indexed color mode.
|
||||||
|
*/
|
||||||
|
redramp[0] = 0; /* unlit color index*/
|
||||||
|
redramp[1] = maxdif - 1; /* maximum diffuse color index*/
|
||||||
|
redramp[2] = rampsz - 1; /* maximum specularity color index */
|
||||||
|
blueramp[0] = rampsz; /* ... and same for the blue ramp ... */
|
||||||
|
blueramp[1] = rampsz + maxdif - 1;
|
||||||
|
blueramp[2] = rampsz * 2 - 1;
|
||||||
|
|
||||||
|
/* set the specular exponent for all objects once */
|
||||||
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 40);
|
||||||
|
|
||||||
|
|
||||||
|
sphere = glGenLists(1);
|
||||||
|
glNewList(sphere, GL_COMPILE);
|
||||||
|
glutSolidSphere(1, 30, 15);
|
||||||
|
glEndList();
|
||||||
|
|
||||||
|
torus = glGenLists(1);
|
||||||
|
glNewList(torus, GL_COMPILE);
|
||||||
|
glutSolidTorus(0.35, 0.9, 20, 40);
|
||||||
|
glEndList();
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display(void)
|
||||||
|
{
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(0, 0, -cam_dist);
|
||||||
|
glRotatef(cam_phi, 1, 0, 0);
|
||||||
|
glRotatef(cam_theta, 0, 1, 0);
|
||||||
|
|
||||||
|
/* set up the red object's lighting indices */
|
||||||
|
glMaterialiv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, redramp);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(-1.5, 0, 0);
|
||||||
|
glCallList(sphere);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
/* setup the blue object's lighting indices */
|
||||||
|
glMaterialiv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, blueramp);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(1.5, 0, 0);
|
||||||
|
glRotatef(90, 1, 0, 0);
|
||||||
|
glCallList(torus);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reshape(int x, int y)
|
||||||
|
{
|
||||||
|
glViewport(0, 0, x, y);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
gluPerspective(50.0, (float)x / y, 0.5, 500.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyb(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
switch(key) {
|
||||||
|
case 27:
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse(int bn, int st, int x, int y)
|
||||||
|
{
|
||||||
|
bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
|
||||||
|
prev_x = x;
|
||||||
|
prev_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void motion(int x, int y)
|
||||||
|
{
|
||||||
|
int dx, dy;
|
||||||
|
|
||||||
|
dx = x - prev_x;
|
||||||
|
dy = y - prev_y;
|
||||||
|
prev_x = x;
|
||||||
|
prev_y = y;
|
||||||
|
|
||||||
|
if(!(dx | dy)) return;
|
||||||
|
|
||||||
|
if(bnstate[0]) {
|
||||||
|
cam_theta += dx * 0.5f;
|
||||||
|
cam_phi += dy * 0.5f;
|
||||||
|
if(cam_phi < -90) cam_phi = -90;
|
||||||
|
if(cam_phi > 90) cam_phi = 90;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
if(bnstate[2]) {
|
||||||
|
cam_dist += dy * 0.1f;
|
||||||
|
if(cam_dist < 0) cam_dist = 0;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* ------------------------------------------
|
||||||
|
* user_error_handler.c
|
||||||
|
*
|
||||||
|
* This is a sample program showing a basic
|
||||||
|
* user defined error handlers with FreeGLUT
|
||||||
|
* ------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------
|
||||||
|
* Declare our own Error handler for FreeGLUT
|
||||||
|
* ------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This declares the vprintf() routine */
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* This declares the va_list type */
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/* The new handler looks like a vprintf prototype */
|
||||||
|
void myError (const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "myError: Entering user defined error handler\n");
|
||||||
|
|
||||||
|
/* print warning message */
|
||||||
|
fprintf(stderr, "myError:");
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
/* deInitialize the freeglut state */
|
||||||
|
fprintf(stderr, "myError: Calling glutExit()\n");
|
||||||
|
glutExit();
|
||||||
|
|
||||||
|
/* terminate error handler appropriately */
|
||||||
|
fprintf(stderr, "myError: Exit-ing handler routine\n");
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------
|
||||||
|
* Just enough code to create the error to
|
||||||
|
* demonstrate the user defined handler
|
||||||
|
* ------------------------------------------
|
||||||
|
*/
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
glutInitErrorFunc(&myError);
|
||||||
|
glutCreateWindow ("error test"); /* This is an error! */
|
||||||
|
glutInit(&argc, argv); /* Should be called
|
||||||
|
after glutInit() */
|
||||||
|
glutMainLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,221 @@
|
||||||
|
/* Joystick demo
|
||||||
|
* Written by John Tsiombikas <nuclear@member.fsf.org>
|
||||||
|
* Press escape or q to exit.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable: 4305 4244)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void display(void);
|
||||||
|
void rect(float x0, float y0, float x1, float y1);
|
||||||
|
void text(float x, float y, const char *fmt, ...);
|
||||||
|
void widget(float xsz, float ysz, float xpos, float ypos);
|
||||||
|
void button(float sz, float state);
|
||||||
|
void reshape(int x, int y);
|
||||||
|
void keyboard(unsigned char key, int x, int y);
|
||||||
|
void joystick(unsigned int bmask, int x, int y, int z);
|
||||||
|
|
||||||
|
int win_width, win_height;
|
||||||
|
int joy[3];
|
||||||
|
unsigned int joy_bmask;
|
||||||
|
int num_buttons, bhist;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitWindowSize(800, 600);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||||
|
glutCreateWindow("Joystick demo");
|
||||||
|
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutReshapeFunc(reshape);
|
||||||
|
glutKeyboardFunc(keyboard);
|
||||||
|
glutJoystickFunc(joystick, 25);
|
||||||
|
|
||||||
|
if(!glutGet(GLUT_HAS_JOYSTICK)) {
|
||||||
|
fprintf(stderr, "no joystick detected\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("Joystick axes: %d\n", glutGet(GLUT_JOYSTICK_AXES));
|
||||||
|
num_buttons = glutGet(GLUT_JOYSTICK_BUTTONS);
|
||||||
|
printf("Joystick buttons: %d\n", num_buttons);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WSZ 0.8
|
||||||
|
#define RAD (WSZ / 8)
|
||||||
|
#define FRM 0.0075
|
||||||
|
#define MAX_BSZ (WSZ / 9)
|
||||||
|
|
||||||
|
void display(void)
|
||||||
|
{
|
||||||
|
float dmax = WSZ * 0.5f - RAD;
|
||||||
|
float jx, jy, jz, cury, bsz;
|
||||||
|
int i, num;
|
||||||
|
|
||||||
|
jx = joy[0] / 1000.0f;
|
||||||
|
jy = joy[1] / 1000.0f;
|
||||||
|
jz = joy[2] / 1000.0f;
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(-WSZ / 2, 0, 0);
|
||||||
|
widget(WSZ, WSZ, jx * dmax, -jy * dmax);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(WSZ / 2, 0, 0);
|
||||||
|
widget(RAD * 2, WSZ, 0, -jz * dmax);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
if(num_buttons > 0) {
|
||||||
|
num = num_buttons;
|
||||||
|
} else {
|
||||||
|
bhist |= joy_bmask;
|
||||||
|
num = 0;
|
||||||
|
while(num < 32 && bhist >> num) {
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(num) {
|
||||||
|
if(num > 32) num = 32;
|
||||||
|
bsz = 2.0 / (num * 1.4);
|
||||||
|
|
||||||
|
if(bsz > MAX_BSZ) bsz = MAX_BSZ;
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(-bsz * 1.4 * (num - 1) / 2, 0.7, 0);
|
||||||
|
for(i=0; i<num; i++) {
|
||||||
|
button(bsz, joy_bmask & (1 << i));
|
||||||
|
glTranslatef(bsz * 1.4, 0, 0);
|
||||||
|
}
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
glColor3f(0, 1, 0);
|
||||||
|
cury = -2 * WSZ / 3;
|
||||||
|
text(-WSZ * 0.75, cury, "X: %d", joy[0]);
|
||||||
|
cury -= 0.08;
|
||||||
|
text(-WSZ * 0.75, cury, "Y: %d", joy[1]);
|
||||||
|
cury -= 0.08;
|
||||||
|
text(-WSZ * 0.75, cury, "Z: %d", joy[2]);
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rect(float x0, float y0, float x1, float y1)
|
||||||
|
{
|
||||||
|
glVertex2f(x0, y0);
|
||||||
|
glVertex2f(x1, y0);
|
||||||
|
glVertex2f(x1, y1);
|
||||||
|
glVertex2f(x0, y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void text(float x, float y, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char buf[256], *s;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsprintf(buf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glRasterPos2f(x, y);
|
||||||
|
|
||||||
|
s = buf;
|
||||||
|
while(*s) {
|
||||||
|
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++);
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void widget(float xsz, float ysz, float xpos, float ypos)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float x, y, theta;
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor3f(1, 1, 1);
|
||||||
|
rect(-xsz / 2 - FRM, -ysz / 2 - FRM, xsz / 2 + FRM, ysz / 2 + FRM);
|
||||||
|
glColor3f(0.1, 0.1, 0.1);
|
||||||
|
rect(-xsz / 2, -ysz / 2, xsz / 2, ysz / 2);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
|
glColor3f(1, 0, 0);
|
||||||
|
glVertex2f(xpos, ypos);
|
||||||
|
for(i=0; i<20; i++) {
|
||||||
|
theta = M_PI * 2 * i / 19.0;
|
||||||
|
x = cos(theta) * RAD;
|
||||||
|
y = sin(theta) * RAD;
|
||||||
|
glVertex2f(xpos + x, ypos + y);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void button(float sz, float state)
|
||||||
|
{
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor3f(1, 1, 1);
|
||||||
|
rect(-sz / 2 - FRM, -sz / 2 - FRM, sz / 2 + FRM, sz / 2 + FRM);
|
||||||
|
|
||||||
|
glColor3f(state ? 1 : 0.2, 0.2, 0.2);
|
||||||
|
rect(-sz / 2, -sz / 2, sz / 2, sz / 2);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reshape(int x, int y)
|
||||||
|
{
|
||||||
|
float aspect = (float)x / y;
|
||||||
|
|
||||||
|
win_width = x;
|
||||||
|
win_height = y;
|
||||||
|
|
||||||
|
glViewport(0, 0, x, y);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glScalef(1.0 / aspect, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
if(key == 27 || key == 'q') {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void joystick(unsigned int bmask, int x, int y, int z)
|
||||||
|
{
|
||||||
|
joy[0] = x;
|
||||||
|
joy[1] = y;
|
||||||
|
joy[2] = z;
|
||||||
|
joy_bmask = bmask;
|
||||||
|
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
void display(void);
|
||||||
|
void draw_text(int x, int y, const char *str);
|
||||||
|
const char *skeyname(int skey);
|
||||||
|
void reshape(int x, int y);
|
||||||
|
void keypress(unsigned char key, int x, int y);
|
||||||
|
void keyrelease(unsigned char key, int x, int y);
|
||||||
|
void skeypress(int key, int x, int y);
|
||||||
|
void skeyrelease(int key, int x, int y);
|
||||||
|
|
||||||
|
unsigned int modstate;
|
||||||
|
int cur_key = -1;
|
||||||
|
int cur_skey = -1;
|
||||||
|
int win_width, win_height;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitWindowSize(400, 200);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||||
|
glutCreateWindow("Keyboard demo");
|
||||||
|
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutReshapeFunc(reshape);
|
||||||
|
glutKeyboardFunc(keypress);
|
||||||
|
glutKeyboardUpFunc(keyrelease);
|
||||||
|
glutSpecialFunc(skeypress);
|
||||||
|
glutSpecialUpFunc(skeyrelease);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display(void)
|
||||||
|
{
|
||||||
|
char str[256];
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
strcpy(str, "Key:");
|
||||||
|
if(cur_key > 0) {
|
||||||
|
if(isprint(cur_key)) {
|
||||||
|
sprintf(str + 4, " '%c'", cur_key);
|
||||||
|
} else {
|
||||||
|
sprintf(str + 4, " 0x%02x", cur_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(modstate & GLUT_ACTIVE_SHIFT) {
|
||||||
|
strcat(str, " shift");
|
||||||
|
}
|
||||||
|
if(modstate & GLUT_ACTIVE_CTRL) {
|
||||||
|
strcat(str, " ctrl");
|
||||||
|
}
|
||||||
|
if(modstate & GLUT_ACTIVE_ALT) {
|
||||||
|
strcat(str, " alt");
|
||||||
|
}
|
||||||
|
if(modstate & GLUT_ACTIVE_SUPER) {
|
||||||
|
strcat(str, " super");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_text(win_width / 3, 2 * win_height / 3, str);
|
||||||
|
|
||||||
|
strcpy(str, "Special key: ");
|
||||||
|
if(cur_skey > 0) {
|
||||||
|
strcat(str, skeyname(cur_skey));
|
||||||
|
}
|
||||||
|
draw_text(win_width / 3, win_height / 3, str);
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_text(int x, int y, const char *str)
|
||||||
|
{
|
||||||
|
glRasterPos2i(x, y);
|
||||||
|
while(*str) {
|
||||||
|
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *str++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *skeyname(int skey)
|
||||||
|
{
|
||||||
|
static const char *fkeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"};
|
||||||
|
|
||||||
|
switch(skey) {
|
||||||
|
case GLUT_KEY_LEFT: return "left";
|
||||||
|
case GLUT_KEY_UP: return "up";
|
||||||
|
case GLUT_KEY_RIGHT: return "right";
|
||||||
|
case GLUT_KEY_DOWN: return "down";
|
||||||
|
case GLUT_KEY_PAGE_UP: return "page up";
|
||||||
|
case GLUT_KEY_PAGE_DOWN: return "page down";
|
||||||
|
case GLUT_KEY_HOME: return "home";
|
||||||
|
case GLUT_KEY_END: return "end";
|
||||||
|
case GLUT_KEY_INSERT: return "insert";
|
||||||
|
case GLUT_KEY_NUM_LOCK: return "num lock";
|
||||||
|
case GLUT_KEY_BEGIN: return "begin";
|
||||||
|
case GLUT_KEY_DELETE: return "delete";
|
||||||
|
case GLUT_KEY_SHIFT_L: return "L Shift";
|
||||||
|
case GLUT_KEY_SHIFT_R: return "R Shift";
|
||||||
|
case GLUT_KEY_CTRL_L: return "L Ctrl";
|
||||||
|
case GLUT_KEY_CTRL_R: return "R Ctrl";
|
||||||
|
case GLUT_KEY_ALT_L: return "L Alt";
|
||||||
|
case GLUT_KEY_ALT_R: return "R Alt";
|
||||||
|
case GLUT_KEY_SUPER_L: return "L Super";
|
||||||
|
case GLUT_KEY_SUPER_R: return "R Super";
|
||||||
|
default:
|
||||||
|
if(skey >= GLUT_KEY_F1 && skey <= GLUT_KEY_F12) {
|
||||||
|
return fkeys[skey - GLUT_KEY_F1];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "<unknown>";
|
||||||
|
}
|
||||||
|
|
||||||
|
void reshape(int x, int y)
|
||||||
|
{
|
||||||
|
win_width = x;
|
||||||
|
win_height = y;
|
||||||
|
glViewport(0, 0, x, y);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, x, 0, y, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keypress(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
if(key == 27) exit(0);
|
||||||
|
|
||||||
|
modstate = glutGetModifiers();
|
||||||
|
cur_key = key;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyrelease(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
cur_key = -1;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void skeypress(int key, int x, int y)
|
||||||
|
{
|
||||||
|
cur_skey = key;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void skeyrelease(int key, int x, int y)
|
||||||
|
{
|
||||||
|
cur_skey = -1;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
/**
|
||||||
|
* Sample multi-touch program that displays a square where a cursor
|
||||||
|
* clicks, with a different color for each cursor.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
#define NUM_DEVICES 16
|
||||||
|
#define NUM_CURSORS 64
|
||||||
|
typedef struct cursor {
|
||||||
|
char on;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} *Cursor;
|
||||||
|
struct cursor cursors[NUM_DEVICES][NUM_CURSORS];
|
||||||
|
|
||||||
|
|
||||||
|
static float square[] = {
|
||||||
|
-.5, -.5,
|
||||||
|
.5, -.5,
|
||||||
|
-.5, .5,
|
||||||
|
.5, .5,
|
||||||
|
};
|
||||||
|
|
||||||
|
void onDisplay(void) {
|
||||||
|
int d;
|
||||||
|
glClearColor(0,0,0,1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glVertexPointer(2, GL_FLOAT, 0, square);
|
||||||
|
for (d = 0; d < NUM_DEVICES; d++) {
|
||||||
|
int c;
|
||||||
|
for (c = 0; c < NUM_CURSORS; c++) {
|
||||||
|
Cursor C = &cursors[d][c];
|
||||||
|
if (C->on) {
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(C->x, C->y, 0);
|
||||||
|
glScalef(30, 30, 1);
|
||||||
|
|
||||||
|
switch(c) {
|
||||||
|
case 0:
|
||||||
|
glColor4f(0,0,1,1);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
glColor4f(0,1,0,1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glColor4f(1,0,0,1);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glColor4f(1,1,1,1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
glColor4d(.5,.5,.5,1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onMouse(int button, int state, int x, int y) {
|
||||||
|
if (button == 0) {
|
||||||
|
cursors[0][0].on = (state == GLUT_DOWN);
|
||||||
|
cursors[0][0].x = (float)x;
|
||||||
|
cursors[0][0].y = (float)y;
|
||||||
|
printf("normal click\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onMotion(int x, int y) {
|
||||||
|
cursors[0][0].x = (float)x;
|
||||||
|
cursors[0][0].y = (float)y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Using FG2.8 (reversed) prototype for now */
|
||||||
|
/* void onMultiButton(int cursor_id, int button, int state, int x, int y) { */
|
||||||
|
void onMultiButton(int cursor_id, int x, int y, int button, int state) {
|
||||||
|
if (cursor_id >= NUM_CURSORS) {
|
||||||
|
fprintf(stderr, "cursor_id (%d) >= NUM_CURSORS (%d), out of slots\n", cursor_id, NUM_CURSORS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (button == 0) {
|
||||||
|
cursors[0][cursor_id].on = (state == GLUT_DOWN);
|
||||||
|
cursors[0][cursor_id].x = (float)x;
|
||||||
|
cursors[0][cursor_id].y = (float)y;
|
||||||
|
printf("multi-touch %d click\n", cursor_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onMultiMotion(int cursor_id, int x, int y) {
|
||||||
|
if (cursor_id >= NUM_CURSORS) {
|
||||||
|
fprintf(stderr, "cursor_id (%d) >= NUM_CURSORS (%d), out of slots\n", cursor_id, NUM_CURSORS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cursors[0][cursor_id].x = (float)x;
|
||||||
|
cursors[0][cursor_id].y = (float)y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onReshape(int width, int height) {
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glOrtho(0, width, height, 0, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onIdle(void) {
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
memset(cursors, 0, sizeof(cursors));
|
||||||
|
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
|
||||||
|
glutInitWindowSize(640, 480);
|
||||||
|
glutCreateWindow("Multi-touch test");
|
||||||
|
|
||||||
|
glutDisplayFunc(onDisplay);
|
||||||
|
glutReshapeFunc(onReshape);
|
||||||
|
glutIdleFunc(onIdle);
|
||||||
|
glutMouseFunc(onMouse);
|
||||||
|
glutMotionFunc(onMotion);
|
||||||
|
glutMultiButtonFunc(onMultiButton);
|
||||||
|
glutMultiMotionFunc(onMultiMotion);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,395 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
int nWindow, nChildWindow = -1;
|
||||||
|
int nLoopMain = 0;
|
||||||
|
GLboolean bChildPosDone = GL_FALSE, bChildSizeDone = GL_FALSE;
|
||||||
|
|
||||||
|
void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY );
|
||||||
|
void Redisplay();
|
||||||
|
void Reshape(int width, int height);
|
||||||
|
void Position(int x, int y);
|
||||||
|
void WindowStatus(int state);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void DrawQuad()
|
||||||
|
{
|
||||||
|
int width = glutGet(GLUT_WINDOW_WIDTH);
|
||||||
|
int height = glutGet(GLUT_WINDOW_HEIGHT);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glVertex2d(width*.25, height*.75);
|
||||||
|
glVertex2d(width*.75, height*.75);
|
||||||
|
glVertex2d(width*.75, height*.25);
|
||||||
|
glVertex2d(width*.25, height*.25);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnhideTimer(int window)
|
||||||
|
{
|
||||||
|
glutSetWindow(window);
|
||||||
|
glutShowWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeTitleTimer(int unused)
|
||||||
|
{
|
||||||
|
glutSetIconTitle("new icon title");
|
||||||
|
glutSetWindowTitle("new test title");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
|
||||||
|
{
|
||||||
|
switch (cChar)
|
||||||
|
{
|
||||||
|
case 27:
|
||||||
|
glutLeaveMainLoop();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
printf("main window toggle fullscreen\n");
|
||||||
|
glutFullScreenToggle();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
if (nChildWindow!=-1 && cChar=='r') /* Capital R always resizes the main window*/
|
||||||
|
{
|
||||||
|
glutSetWindow(nChildWindow);
|
||||||
|
printf("child window resize\n");
|
||||||
|
if (!bChildSizeDone)
|
||||||
|
glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)+50,glutGet(GLUT_WINDOW_HEIGHT)+50);
|
||||||
|
else
|
||||||
|
glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)-50,glutGet(GLUT_WINDOW_HEIGHT)-50);
|
||||||
|
bChildSizeDone = !bChildSizeDone;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glutSetWindow(nWindow);
|
||||||
|
printf("main window resize\n");
|
||||||
|
if (glutGet(GLUT_WINDOW_WIDTH)<400)
|
||||||
|
glutReshapeWindow(600,300);
|
||||||
|
else
|
||||||
|
glutReshapeWindow(300,300);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
if (nChildWindow!=-1 && cChar=='m') /* Capital M always moves the main window*/
|
||||||
|
{
|
||||||
|
glutSetWindow(nChildWindow);
|
||||||
|
/* The window position you request is relative to the top-left
|
||||||
|
* corner of the client area of the parent window.
|
||||||
|
*/
|
||||||
|
if (!bChildPosDone)
|
||||||
|
glutPositionWindow(glutGet(GLUT_WINDOW_X)+50,glutGet(GLUT_WINDOW_Y)+50);
|
||||||
|
else
|
||||||
|
glutPositionWindow(glutGet(GLUT_WINDOW_X)-50,glutGet(GLUT_WINDOW_Y)-50);
|
||||||
|
bChildPosDone = !bChildPosDone;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glutSetWindow(nWindow);
|
||||||
|
printf("main window position\n");
|
||||||
|
/* The window position you request is the outer top-left of the window,
|
||||||
|
* the client area is at a different position if the window has borders
|
||||||
|
* and/or a title bar.
|
||||||
|
*/
|
||||||
|
if (glutGet(GLUT_WINDOW_X)<400)
|
||||||
|
glutPositionWindow(600,300);
|
||||||
|
else
|
||||||
|
glutPositionWindow(300,300);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
if (nChildWindow!=-1 && cChar=='d') /* Capital D always moves+resizes the main window*/
|
||||||
|
{
|
||||||
|
glutSetWindow(nChildWindow);
|
||||||
|
if (!bChildPosDone)
|
||||||
|
glutPositionWindow(glutGet(GLUT_WINDOW_X)+50,glutGet(GLUT_WINDOW_Y)+50);
|
||||||
|
else
|
||||||
|
glutPositionWindow(glutGet(GLUT_WINDOW_X)-50,glutGet(GLUT_WINDOW_Y)-50);
|
||||||
|
bChildPosDone = !bChildPosDone;
|
||||||
|
if (!bChildSizeDone)
|
||||||
|
glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)+50,glutGet(GLUT_WINDOW_HEIGHT)+50);
|
||||||
|
else
|
||||||
|
glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)-50,glutGet(GLUT_WINDOW_HEIGHT)-50);
|
||||||
|
bChildSizeDone = !bChildSizeDone;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (glutGet(GLUT_WINDOW_X)<400)
|
||||||
|
glutPositionWindow(600,300);
|
||||||
|
else
|
||||||
|
glutPositionWindow(300,300);
|
||||||
|
if (glutGet(GLUT_WINDOW_WIDTH)<400)
|
||||||
|
glutReshapeWindow(600,300);
|
||||||
|
else
|
||||||
|
glutReshapeWindow(300,300);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
if (nChildWindow==-1)
|
||||||
|
{
|
||||||
|
int width = glutGet(GLUT_WINDOW_WIDTH);
|
||||||
|
int height = glutGet(GLUT_WINDOW_HEIGHT);
|
||||||
|
|
||||||
|
/* open child window */
|
||||||
|
printf("open child window\n");
|
||||||
|
|
||||||
|
nChildWindow = glutCreateSubWindow(nWindow,(int)(width*.35),(int)(height*.35),(int)(width*.3),(int)(height*.3));
|
||||||
|
glutKeyboardFunc( SampleKeyboard );
|
||||||
|
glutDisplayFunc( Redisplay );
|
||||||
|
glutReshapeFunc( Reshape );
|
||||||
|
glutPositionFunc( Position );
|
||||||
|
glutWindowStatusFunc( WindowStatus );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* close child window */
|
||||||
|
printf("close child window\n");
|
||||||
|
glutSetWindow(nWindow);
|
||||||
|
glutDestroyWindow(nChildWindow);
|
||||||
|
nChildWindow = -1;
|
||||||
|
bChildSizeDone = GL_FALSE;
|
||||||
|
bChildPosDone = GL_FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
glutIconifyWindow();
|
||||||
|
glutTimerFunc(1500, ChangeTitleTimer, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
if (nChildWindow!=-1 && cChar=='h') /* Capital H always hides the main window*/
|
||||||
|
{
|
||||||
|
glutSetWindow(nChildWindow);
|
||||||
|
glutTimerFunc(2000, UnhideTimer, nChildWindow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glutSetWindow(nWindow);
|
||||||
|
glutTimerFunc(2000, UnhideTimer, nWindow);
|
||||||
|
}
|
||||||
|
glutHideWindow();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
if (nChildWindow!=-1 && cChar=='p') /* Capital P always changes pointer for the main window*/
|
||||||
|
{
|
||||||
|
glutSetWindow(nChildWindow);
|
||||||
|
if (glutGet(GLUT_WINDOW_CURSOR)==GLUT_CURSOR_TOP_SIDE)
|
||||||
|
{
|
||||||
|
glutSetCursor(GLUT_CURSOR_RIGHT_ARROW);
|
||||||
|
printf("reverting child window cursor\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glutSetCursor(GLUT_CURSOR_TOP_SIDE);
|
||||||
|
printf("changing child window cursor\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glutSetWindow(nWindow);
|
||||||
|
if (glutGet(GLUT_WINDOW_CURSOR)==GLUT_CURSOR_CYCLE)
|
||||||
|
{
|
||||||
|
glutSetCursor(GLUT_CURSOR_RIGHT_ARROW);
|
||||||
|
printf("reverting main window cursor\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glutSetCursor(GLUT_CURSOR_CYCLE);
|
||||||
|
printf("changing main window cursor\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idle(void)
|
||||||
|
{
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reshape(int width, int height)
|
||||||
|
{
|
||||||
|
int win = glutGetWindow();
|
||||||
|
|
||||||
|
printf("reshape %s, client area: %dx%d\n",win==nWindow?"main":"child",
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
glViewport(0,0,width,height);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
gluOrtho2D(0,width,0,height);
|
||||||
|
|
||||||
|
if (win==nWindow && nChildWindow!=-1)
|
||||||
|
{
|
||||||
|
/* Put child window in right place */
|
||||||
|
int x = (int)(width*.35), y=(int)(height*.35), w=(int)(width*.3), h = (int)(height*.3);
|
||||||
|
if (bChildPosDone)
|
||||||
|
{
|
||||||
|
x += 50;
|
||||||
|
y += 50;
|
||||||
|
}
|
||||||
|
if (bChildSizeDone)
|
||||||
|
{
|
||||||
|
w += 50;
|
||||||
|
h += 50;
|
||||||
|
}
|
||||||
|
glutSetWindow(nChildWindow);
|
||||||
|
glutPositionWindow(x,y);
|
||||||
|
glutReshapeWindow(w,h);
|
||||||
|
glutSetWindow(nWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Position(int x, int y)
|
||||||
|
{
|
||||||
|
int win = glutGetWindow();
|
||||||
|
|
||||||
|
printf("position, %s: (%d,%d)\n",win==nWindow?"top-left (non-client) of main":"top-left of child relative to parent",
|
||||||
|
x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowStatus(int state)
|
||||||
|
{
|
||||||
|
int win = glutGetWindow();
|
||||||
|
printf("windowstatus (win %i): %i\n",win,state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Redisplay(void)
|
||||||
|
{
|
||||||
|
int win = glutGetWindow();
|
||||||
|
int viewport[4];
|
||||||
|
|
||||||
|
if (win==nWindow)
|
||||||
|
{
|
||||||
|
glClearColor(.2f,0.f,0.f,0.f);
|
||||||
|
glColor3f(1,1,1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* child window */
|
||||||
|
glClearColor(.0f,.2f,0.f,0.f);
|
||||||
|
glColor3f(.5,.5,.5);
|
||||||
|
glutPostWindowRedisplay(nWindow);
|
||||||
|
}
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
DrawQuad();
|
||||||
|
|
||||||
|
if (win==nWindow)
|
||||||
|
{
|
||||||
|
glColor3f(1, 1, 0);
|
||||||
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||||
|
glRasterPos2i(2, -glutBitmapHeight(GLUT_BITMAP_9_BY_15)+3+viewport[3]);
|
||||||
|
glutBitmapString(GLUT_BITMAP_9_BY_15, (unsigned char*)"press f/r/m/d/c/i/h/p");
|
||||||
|
}
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
glutPostWindowRedisplay(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer(int unused)
|
||||||
|
{
|
||||||
|
int win = glutGetWindow();
|
||||||
|
int x, y;
|
||||||
|
int width, height;
|
||||||
|
int border, caption;
|
||||||
|
|
||||||
|
x = glutGet(GLUT_WINDOW_X);
|
||||||
|
y = glutGet(GLUT_WINDOW_Y);
|
||||||
|
width = glutGet(GLUT_WINDOW_WIDTH);
|
||||||
|
height = glutGet(GLUT_WINDOW_HEIGHT);
|
||||||
|
border = glutGet(GLUT_WINDOW_BORDER_WIDTH);
|
||||||
|
caption = glutGet(GLUT_WINDOW_HEADER_HEIGHT);
|
||||||
|
/* returned position is top-left of client area, to get top-left of
|
||||||
|
* of window you'll need to add the size of the border and caption
|
||||||
|
* of the current window (can be 0).
|
||||||
|
* Note that the window position is not necessarily positive (e.g.
|
||||||
|
* when the window is on a monitor to the left of the primary monitor
|
||||||
|
* or simply when maximized--try pressing the maximize button).
|
||||||
|
* the returned size is the size of the client area
|
||||||
|
* Note that the top-left of a child window is relative to the
|
||||||
|
* top-left of the client area of the parent.
|
||||||
|
*/
|
||||||
|
/* printf("window border: %dpx, caption: %dpx\n",border,caption); */
|
||||||
|
if (win==nWindow)
|
||||||
|
printf("main window %dx%d, top-left of client at: (%d,%d), of window at: (%d,%d)\n",
|
||||||
|
width, height,
|
||||||
|
x ,y,
|
||||||
|
x-border,
|
||||||
|
y-caption);
|
||||||
|
else
|
||||||
|
printf("child window %dx%d, top-left of client at: (%d,%d), relative to parent\n",
|
||||||
|
width, height,
|
||||||
|
x ,y);
|
||||||
|
|
||||||
|
/* (re)set the timer callback and ask glut to call it in 500 ms */
|
||||||
|
glutTimerFunc(500, Timer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int border, caption;
|
||||||
|
glutInit( &argc, argv );
|
||||||
|
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE /*| GLUT_BORDERLESS*/); /* do try as well with GLUT_BORDERLESS and GLUT_CAPTIONLESS */
|
||||||
|
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS);
|
||||||
|
|
||||||
|
/* Get border and caption size of default window style */
|
||||||
|
border = glutGet(GLUT_WINDOW_BORDER_WIDTH);
|
||||||
|
caption = glutGet(GLUT_WINDOW_HEADER_HEIGHT);
|
||||||
|
printf("default window style border: %dpx, caption: %dpx\n",border,caption);
|
||||||
|
|
||||||
|
/* NB: The window position you request is the outer top-left of the
|
||||||
|
* window, the client area is at a different position if the window has
|
||||||
|
* borders and/or a title bar.
|
||||||
|
*/
|
||||||
|
glutInitWindowPosition(150,250);
|
||||||
|
glutInitWindowSize(200,200);
|
||||||
|
|
||||||
|
nWindow = glutCreateWindow("test");
|
||||||
|
glutSetIconTitle("test icon title");
|
||||||
|
printf("main window id: %d\n", nWindow);
|
||||||
|
|
||||||
|
glutKeyboardFunc( SampleKeyboard );
|
||||||
|
glutDisplayFunc( Redisplay );
|
||||||
|
glutReshapeFunc( Reshape );
|
||||||
|
glutPositionFunc( Position );
|
||||||
|
glutWindowStatusFunc( WindowStatus );
|
||||||
|
|
||||||
|
glutTimerFunc(300, Timer, 0);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
printf("glutMainLoop returned\n");
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,219 @@
|
||||||
|
#include <string.h>
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
#include "glmatrix.h"
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.141592653589793
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MMODE_IDX(x) ((x) - GL_MODELVIEW)
|
||||||
|
#define MAT_STACK_SIZE 32
|
||||||
|
#define MAT_IDENT {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
|
||||||
|
|
||||||
|
static int mm_idx = 0;
|
||||||
|
static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}};
|
||||||
|
static int stack_top[3];
|
||||||
|
|
||||||
|
void gl_matrix_mode(int mm)
|
||||||
|
{
|
||||||
|
mm_idx = MMODE_IDX(mm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_push_matrix(void)
|
||||||
|
{
|
||||||
|
int top = stack_top[mm_idx];
|
||||||
|
|
||||||
|
memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float));
|
||||||
|
stack_top[mm_idx]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_pop_matrix(void)
|
||||||
|
{
|
||||||
|
stack_top[mm_idx]--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_load_identity(void)
|
||||||
|
{
|
||||||
|
static const float idmat[] = MAT_IDENT;
|
||||||
|
int top = stack_top[mm_idx];
|
||||||
|
float *mat = mat_stack[mm_idx][top];
|
||||||
|
|
||||||
|
memcpy(mat, idmat, sizeof idmat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_load_matrixf(const float *m)
|
||||||
|
{
|
||||||
|
int top = stack_top[mm_idx];
|
||||||
|
float *mat = mat_stack[mm_idx][top];
|
||||||
|
|
||||||
|
memcpy(mat, m, 16 * sizeof *mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define M4(i, j) ((i << 2) + j)
|
||||||
|
|
||||||
|
void gl_mult_matrixf(const float *m2)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
int top = stack_top[mm_idx];
|
||||||
|
float *m1 = mat_stack[mm_idx][top];
|
||||||
|
float res[16];
|
||||||
|
|
||||||
|
for(i=0; i<4; i++) {
|
||||||
|
for(j=0; j<4; j++) {
|
||||||
|
res[M4(i,j)] = m1[M4(i,0)] * m2[M4(0,j)] +
|
||||||
|
m1[M4(i,1)] * m2[M4(1,j)] +
|
||||||
|
m1[M4(i,2)] * m2[M4(2,j)] +
|
||||||
|
m1[M4(i,3)] * m2[M4(3,j)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(m1, res, sizeof res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_translatef(float x, float y, float z)
|
||||||
|
{
|
||||||
|
float mat[] = MAT_IDENT;
|
||||||
|
|
||||||
|
mat[12] = x;
|
||||||
|
mat[13] = y;
|
||||||
|
mat[14] = z;
|
||||||
|
|
||||||
|
gl_mult_matrixf(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_rotatef(float angle, float x, float y, float z)
|
||||||
|
{
|
||||||
|
float mat[] = MAT_IDENT;
|
||||||
|
|
||||||
|
float angle_rad = (float)M_PI * angle / 180.f;
|
||||||
|
float sina = (float)sin(angle_rad);
|
||||||
|
float cosa = (float)cos(angle_rad);
|
||||||
|
float one_minus_cosa = 1.f - cosa;
|
||||||
|
float nxsq = x * x;
|
||||||
|
float nysq = y * y;
|
||||||
|
float nzsq = z * z;
|
||||||
|
|
||||||
|
mat[0] = nxsq + (1.f - nxsq) * cosa;
|
||||||
|
mat[4] = x * y * one_minus_cosa - z * sina;
|
||||||
|
mat[8] = x * z * one_minus_cosa + y * sina;
|
||||||
|
mat[1] = x * y * one_minus_cosa + z * sina;
|
||||||
|
mat[5] = nysq + (1.f - nysq) * cosa;
|
||||||
|
mat[9] = y * z * one_minus_cosa - x * sina;
|
||||||
|
mat[2] = x * z * one_minus_cosa - y * sina;
|
||||||
|
mat[6] = y * z * one_minus_cosa + x * sina;
|
||||||
|
mat[10] = nzsq + (1.f - nzsq) * cosa;
|
||||||
|
|
||||||
|
gl_mult_matrixf(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_scalef(float x, float y, float z)
|
||||||
|
{
|
||||||
|
float mat[] = MAT_IDENT;
|
||||||
|
|
||||||
|
mat[0] = x;
|
||||||
|
mat[5] = y;
|
||||||
|
mat[10] = z;
|
||||||
|
|
||||||
|
gl_mult_matrixf(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_ortho(float left, float right, float bottom, float top, float znear, float zfar)
|
||||||
|
{
|
||||||
|
float mat[] = MAT_IDENT;
|
||||||
|
|
||||||
|
float dx = right - left;
|
||||||
|
float dy = top - bottom;
|
||||||
|
float dz = zfar - znear;
|
||||||
|
|
||||||
|
float tx = -(right + left) / dx;
|
||||||
|
float ty = -(top + bottom) / dy;
|
||||||
|
float tz = -(zfar + znear) / dz;
|
||||||
|
|
||||||
|
float sx = 2.f / dx;
|
||||||
|
float sy = 2.f / dy;
|
||||||
|
float sz = -2.f / dz;
|
||||||
|
|
||||||
|
mat[0] = sx;
|
||||||
|
mat[5] = sy;
|
||||||
|
mat[10] = sz;
|
||||||
|
mat[12] = tx;
|
||||||
|
mat[13] = ty;
|
||||||
|
mat[14] = tz;
|
||||||
|
|
||||||
|
gl_mult_matrixf(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_frustum(float left, float right, float bottom, float top, float znear, float zfar)
|
||||||
|
{
|
||||||
|
float mat[] = MAT_IDENT;
|
||||||
|
|
||||||
|
float dx = right - left;
|
||||||
|
float dy = top - bottom;
|
||||||
|
float dz = zfar - znear;
|
||||||
|
|
||||||
|
float a = (right + left) / dx;
|
||||||
|
float b = (top + bottom) / dy;
|
||||||
|
float c = -(zfar + znear) / dz;
|
||||||
|
float d = -2.f * zfar * znear / dz;
|
||||||
|
|
||||||
|
mat[0] = 2.f * znear / dx;
|
||||||
|
mat[5] = 2.f * znear / dy;
|
||||||
|
mat[8] = a;
|
||||||
|
mat[9] = b;
|
||||||
|
mat[10] = c;
|
||||||
|
mat[11] = -1.f;
|
||||||
|
mat[14] = d;
|
||||||
|
mat[15] = 0;
|
||||||
|
|
||||||
|
gl_mult_matrixf(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void glu_perspective(float vfov, float aspect, float znear, float zfar)
|
||||||
|
{
|
||||||
|
float vfov_rad = (float)M_PI * vfov / 180.f;
|
||||||
|
float x = znear * (float)tan(vfov_rad / 2.f);
|
||||||
|
gl_frustum(-aspect * x, aspect * x, -x, x, znear, zfar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the matrix (16 elements, 4x4 matrix, row-major order */
|
||||||
|
float* get_matrix(int mm)
|
||||||
|
{
|
||||||
|
int idx = MMODE_IDX(mm);
|
||||||
|
int top = stack_top[idx];
|
||||||
|
return mat_stack[idx][top];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define M3(i, j) ((i * 3) + j)
|
||||||
|
static float inv_transpose_result[9];
|
||||||
|
|
||||||
|
/* return the inverse transpose of the left-upper 3x3 of a matrix
|
||||||
|
The returned pointer is only valid until the next time this function is
|
||||||
|
called, so make a deep copy when you want to keep it around.
|
||||||
|
*/
|
||||||
|
float* get_inv_transpose_3x3(int mm)
|
||||||
|
{
|
||||||
|
int idx = MMODE_IDX(mm);
|
||||||
|
int top = stack_top[idx];
|
||||||
|
float *m1 = mat_stack[idx][top];
|
||||||
|
|
||||||
|
|
||||||
|
float determinant = +m1[M4(0,0)]*(m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)])
|
||||||
|
-m1[M4(0,1)]*(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)])
|
||||||
|
+m1[M4(0,2)]*(m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(1,1)]*m1[M4(2,0)]);
|
||||||
|
|
||||||
|
float invdet = 1/determinant;
|
||||||
|
|
||||||
|
inv_transpose_result[M3(0,0)] = (m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)])*invdet;
|
||||||
|
inv_transpose_result[M3(1,0)] = -(m1[M4(0,1)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,1)])*invdet;
|
||||||
|
inv_transpose_result[M3(2,0)] = (m1[M4(0,1)]*m1[M4(1,2)]-m1[M4(0,2)]*m1[M4(1,1)])*invdet;
|
||||||
|
inv_transpose_result[M3(0,1)] = -(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)])*invdet;
|
||||||
|
inv_transpose_result[M3(1,1)] = (m1[M4(0,0)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,0)])*invdet;
|
||||||
|
inv_transpose_result[M3(2,1)] = -(m1[M4(0,0)]*m1[M4(1,2)]-m1[M4(1,0)]*m1[M4(0,2)])*invdet;
|
||||||
|
inv_transpose_result[M3(0,2)] = (m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(1,1)])*invdet;
|
||||||
|
inv_transpose_result[M3(1,2)] = -(m1[M4(0,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(0,1)])*invdet;
|
||||||
|
inv_transpose_result[M3(2,2)] = (m1[M4(0,0)]*m1[M4(1,1)]-m1[M4(1,0)]*m1[M4(0,1)])*invdet;
|
||||||
|
|
||||||
|
return inv_transpose_result;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef GLMATRIX_H_
|
||||||
|
#define GLMATRIX_H_
|
||||||
|
|
||||||
|
#ifndef GL_MODELVIEW
|
||||||
|
#define GL_MODELVIEW 0x1700
|
||||||
|
#endif
|
||||||
|
#ifndef GL_PROJECTION
|
||||||
|
#define GL_PROJECTION 0x1701
|
||||||
|
#endif
|
||||||
|
#ifndef GL_TEXTURE
|
||||||
|
#define GL_TEXTURE 0x1702
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void gl_matrix_mode(int mmode);
|
||||||
|
void gl_push_matrix(void);
|
||||||
|
void gl_pop_matrix(void);
|
||||||
|
void gl_load_identity(void);
|
||||||
|
void gl_load_matrixf(const float *mat);
|
||||||
|
void gl_mult_matrixf(const float *mat);
|
||||||
|
void gl_translatef(float x, float y, float z);
|
||||||
|
void gl_rotatef(float angle, float x, float y, float z);
|
||||||
|
void gl_scalef(float x, float y, float z);
|
||||||
|
void gl_ortho(float left, float right, float bottom, float top, float znear, float zfar);
|
||||||
|
void gl_frustum(float left, float right, float bottom, float top, float znear, float zfar);
|
||||||
|
void glu_perspective(float vfov, float aspect, float znear, float zfar);
|
||||||
|
|
||||||
|
/* getters */
|
||||||
|
float* get_matrix(int mm);
|
||||||
|
float* get_inv_transpose_3x3(int mm);
|
||||||
|
|
||||||
|
#endif /* GLMATRIX_H_ */
|
|
@ -0,0 +1,946 @@
|
||||||
|
/*! \file shapes.c
|
||||||
|
\ingroup demos
|
||||||
|
|
||||||
|
This program is a test harness for the various shapes
|
||||||
|
in OpenGLUT. It may also be useful to see which
|
||||||
|
parameters control what behavior in the OpenGLUT
|
||||||
|
objects.
|
||||||
|
|
||||||
|
Spinning wireframe and solid-shaded shapes are
|
||||||
|
displayed. Some parameters can be adjusted.
|
||||||
|
|
||||||
|
Keys:
|
||||||
|
- <tt>Esc </tt> Quit
|
||||||
|
- <tt>q Q </tt> Quit
|
||||||
|
- <tt>i I </tt> Show info
|
||||||
|
- <tt>p P </tt> Toggle perspective or orthographic projection
|
||||||
|
- <tt>r R </tt> Toggle fixed or animated rotation around model X-axis
|
||||||
|
- <tt>s S </tt> Toggle toggle fixed function or shader render path
|
||||||
|
- <tt>n N </tt> Toggle visualization of object's normal vectors
|
||||||
|
- <tt>= + </tt> Increase \a slices
|
||||||
|
- <tt>- _ </tt> Decreate \a slices
|
||||||
|
- <tt>, < </tt> Decreate \a stacks
|
||||||
|
- <tt>. > </tt> Increase \a stacks
|
||||||
|
- <tt>9 ( </tt> Decreate \a depth (Sierpinski Sponge)
|
||||||
|
- <tt>0 ) </tt> Increase \a depth (Sierpinski Sponge)
|
||||||
|
- <tt>up </tt> Increase "outer radius"
|
||||||
|
- <tt>down </tt> Decrease "outer radius"
|
||||||
|
- <tt>left </tt> Decrease "inner radius"
|
||||||
|
- <tt>right</tt> Increase "inner radius"
|
||||||
|
- <tt>PgUp </tt> Next shape-drawing function
|
||||||
|
- <tt>PgDn </tt> Prev shape-drawing function
|
||||||
|
|
||||||
|
\author Written by Nigel Stewart November 2003
|
||||||
|
|
||||||
|
\author Portions Copyright (C) 2004, the OpenGLUT project contributors. <br>
|
||||||
|
OpenGLUT branched from freeglut in February, 2004.
|
||||||
|
|
||||||
|
\image html openglut_shapes.png OpenGLUT Geometric Shapes Demonstration
|
||||||
|
\include demos/shapes/shapes.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "glmatrix.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAKS */
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* report GL errors, if any, to stderr */
|
||||||
|
void checkError(const char *functionName)
|
||||||
|
{
|
||||||
|
GLenum error;
|
||||||
|
while (( error = glGetError() ) != GL_NO_ERROR) {
|
||||||
|
fprintf (stderr, "GL error 0x%X detected in %s\n", error, functionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OpenGL 2+ shader mode needs some function and macro definitions,
|
||||||
|
* avoiding a dependency on additional libraries like GLEW or the
|
||||||
|
* GL/glext.h header
|
||||||
|
*/
|
||||||
|
#ifndef GL_FRAGMENT_SHADER
|
||||||
|
#define GL_FRAGMENT_SHADER 0x8B30
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_VERTEX_SHADER
|
||||||
|
#define GL_VERTEX_SHADER 0x8B31
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_COMPILE_STATUS
|
||||||
|
#define GL_COMPILE_STATUS 0x8B81
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_LINK_STATUS
|
||||||
|
#define GL_LINK_STATUS 0x8B82
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_INFO_LOG_LENGTH
|
||||||
|
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef ptrdiff_t ourGLsizeiptr;
|
||||||
|
typedef char ourGLchar;
|
||||||
|
|
||||||
|
#ifndef APIENTRY
|
||||||
|
#define APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_VERSION_2_0
|
||||||
|
typedef GLuint (APIENTRY *PFNGLCREATESHADERPROC) (GLenum type);
|
||||||
|
typedef void (APIENTRY *PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const ourGLchar **string, const GLint *length);
|
||||||
|
typedef void (APIENTRY *PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||||
|
typedef GLuint (APIENTRY *PFNGLCREATEPROGRAMPROC) (void);
|
||||||
|
typedef void (APIENTRY *PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||||
|
typedef void (APIENTRY *PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||||
|
typedef void (APIENTRY *PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||||
|
typedef void (APIENTRY *PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||||
|
typedef void (APIENTRY *PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog);
|
||||||
|
typedef void (APIENTRY *PFNGLGETPROGRAMIVPROC) (GLenum target, GLenum pname, GLint *params);
|
||||||
|
typedef void (APIENTRY *PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog);
|
||||||
|
typedef GLint (APIENTRY *PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const ourGLchar *name);
|
||||||
|
typedef GLint (APIENTRY *PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const ourGLchar *name);
|
||||||
|
typedef void (APIENTRY *PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||||
|
typedef void (APIENTRY *PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PFNGLCREATESHADERPROC gl_CreateShader;
|
||||||
|
PFNGLSHADERSOURCEPROC gl_ShaderSource;
|
||||||
|
PFNGLCOMPILESHADERPROC gl_CompileShader;
|
||||||
|
PFNGLCREATEPROGRAMPROC gl_CreateProgram;
|
||||||
|
PFNGLATTACHSHADERPROC gl_AttachShader;
|
||||||
|
PFNGLLINKPROGRAMPROC gl_LinkProgram;
|
||||||
|
PFNGLUSEPROGRAMPROC gl_UseProgram;
|
||||||
|
PFNGLGETSHADERIVPROC gl_GetShaderiv;
|
||||||
|
PFNGLGETSHADERINFOLOGPROC gl_GetShaderInfoLog;
|
||||||
|
PFNGLGETPROGRAMIVPROC gl_GetProgramiv;
|
||||||
|
PFNGLGETPROGRAMINFOLOGPROC gl_GetProgramInfoLog;
|
||||||
|
PFNGLGETATTRIBLOCATIONPROC gl_GetAttribLocation;
|
||||||
|
PFNGLGETUNIFORMLOCATIONPROC gl_GetUniformLocation;
|
||||||
|
PFNGLUNIFORMMATRIX4FVPROC gl_UniformMatrix4fv;
|
||||||
|
PFNGLUNIFORMMATRIX3FVPROC gl_UniformMatrix3fv;
|
||||||
|
|
||||||
|
void initExtensionEntries(void)
|
||||||
|
{
|
||||||
|
gl_CreateShader = (PFNGLCREATESHADERPROC) glutGetProcAddress ("glCreateShader");
|
||||||
|
gl_ShaderSource = (PFNGLSHADERSOURCEPROC) glutGetProcAddress ("glShaderSource");
|
||||||
|
gl_CompileShader = (PFNGLCOMPILESHADERPROC) glutGetProcAddress ("glCompileShader");
|
||||||
|
gl_CreateProgram = (PFNGLCREATEPROGRAMPROC) glutGetProcAddress ("glCreateProgram");
|
||||||
|
gl_AttachShader = (PFNGLATTACHSHADERPROC) glutGetProcAddress ("glAttachShader");
|
||||||
|
gl_LinkProgram = (PFNGLLINKPROGRAMPROC) glutGetProcAddress ("glLinkProgram");
|
||||||
|
gl_UseProgram = (PFNGLUSEPROGRAMPROC) glutGetProcAddress ("glUseProgram");
|
||||||
|
gl_GetShaderiv = (PFNGLGETSHADERIVPROC) glutGetProcAddress ("glGetShaderiv");
|
||||||
|
gl_GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) glutGetProcAddress ("glGetShaderInfoLog");
|
||||||
|
gl_GetProgramiv = (PFNGLGETPROGRAMIVPROC) glutGetProcAddress ("glGetProgramiv");
|
||||||
|
gl_GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) glutGetProcAddress ("glGetProgramInfoLog");
|
||||||
|
gl_GetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) glutGetProcAddress ("glGetAttribLocation");
|
||||||
|
gl_GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) glutGetProcAddress ("glGetUniformLocation");
|
||||||
|
gl_UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) glutGetProcAddress ("glUniformMatrix4fv");
|
||||||
|
gl_UniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) glutGetProcAddress ("glUniformMatrix3fv");
|
||||||
|
if (!gl_CreateShader || !gl_ShaderSource || !gl_CompileShader || !gl_CreateProgram || !gl_AttachShader || !gl_LinkProgram || !gl_UseProgram || !gl_GetShaderiv || !gl_GetShaderInfoLog || !gl_GetProgramiv || !gl_GetProgramInfoLog || !gl_GetAttribLocation || !gl_GetUniformLocation || !gl_UniformMatrix4fv || !gl_UniformMatrix3fv)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "glCreateShader, glShaderSource, glCompileShader, glCreateProgram, glAttachShader, glLinkProgram, glUseProgram, glGetShaderiv, glGetShaderInfoLog, glGetProgramiv, glGetProgramInfoLog, glGetAttribLocation, glGetUniformLocation, glUniformMatrix4fv or gl_UniformMatrix3fv not found");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ourGLchar *vertexShaderSource[] = {
|
||||||
|
"/**",
|
||||||
|
" * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Smooth_Specular_Highlights",
|
||||||
|
" * This file is in the public domain.",
|
||||||
|
" * Contributors: Sylvain Beucler",
|
||||||
|
" */",
|
||||||
|
"attribute vec3 fg_coord;",
|
||||||
|
"attribute vec3 fg_normal;",
|
||||||
|
"varying vec4 position; /* position of the vertex (and fragment) in world space */",
|
||||||
|
"varying vec3 varyingNormalDirection; /* surface normal vector in world space */",
|
||||||
|
"uniform mat4 m, p; /* don't need v, as always identity in our demo */",
|
||||||
|
"uniform mat3 m_3x3_inv_transp;",
|
||||||
|
" ",
|
||||||
|
"void main()",
|
||||||
|
"{",
|
||||||
|
" vec4 fg_coord4 = vec4(fg_coord, 1.0);",
|
||||||
|
" position = m * fg_coord4;",
|
||||||
|
" varyingNormalDirection = normalize(m_3x3_inv_transp * fg_normal);",
|
||||||
|
" ",
|
||||||
|
" mat4 mvp = p*m; /* normally p*v*m */",
|
||||||
|
" gl_Position = mvp * fg_coord4;",
|
||||||
|
"}"
|
||||||
|
};
|
||||||
|
|
||||||
|
const ourGLchar *fragmentShaderSource[] = {
|
||||||
|
"/**",
|
||||||
|
" * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Smooth_Specular_Highlights",
|
||||||
|
" * This file is in the public domain.",
|
||||||
|
" * Contributors: Martin Kraus, Sylvain Beucler",
|
||||||
|
" */",
|
||||||
|
"varying vec4 position; /* position of the vertex (and fragment) in world space */",
|
||||||
|
"varying vec3 varyingNormalDirection; /* surface normal vector in world space */",
|
||||||
|
"/* uniform mat4 v_inv; // in this demo, the view matrix is always an identity matrix */",
|
||||||
|
" ",
|
||||||
|
"struct lightSource",
|
||||||
|
"{",
|
||||||
|
" vec4 position;",
|
||||||
|
" vec4 diffuse;",
|
||||||
|
" vec4 specular;",
|
||||||
|
" float constantAttenuation, linearAttenuation, quadraticAttenuation;",
|
||||||
|
" float spotCutoff, spotExponent;",
|
||||||
|
" vec3 spotDirection;",
|
||||||
|
"};",
|
||||||
|
"lightSource light0 = lightSource(",
|
||||||
|
" vec4(2.0, 5.0, 5.0, 0.0),",
|
||||||
|
" vec4(1.0, 1.0, 1.0, 1.0),",
|
||||||
|
" vec4(1.0, 1.0, 1.0, 1.0),",
|
||||||
|
" 0.0, 1.0, 0.0,",
|
||||||
|
" 180.0, 0.0,",
|
||||||
|
" vec3(0.0, 0.0, 0.0)",
|
||||||
|
");",
|
||||||
|
"vec4 scene_ambient = vec4(0.2, 0.2, 0.2, 1.0);",
|
||||||
|
" ",
|
||||||
|
"struct material",
|
||||||
|
"{",
|
||||||
|
" vec4 ambient;",
|
||||||
|
" vec4 diffuse;",
|
||||||
|
" vec4 specular;",
|
||||||
|
" float shininess;",
|
||||||
|
"};",
|
||||||
|
"material frontMaterial = material(",
|
||||||
|
" vec4(1.0, 0.0, 0.0, 1.0),",
|
||||||
|
" vec4(1.0, 0.0, 0.0, 1.0),",
|
||||||
|
" vec4(1.0, 1.0, 1.0, 1.0),",
|
||||||
|
" 100.0",
|
||||||
|
");",
|
||||||
|
" ",
|
||||||
|
"void main()",
|
||||||
|
"{",
|
||||||
|
" vec3 normalDirection = normalize(varyingNormalDirection);",
|
||||||
|
" /* vec3 viewDirection = normalize(vec3(v_inv * vec4(0.0, 0.0, 0.0, 1.0) - position)); */",
|
||||||
|
" vec3 viewDirection = normalize(vec3(vec4(0.0, 0.0, 0.0, 1.0) - position)); /* in this demo, the view matrix is always an identity matrix */",
|
||||||
|
" vec3 lightDirection;",
|
||||||
|
" float attenuation;",
|
||||||
|
" ",
|
||||||
|
" if (0.0 == light0.position.w) /* directional light? */",
|
||||||
|
" {",
|
||||||
|
" attenuation = 1.0; /* no attenuation */",
|
||||||
|
" lightDirection = normalize(vec3(light0.position));",
|
||||||
|
" } ",
|
||||||
|
" else /* point light or spotlight (or other kind of light) */",
|
||||||
|
" {",
|
||||||
|
" vec3 positionToLightSource = vec3(light0.position - position);",
|
||||||
|
" float distance = length(positionToLightSource);",
|
||||||
|
" lightDirection = normalize(positionToLightSource);",
|
||||||
|
" attenuation = 1.0 / (light0.constantAttenuation",
|
||||||
|
" + light0.linearAttenuation * distance",
|
||||||
|
" + light0.quadraticAttenuation * distance * distance);",
|
||||||
|
" ",
|
||||||
|
" if (light0.spotCutoff <= 90.0) /* spotlight? */",
|
||||||
|
" {",
|
||||||
|
" float clampedCosine = max(0.0, dot(-lightDirection, light0.spotDirection));",
|
||||||
|
" if (clampedCosine < cos(radians(light0.spotCutoff))) /* outside of spotlight cone? */",
|
||||||
|
" {",
|
||||||
|
" attenuation = 0.0;",
|
||||||
|
" }",
|
||||||
|
" else",
|
||||||
|
" {",
|
||||||
|
" attenuation = attenuation * pow(clampedCosine, light0.spotExponent); ",
|
||||||
|
" }",
|
||||||
|
" }",
|
||||||
|
" }",
|
||||||
|
" ",
|
||||||
|
" vec3 ambientLighting = vec3(scene_ambient) * vec3(frontMaterial.ambient);",
|
||||||
|
" ",
|
||||||
|
" vec3 diffuseReflection = attenuation ",
|
||||||
|
" * vec3(light0.diffuse) * vec3(frontMaterial.diffuse)",
|
||||||
|
" * max(0.0, dot(normalDirection, lightDirection));",
|
||||||
|
" ",
|
||||||
|
" vec3 specularReflection;",
|
||||||
|
" if (dot(normalDirection, lightDirection) < 0.0) /* light source on the wrong side? */",
|
||||||
|
" {",
|
||||||
|
" specularReflection = vec3(0.0, 0.0, 0.0); /* no specular reflection */",
|
||||||
|
" }",
|
||||||
|
" else /* light source on the right side */",
|
||||||
|
" {",
|
||||||
|
" specularReflection = attenuation * vec3(light0.specular) * vec3(frontMaterial.specular) ",
|
||||||
|
" * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), frontMaterial.shininess);",
|
||||||
|
" }",
|
||||||
|
" ",
|
||||||
|
" gl_FragColor = vec4(ambientLighting + diffuseReflection + specularReflection, 1.0);",
|
||||||
|
"}"
|
||||||
|
};
|
||||||
|
|
||||||
|
GLint getAttribOrUniformLocation(const char* name, GLuint program, GLboolean isAttrib)
|
||||||
|
{
|
||||||
|
if (isAttrib)
|
||||||
|
{
|
||||||
|
GLint attrib = gl_GetAttribLocation(program, name);
|
||||||
|
if (attrib == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Warning: Could not bind attrib %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkError ("getAttribOrUniformLocation");
|
||||||
|
return attrib;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLint uniform = gl_GetUniformLocation(program, name);
|
||||||
|
if (uniform == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Warning: Could not bind uniform %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkError ("getAttribOrUniformLocation");
|
||||||
|
return uniform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint program;
|
||||||
|
GLint attribute_fg_coord = -1, attribute_fg_normal = -1;
|
||||||
|
GLint uniform_m = -1, uniform_p = -1, uniform_m_3x3_inv_transp = -1;
|
||||||
|
GLint shaderReady = 0; /* Set to 1 when all initialization went well, to -1 when shader somehow unusable. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void compileAndCheck(GLuint shader)
|
||||||
|
{
|
||||||
|
GLint status;
|
||||||
|
gl_CompileShader (shader);
|
||||||
|
gl_GetShaderiv (shader, GL_COMPILE_STATUS, &status);
|
||||||
|
if (status == GL_FALSE) {
|
||||||
|
GLint infoLogLength;
|
||||||
|
ourGLchar *infoLog;
|
||||||
|
gl_GetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
infoLog = (ourGLchar*) malloc (infoLogLength);
|
||||||
|
gl_GetShaderInfoLog (shader, infoLogLength, NULL, infoLog);
|
||||||
|
fprintf (stderr, "compile log: %s\n", infoLog);
|
||||||
|
free (infoLog);
|
||||||
|
}
|
||||||
|
checkError ("compileAndCheck");
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint compileShaderSource(GLenum type, GLsizei count, const ourGLchar **string)
|
||||||
|
{
|
||||||
|
GLuint shader = gl_CreateShader (type);
|
||||||
|
gl_ShaderSource (shader, count, string, NULL);
|
||||||
|
|
||||||
|
checkError ("compileShaderSource");
|
||||||
|
|
||||||
|
compileAndCheck (shader);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linkAndCheck(GLuint program)
|
||||||
|
{
|
||||||
|
GLint status;
|
||||||
|
gl_LinkProgram (program);
|
||||||
|
gl_GetProgramiv (program, GL_LINK_STATUS, &status);
|
||||||
|
if (status == GL_FALSE) {
|
||||||
|
GLint infoLogLength;
|
||||||
|
ourGLchar *infoLog;
|
||||||
|
gl_GetProgramiv (program, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
infoLog = (ourGLchar*) malloc (infoLogLength);
|
||||||
|
gl_GetProgramInfoLog (program, infoLogLength, NULL, infoLog);
|
||||||
|
fprintf (stderr, "link log: %s\n", infoLog);
|
||||||
|
free (infoLog);
|
||||||
|
}
|
||||||
|
checkError ("linkAndCheck");
|
||||||
|
}
|
||||||
|
|
||||||
|
void createProgram(GLuint vertexShader, GLuint fragmentShader)
|
||||||
|
{
|
||||||
|
program = gl_CreateProgram ();
|
||||||
|
if (vertexShader != 0) {
|
||||||
|
gl_AttachShader (program, vertexShader);
|
||||||
|
}
|
||||||
|
if (fragmentShader != 0) {
|
||||||
|
gl_AttachShader (program, fragmentShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkError ("createProgram");
|
||||||
|
|
||||||
|
linkAndCheck (program);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initShader(void)
|
||||||
|
{
|
||||||
|
const GLsizei vertexShaderLines = sizeof(vertexShaderSource) / sizeof(ourGLchar*);
|
||||||
|
GLuint vertexShader =
|
||||||
|
compileShaderSource (GL_VERTEX_SHADER, vertexShaderLines, vertexShaderSource);
|
||||||
|
|
||||||
|
const GLsizei fragmentShaderLines = sizeof(fragmentShaderSource) / sizeof(ourGLchar*);
|
||||||
|
GLuint fragmentShader =
|
||||||
|
compileShaderSource (GL_FRAGMENT_SHADER, fragmentShaderLines, fragmentShaderSource);
|
||||||
|
|
||||||
|
checkError ("initShader - 1");
|
||||||
|
|
||||||
|
createProgram (vertexShader, fragmentShader);
|
||||||
|
|
||||||
|
gl_UseProgram (program);
|
||||||
|
|
||||||
|
attribute_fg_coord = getAttribOrUniformLocation("fg_coord" , program, GL_TRUE);
|
||||||
|
attribute_fg_normal = getAttribOrUniformLocation("fg_normal" , program, GL_TRUE);
|
||||||
|
uniform_m = getAttribOrUniformLocation("m" , program, GL_FALSE);
|
||||||
|
uniform_p = getAttribOrUniformLocation("p" , program, GL_FALSE);
|
||||||
|
uniform_m_3x3_inv_transp= getAttribOrUniformLocation("m_3x3_inv_transp" , program, GL_FALSE);
|
||||||
|
|
||||||
|
gl_UseProgram (0);
|
||||||
|
|
||||||
|
if (attribute_fg_coord==-1 || attribute_fg_normal==-1 ||
|
||||||
|
uniform_m==-1 || uniform_p==-1 || uniform_m_3x3_inv_transp==-1)
|
||||||
|
shaderReady = -1;
|
||||||
|
else
|
||||||
|
shaderReady = 1;
|
||||||
|
|
||||||
|
checkError ("initShader - 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This macro is only intended to be used on arrays, of course.
|
||||||
|
*/
|
||||||
|
#define NUMBEROF(x) ((sizeof(x))/(sizeof(x[0])))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These global variables control which object is drawn,
|
||||||
|
* and how it is drawn. No object uses all of these
|
||||||
|
* variables.
|
||||||
|
*/
|
||||||
|
static int function_index;
|
||||||
|
static int slices = 16;
|
||||||
|
static int stacks = 16;
|
||||||
|
static double irad = .25;
|
||||||
|
static double orad = 1.0; /* doubles as size for objects other than Torus */
|
||||||
|
static int depth = 4;
|
||||||
|
static double offset[ 3 ] = { 0, 0, 0 };
|
||||||
|
static GLboolean show_info = GL_TRUE;
|
||||||
|
static float ar;
|
||||||
|
static GLboolean persProject = GL_TRUE;
|
||||||
|
static GLboolean animateXRot = GL_FALSE;
|
||||||
|
static GLboolean useShader = GL_FALSE;
|
||||||
|
static GLboolean visNormals = GL_FALSE;
|
||||||
|
static GLboolean flat;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enum to tell drawSizeInfo what to draw for each object
|
||||||
|
*/
|
||||||
|
#define GEO_NO_SIZE 0
|
||||||
|
#define GEO_SIZE 1
|
||||||
|
#define GEO_SCALE 2
|
||||||
|
#define GEO_INNER_OUTER_RAD 4
|
||||||
|
#define GEO_RAD 8
|
||||||
|
#define GEO_BASE_HEIGHT 16
|
||||||
|
#define GEO_RAD_HEIGHT 32
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These one-liners draw particular objects, fetching appropriate
|
||||||
|
* information from the above globals. They are just thin wrappers
|
||||||
|
* for the FreeGLUT objects.
|
||||||
|
*/
|
||||||
|
static void drawSolidTetrahedron(void) { glutSolidTetrahedron (); }
|
||||||
|
static void drawWireTetrahedron(void) { glutWireTetrahedron (); }
|
||||||
|
static void drawSolidCube(void) { glutSolidCube(orad); } /* orad doubles as size input */
|
||||||
|
static void drawWireCube(void) { glutWireCube(orad); } /* orad doubles as size input */
|
||||||
|
static void drawSolidOctahedron(void) { glutSolidOctahedron (); }
|
||||||
|
static void drawWireOctahedron(void) { glutWireOctahedron (); }
|
||||||
|
static void drawSolidDodecahedron(void) { glutSolidDodecahedron (); }
|
||||||
|
static void drawWireDodecahedron(void) { glutWireDodecahedron (); }
|
||||||
|
static void drawSolidRhombicDodecahedron(void) { glutSolidRhombicDodecahedron (); }
|
||||||
|
static void drawWireRhombicDodecahedron(void) { glutWireRhombicDodecahedron (); }
|
||||||
|
static void drawSolidIcosahedron(void) { glutSolidIcosahedron (); }
|
||||||
|
static void drawWireIcosahedron(void) { glutWireIcosahedron (); }
|
||||||
|
static void drawSolidSierpinskiSponge(void) { glutSolidSierpinskiSponge (depth, offset, orad);} /* orad doubles as size input */
|
||||||
|
static void drawWireSierpinskiSponge(void) { glutWireSierpinskiSponge (depth, offset, orad); } /* orad doubles as size input */
|
||||||
|
static void drawSolidTorus(void) { glutSolidTorus(irad,orad,slices,stacks); }
|
||||||
|
static void drawWireTorus(void) { glutWireTorus (irad,orad,slices,stacks); }
|
||||||
|
static void drawSolidSphere(void) { glutSolidSphere(orad,slices,stacks); } /* orad doubles as size input */
|
||||||
|
static void drawWireSphere(void) { glutWireSphere(orad,slices,stacks); } /* orad doubles as size input */
|
||||||
|
static void drawSolidCone(void) { glutSolidCone(irad,orad,slices,stacks); } /* irad doubles as base input, and orad as height input */
|
||||||
|
static void drawWireCone(void) { glutWireCone(irad,orad,slices,stacks); } /* irad doubles as base input, and orad as height input */
|
||||||
|
static void drawSolidCylinder(void) { glutSolidCylinder(irad,orad,slices,stacks); } /* irad doubles as radius input, and orad as height input */
|
||||||
|
static void drawWireCylinder(void) { glutWireCylinder(irad,orad,slices,stacks); } /* irad doubles as radius input, and orad as height input */
|
||||||
|
/* per Glut manpage, it should be noted that the teapot is rendered
|
||||||
|
* with clockwise winding for front facing polygons...
|
||||||
|
* Same for the teacup and teaspoon
|
||||||
|
*/
|
||||||
|
static void drawSolidTeapot(void)
|
||||||
|
{ glFrontFace(GL_CW); glutSolidTeapot(orad); glFrontFace(GL_CCW); /* orad doubles as size input */}
|
||||||
|
static void drawWireTeapot(void)
|
||||||
|
{ glFrontFace(GL_CW); glutWireTeapot(orad); glFrontFace(GL_CCW); /* orad doubles as size input */}
|
||||||
|
static void drawSolidTeacup(void)
|
||||||
|
{ glFrontFace(GL_CW); glutSolidTeacup(orad); glFrontFace(GL_CCW); /* orad doubles as size input */}
|
||||||
|
static void drawWireTeacup(void)
|
||||||
|
{ glFrontFace(GL_CW); glutWireTeacup(orad); glFrontFace(GL_CCW); /* orad doubles as size input */}
|
||||||
|
static void drawSolidTeaspoon(void)
|
||||||
|
{ glFrontFace(GL_CW); glutSolidTeaspoon(orad); glFrontFace(GL_CCW); /* orad doubles as size input */}
|
||||||
|
static void drawWireTeaspoon(void)
|
||||||
|
{ glFrontFace(GL_CW); glutWireTeaspoon(orad); glFrontFace(GL_CCW); /* orad doubles as size input */}
|
||||||
|
|
||||||
|
#define RADIUSFAC 0.70710678118654752440084436210485f
|
||||||
|
|
||||||
|
static void drawSolidCuboctahedron(void)
|
||||||
|
{
|
||||||
|
GLfloat radius = RADIUSFAC*(GLfloat)orad; /* orad doubles as size */
|
||||||
|
glBegin( GL_TRIANGLES );
|
||||||
|
glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( radius, radius, 0.0 ); glVertex3d( 0.0, radius, radius ); glVertex3d( radius, 0.0, radius );
|
||||||
|
glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( radius, radius, 0.0 ); glVertex3d( radius, 0.0,-radius ); glVertex3d( 0.0, radius,-radius );
|
||||||
|
glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( radius,-radius, 0.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( 0.0,-radius, radius );
|
||||||
|
glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( radius,-radius, 0.0 ); glVertex3d( 0.0,-radius,-radius ); glVertex3d( radius, 0.0,-radius );
|
||||||
|
glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-radius, radius, 0.0 ); glVertex3d(-radius, 0.0, radius ); glVertex3d( 0.0, radius, radius );
|
||||||
|
glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-radius, radius, 0.0 ); glVertex3d( 0.0, radius,-radius ); glVertex3d(-radius, 0.0,-radius );
|
||||||
|
glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-radius,-radius, 0.0 ); glVertex3d( 0.0,-radius, radius ); glVertex3d(-radius, 0.0, radius );
|
||||||
|
glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-radius,-radius, 0.0 ); glVertex3d(-radius, 0.0,-radius ); glVertex3d( 0.0,-radius,-radius );
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glBegin( GL_QUADS );
|
||||||
|
glNormal3d( 1.0, 0.0, 0.0 ); glVertex3d( radius, radius, 0.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( radius,-radius, 0.0 ); glVertex3d( radius, 0.0,-radius );
|
||||||
|
glNormal3d(-1.0, 0.0, 0.0 ); glVertex3d(-radius, radius, 0.0 ); glVertex3d(-radius, 0.0,-radius ); glVertex3d(-radius,-radius, 0.0 ); glVertex3d(-radius, 0.0, radius );
|
||||||
|
glNormal3d( 0.0, 1.0, 0.0 ); glVertex3d( radius, radius, 0.0 ); glVertex3d( 0.0, radius,-radius ); glVertex3d(-radius, radius, 0.0 ); glVertex3d( 0.0, radius, radius );
|
||||||
|
glNormal3d( 0.0,-1.0, 0.0 ); glVertex3d( radius,-radius, 0.0 ); glVertex3d( 0.0,-radius, radius ); glVertex3d(-radius,-radius, 0.0 ); glVertex3d( 0.0,-radius,-radius );
|
||||||
|
glNormal3d( 0.0, 0.0, 1.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( 0.0, radius, radius ); glVertex3d(-radius, 0.0, radius ); glVertex3d( 0.0,-radius, radius );
|
||||||
|
glNormal3d( 0.0, 0.0,-1.0 ); glVertex3d( radius, 0.0,-radius ); glVertex3d( 0.0,-radius,-radius ); glVertex3d(-radius, 0.0,-radius ); glVertex3d( 0.0, radius,-radius );
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawWireCuboctahedron(void)
|
||||||
|
{
|
||||||
|
GLfloat radius = RADIUSFAC*(GLfloat)orad; /* orad doubles as size */
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glNormal3d( 1.0, 0.0, 0.0 ); glVertex3d( radius, radius, 0.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( radius,-radius, 0.0 ); glVertex3d( radius, 0.0,-radius );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glNormal3d(-1.0, 0.0, 0.0 ); glVertex3d(-radius, radius, 0.0 ); glVertex3d(-radius, 0.0,-radius ); glVertex3d(-radius,-radius, 0.0 ); glVertex3d(-radius, 0.0, radius );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glNormal3d( 0.0, 1.0, 0.0 ); glVertex3d( radius, radius, 0.0 ); glVertex3d( 0.0, radius,-radius ); glVertex3d(-radius, radius, 0.0 ); glVertex3d( 0.0, radius, radius );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glNormal3d( 0.0,-1.0, 0.0 ); glVertex3d( radius,-radius, 0.0 ); glVertex3d( 0.0,-radius, radius ); glVertex3d(-radius,-radius, 0.0 ); glVertex3d( 0.0,-radius,-radius );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glNormal3d( 0.0, 0.0, 1.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( 0.0, radius, radius ); glVertex3d(-radius, 0.0, radius ); glVertex3d( 0.0,-radius, radius );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glNormal3d( 0.0, 0.0,-1.0 ); glVertex3d( radius, 0.0,-radius ); glVertex3d( 0.0,-radius,-radius ); glVertex3d(-radius, 0.0,-radius ); glVertex3d( 0.0, radius,-radius );
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef RADIUSFAC
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure defines an entry in our function-table.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char * const name;
|
||||||
|
void (*solid) (void);
|
||||||
|
void (*wire) (void);
|
||||||
|
int drawSizeInfoFlag;
|
||||||
|
} entry;
|
||||||
|
|
||||||
|
#define ENTRY(e,f) {#e, drawSolid##e, drawWire##e,f}
|
||||||
|
static const entry table [] =
|
||||||
|
{
|
||||||
|
ENTRY (Tetrahedron,GEO_NO_SIZE),
|
||||||
|
ENTRY (Cube,GEO_SIZE),
|
||||||
|
ENTRY (Octahedron,GEO_NO_SIZE),
|
||||||
|
ENTRY (Dodecahedron,GEO_NO_SIZE),
|
||||||
|
ENTRY (RhombicDodecahedron,GEO_NO_SIZE),
|
||||||
|
ENTRY (Icosahedron,GEO_NO_SIZE),
|
||||||
|
ENTRY (SierpinskiSponge,GEO_SCALE),
|
||||||
|
ENTRY (Teapot,GEO_SIZE),
|
||||||
|
ENTRY (Teacup,GEO_SIZE),
|
||||||
|
ENTRY (Teaspoon,GEO_SIZE),
|
||||||
|
ENTRY (Torus,GEO_INNER_OUTER_RAD),
|
||||||
|
ENTRY (Sphere,GEO_RAD),
|
||||||
|
ENTRY (Cone,GEO_BASE_HEIGHT),
|
||||||
|
ENTRY (Cylinder,GEO_RAD_HEIGHT),
|
||||||
|
ENTRY (Cuboctahedron,GEO_SIZE) /* This one doesn't work when in shader mode and is then skipped */
|
||||||
|
};
|
||||||
|
#undef ENTRY
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Does printf()-like work using freeglut
|
||||||
|
glutBitmapString(). Uses a fixed font. Prints
|
||||||
|
at the indicated row/column position.
|
||||||
|
|
||||||
|
Limitation: Cannot address pixels.
|
||||||
|
Limitation: Renders in screen coords, not model coords.
|
||||||
|
*/
|
||||||
|
static void shapesPrintf (int row, int col, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
static char buf[256];
|
||||||
|
int viewport[4];
|
||||||
|
void *font = GLUT_BITMAP_9_BY_15;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||||
|
(void) _vsnprintf (buf, sizeof(buf), fmt, args);
|
||||||
|
#else
|
||||||
|
(void) vsnprintf (buf, sizeof(buf), fmt, args);
|
||||||
|
#endif
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
glGetIntegerv(GL_VIEWPORT,viewport);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glOrtho(0,viewport[2],0,viewport[3],-1,1);
|
||||||
|
|
||||||
|
glRasterPos2i
|
||||||
|
(
|
||||||
|
glutBitmapWidth(font, ' ') * col,
|
||||||
|
- glutBitmapHeight(font) * row + viewport[3]
|
||||||
|
);
|
||||||
|
glutBitmapString (font, (unsigned char*)buf);
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print info about the about the current shape and render state on the screen */
|
||||||
|
static void DrawSizeInfo(int *row)
|
||||||
|
{
|
||||||
|
switch (table [function_index].drawSizeInfoFlag)
|
||||||
|
{
|
||||||
|
case GEO_NO_SIZE:
|
||||||
|
break;
|
||||||
|
case GEO_SIZE:
|
||||||
|
shapesPrintf ((*row)++, 1, "Size Up Down : %f", orad);
|
||||||
|
break;
|
||||||
|
case GEO_SCALE:
|
||||||
|
shapesPrintf ((*row)++, 1, "Scale Up Down : %f", orad);
|
||||||
|
break;
|
||||||
|
case GEO_INNER_OUTER_RAD:
|
||||||
|
shapesPrintf ((*row)++, 1, "Inner radius Left Right: %f", irad);
|
||||||
|
shapesPrintf ((*row)++, 1, "Outer radius Up Down : %f", orad);
|
||||||
|
break;
|
||||||
|
case GEO_RAD:
|
||||||
|
shapesPrintf ((*row)++, 1, "Radius Up Down : %f", orad);
|
||||||
|
break;
|
||||||
|
case GEO_BASE_HEIGHT:
|
||||||
|
shapesPrintf ((*row)++, 1, "Base Left Right: %f", irad);
|
||||||
|
shapesPrintf ((*row)++, 1, "Height Up Down : %f", orad);
|
||||||
|
break;
|
||||||
|
case GEO_RAD_HEIGHT:
|
||||||
|
shapesPrintf ((*row)++, 1, "Radius Left Right: %f", irad);
|
||||||
|
shapesPrintf ((*row)++, 1, "Height Up Down : %f", orad);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawInfo()
|
||||||
|
{
|
||||||
|
int row = 1;
|
||||||
|
shapesPrintf (row++, 1, "Shape PgUp PgDn: %s", table [function_index].name);
|
||||||
|
shapesPrintf (row++, 1, "Slices +-: %d Stacks <>: %d", slices, stacks);
|
||||||
|
shapesPrintf (row++, 1, "nSides +-: %d nRings <>: %d", slices, stacks);
|
||||||
|
shapesPrintf (row++, 1, "Depth (): %d", depth);
|
||||||
|
DrawSizeInfo(&row);
|
||||||
|
if (persProject)
|
||||||
|
shapesPrintf (row++, 1, "Perspective projection (p)");
|
||||||
|
else
|
||||||
|
shapesPrintf (row++, 1, "Orthographic projection (p)");
|
||||||
|
if (useShader) {
|
||||||
|
shapesPrintf (row++, 1, "Using shader (s)");
|
||||||
|
} else {
|
||||||
|
shapesPrintf (row++, 1, "Using fixed function pipeline (s)");
|
||||||
|
if (flat)
|
||||||
|
shapesPrintf (row++, 1, "Flat shading (f)");
|
||||||
|
else
|
||||||
|
shapesPrintf (row++, 1, "Smooth shading (f)");
|
||||||
|
}
|
||||||
|
if (animateXRot)
|
||||||
|
shapesPrintf (row++, 1, "2D rotation (r)");
|
||||||
|
else
|
||||||
|
shapesPrintf (row++, 1, "1D rotation (r)");
|
||||||
|
shapesPrintf (row++, 1, "visualizing normals: %i (n)",visNormals);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GLUT callback Handlers */
|
||||||
|
static void
|
||||||
|
resize(int width, int height)
|
||||||
|
{
|
||||||
|
ar = (float) width / (float) height;
|
||||||
|
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display(void)
|
||||||
|
{
|
||||||
|
const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
|
||||||
|
const double a = t*89.0;
|
||||||
|
const double b = (animateXRot?t:1)*67.0;
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glutSetOption(GLUT_GEOMETRY_VISUALIZE_NORMALS,visNormals); /* Normals visualized or not? */
|
||||||
|
|
||||||
|
glShadeModel(flat ? GL_FLAT : GL_SMOOTH); /* flat or gouraud shading */
|
||||||
|
|
||||||
|
if (useShader && !shaderReady)
|
||||||
|
initShader();
|
||||||
|
|
||||||
|
if (useShader && shaderReady)
|
||||||
|
{
|
||||||
|
/* setup use of shader (and vertex buffer by FreeGLUT) */
|
||||||
|
gl_UseProgram (program);
|
||||||
|
glutSetVertexAttribCoord3(attribute_fg_coord);
|
||||||
|
glutSetVertexAttribNormal(attribute_fg_normal);
|
||||||
|
/* There is also a glutSetVertexAttribTexCoord2, which is used only when drawing the teapot, teacup or teaspoon */
|
||||||
|
|
||||||
|
gl_matrix_mode(GL_PROJECTION);
|
||||||
|
gl_load_identity();
|
||||||
|
if (persProject)
|
||||||
|
gl_frustum(-ar, ar, -1.f, 1.f, 2.f, 100.f);
|
||||||
|
else
|
||||||
|
gl_ortho(-ar*3, ar*3, -3.f, 3.f, 2.f, 100.f);
|
||||||
|
gl_UniformMatrix4fv (uniform_p, 1, GL_FALSE, get_matrix(GL_PROJECTION));
|
||||||
|
|
||||||
|
|
||||||
|
gl_matrix_mode(GL_MODELVIEW);
|
||||||
|
gl_load_identity();
|
||||||
|
|
||||||
|
gl_push_matrix();
|
||||||
|
/* Not in reverse order like normal OpenGL, our util library multiplies the matrices in the order they are specified in */
|
||||||
|
gl_rotatef((float)a,0,0,1);
|
||||||
|
gl_rotatef((float)b,1,0,0);
|
||||||
|
gl_translatef(0,1.2f,-6);
|
||||||
|
gl_UniformMatrix4fv (uniform_m , 1, GL_FALSE, get_matrix(GL_MODELVIEW));
|
||||||
|
gl_UniformMatrix3fv (uniform_m_3x3_inv_transp, 1, GL_FALSE, get_inv_transpose_3x3(GL_MODELVIEW));
|
||||||
|
table [function_index].solid ();
|
||||||
|
gl_pop_matrix();
|
||||||
|
|
||||||
|
gl_push_matrix();
|
||||||
|
gl_rotatef((float)a,0,0,1);
|
||||||
|
gl_rotatef((float)b,1,0,0);
|
||||||
|
gl_translatef(0,-1.2f,-6);
|
||||||
|
gl_UniformMatrix4fv (uniform_m , 1, GL_FALSE, get_matrix(GL_MODELVIEW));
|
||||||
|
gl_UniformMatrix3fv (uniform_m_3x3_inv_transp, 1, GL_FALSE, get_inv_transpose_3x3(GL_MODELVIEW));
|
||||||
|
table [function_index].wire ();
|
||||||
|
gl_pop_matrix();
|
||||||
|
|
||||||
|
gl_UseProgram (0);
|
||||||
|
glutSetVertexAttribCoord3(-1);
|
||||||
|
glutSetVertexAttribNormal(-1);
|
||||||
|
|
||||||
|
checkError ("display");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* fixed function pipeline */
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
if (persProject)
|
||||||
|
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
|
||||||
|
else
|
||||||
|
glOrtho(-ar*3, ar*3, -3.0, 3.0, 2.0, 100.0);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
|
||||||
|
glColor3d(1,0,0);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslated(0,1.2,-6);
|
||||||
|
glRotated(b,1,0,0);
|
||||||
|
glRotated(a,0,0,1);
|
||||||
|
table [function_index].solid ();
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslated(0,-1.2,-6);
|
||||||
|
glRotated(b,1,0,0);
|
||||||
|
glRotated(a,0,0,1);
|
||||||
|
table [function_index].wire ();
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glColor3d(0.1,0.1,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( show_info )
|
||||||
|
/* print info to screen */
|
||||||
|
drawInfo();
|
||||||
|
else
|
||||||
|
/* print to command line instead */
|
||||||
|
printf ( "Shape %d slides %d stacks %d\n", function_index, slices, stacks ) ;
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
key(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case 27 :
|
||||||
|
case 'Q':
|
||||||
|
case 'q': glutLeaveMainLoop () ; break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
case 'i': show_info=!show_info; break;
|
||||||
|
|
||||||
|
case '=':
|
||||||
|
case '+': slices++; break;
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
case '_': if( slices > -1 ) slices--; break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
case '<': if( stacks > -1 ) stacks--; break;
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
case '>': stacks++; break;
|
||||||
|
|
||||||
|
case '9':
|
||||||
|
case '(': if( depth > -1 ) depth--; break;
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
case ')': ++depth; break;
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
case 'p': persProject=!persProject; break;
|
||||||
|
|
||||||
|
case 'R':
|
||||||
|
case 'r': animateXRot=!animateXRot; break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
case 's':
|
||||||
|
useShader=!useShader;
|
||||||
|
/* Cuboctahedron can't be shown when in shader mode, move to next */
|
||||||
|
if (useShader && NUMBEROF (table)-1 == ( unsigned )function_index)
|
||||||
|
function_index = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
case 'f':
|
||||||
|
flat ^= 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'N':
|
||||||
|
case 'n': visNormals=!visNormals; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void special (int key, int x, int y)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case GLUT_KEY_PAGE_UP: ++function_index; break;
|
||||||
|
case GLUT_KEY_PAGE_DOWN: --function_index; break;
|
||||||
|
case GLUT_KEY_UP: orad *= 2; break;
|
||||||
|
case GLUT_KEY_DOWN: orad /= 2; break;
|
||||||
|
|
||||||
|
case GLUT_KEY_RIGHT: irad *= 2; break;
|
||||||
|
case GLUT_KEY_LEFT: irad /= 2; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 > function_index)
|
||||||
|
function_index = NUMBEROF (table) - 1;
|
||||||
|
|
||||||
|
if (NUMBEROF (table) <= ( unsigned )function_index)
|
||||||
|
function_index = 0;
|
||||||
|
|
||||||
|
/* Cuboctahedron can't be shown when in shader mode, skip it */
|
||||||
|
if (useShader && NUMBEROF (table)-1 == ( unsigned )function_index)
|
||||||
|
{
|
||||||
|
if (key==GLUT_KEY_PAGE_UP)
|
||||||
|
function_index = 0;
|
||||||
|
else
|
||||||
|
function_index -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
idle(void)
|
||||||
|
{
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
|
||||||
|
|
||||||
|
const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
|
||||||
|
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
|
||||||
|
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
const GLfloat high_shininess[] = { 100.0f };
|
||||||
|
|
||||||
|
/* Program entry point */
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
glutInitWindowSize(800,600);
|
||||||
|
glutInitWindowPosition(40,40);
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
|
||||||
|
|
||||||
|
glutCreateWindow("FreeGLUT Shapes");
|
||||||
|
|
||||||
|
glutReshapeFunc(resize);
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutKeyboardFunc(key);
|
||||||
|
glutSpecialFunc(special);
|
||||||
|
glutIdleFunc(idle);
|
||||||
|
|
||||||
|
glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ;
|
||||||
|
|
||||||
|
glClearColor(1,1,1,1);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
glEnable(GL_NORMALIZE);
|
||||||
|
glEnable(GL_COLOR_MATERIAL);
|
||||||
|
|
||||||
|
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
|
||||||
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
||||||
|
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
|
||||||
|
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
|
||||||
|
|
||||||
|
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
|
||||||
|
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||||
|
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
|
||||||
|
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
|
||||||
|
|
||||||
|
initExtensionEntries();
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAK INFORMATION */
|
||||||
|
_CrtDumpMemoryLeaks () ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,469 @@
|
||||||
|
/*
|
||||||
|
* smooth_opengl3.c, based on smooth.c, which is (c) by SGI, see below.
|
||||||
|
* This program demonstrates smooth shading in a way which is fully
|
||||||
|
* OpenGL-3.1-compliant.
|
||||||
|
* A smooth shaded polygon is drawn in a 2-D projection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Original copyright notice from smooth.c:
|
||||||
|
*
|
||||||
|
* License Applicability. Except to the extent portions of this file are
|
||||||
|
* made subject to an alternative license as permitted in the SGI Free
|
||||||
|
* Software License B, Version 1.1 (the "License"), the contents of this
|
||||||
|
* file are subject only to the provisions of the License. You may not use
|
||||||
|
* this file except in compliance with the License. You may obtain a copy
|
||||||
|
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
|
||||||
|
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
|
||||||
|
*
|
||||||
|
* http://oss.sgi.com/projects/FreeB
|
||||||
|
*
|
||||||
|
* Note that, as provided in the License, the Software is distributed on an
|
||||||
|
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
|
||||||
|
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
|
||||||
|
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
||||||
|
*
|
||||||
|
* Original Code. The Original Code is: OpenGL Sample Implementation,
|
||||||
|
* Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
|
||||||
|
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
|
||||||
|
* Copyright in any portions created by third parties is as indicated
|
||||||
|
* elsewhere herein. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Additional Notice Provisions: The application programming interfaces
|
||||||
|
* established by SGI in conjunction with the Original Code are The
|
||||||
|
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
|
||||||
|
* April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
|
||||||
|
* 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
|
||||||
|
* Window System(R) (Version 1.3), released October 19, 1998. This software
|
||||||
|
* was created using the OpenGL(R) version 1.2.1 Sample Implementation
|
||||||
|
* published by SGI, but has not been independently verified as being
|
||||||
|
* compliant with the OpenGL(R) version 1.2.1 Specification.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* report GL errors, if any, to stderr */
|
||||||
|
void checkError(const char *functionName)
|
||||||
|
{
|
||||||
|
GLenum error;
|
||||||
|
while (( error = glGetError() ) != GL_NO_ERROR) {
|
||||||
|
fprintf (stderr, "GL error 0x%X detected in %s\n", error, functionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extension #defines, types and entries, avoiding a dependency on additional
|
||||||
|
libraries like GLEW or the GL/glext.h header */
|
||||||
|
#ifndef GL_ARRAY_BUFFER
|
||||||
|
#define GL_ARRAY_BUFFER 0x8892
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_STATIC_DRAW
|
||||||
|
#define GL_STATIC_DRAW 0x88E4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_FRAGMENT_SHADER
|
||||||
|
#define GL_FRAGMENT_SHADER 0x8B30
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_VERTEX_SHADER
|
||||||
|
#define GL_VERTEX_SHADER 0x8B31
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_SHADING_LANGUAGE_VERSION
|
||||||
|
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_COMPILE_STATUS
|
||||||
|
#define GL_COMPILE_STATUS 0x8B81
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_LINK_STATUS
|
||||||
|
#define GL_LINK_STATUS 0x8B82
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_INFO_LOG_LENGTH
|
||||||
|
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef ptrdiff_t ourGLsizeiptr;
|
||||||
|
typedef char ourGLchar;
|
||||||
|
|
||||||
|
#ifndef APIENTRY
|
||||||
|
#define APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef GL_ARB_vertex_array_object
|
||||||
|
typedef void (APIENTRY *PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
|
||||||
|
typedef void (APIENTRY *PFNGLBINDVERTEXARRAYPROC) (GLuint array);
|
||||||
|
#endif
|
||||||
|
#ifndef GL_VERSION_1_5
|
||||||
|
typedef void (APIENTRY *PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
|
||||||
|
typedef void (APIENTRY *PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||||
|
typedef void (APIENTRY *PFNGLBUFFERDATAPROC) (GLenum target, ourGLsizeiptr size, const GLvoid *data, GLenum usage);
|
||||||
|
#endif
|
||||||
|
#ifndef GL_VERSION_2_0
|
||||||
|
typedef GLuint (APIENTRY *PFNGLCREATESHADERPROC) (GLenum type);
|
||||||
|
typedef void (APIENTRY *PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const ourGLchar **string, const GLint *length);
|
||||||
|
typedef void (APIENTRY *PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||||
|
typedef GLuint (APIENTRY *PFNGLCREATEPROGRAMPROC) (void);
|
||||||
|
typedef void (APIENTRY *PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||||
|
typedef void (APIENTRY *PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||||
|
typedef void (APIENTRY *PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||||
|
typedef void (APIENTRY *PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||||
|
typedef void (APIENTRY *PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog);
|
||||||
|
typedef void (APIENTRY *PFNGLGETPROGRAMIVPROC) (GLenum target, GLenum pname, GLint *params);
|
||||||
|
typedef void (APIENTRY *PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog);
|
||||||
|
typedef GLint (APIENTRY *PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const ourGLchar *name);
|
||||||
|
typedef void (APIENTRY *PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
|
||||||
|
typedef void (APIENTRY *PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||||
|
typedef GLint (APIENTRY *PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const ourGLchar *name);
|
||||||
|
typedef void (APIENTRY *PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PFNGLGENVERTEXARRAYSPROC gl_GenVertexArrays;
|
||||||
|
PFNGLBINDVERTEXARRAYPROC gl_BindVertexArray;
|
||||||
|
PFNGLGENBUFFERSPROC gl_GenBuffers;
|
||||||
|
PFNGLBINDBUFFERPROC gl_BindBuffer;
|
||||||
|
PFNGLBUFFERDATAPROC gl_BufferData;
|
||||||
|
PFNGLCREATESHADERPROC gl_CreateShader;
|
||||||
|
PFNGLSHADERSOURCEPROC gl_ShaderSource;
|
||||||
|
PFNGLCOMPILESHADERPROC gl_CompileShader;
|
||||||
|
PFNGLCREATEPROGRAMPROC gl_CreateProgram;
|
||||||
|
PFNGLATTACHSHADERPROC gl_AttachShader;
|
||||||
|
PFNGLLINKPROGRAMPROC gl_LinkProgram;
|
||||||
|
PFNGLUSEPROGRAMPROC gl_UseProgram;
|
||||||
|
PFNGLGETSHADERIVPROC gl_GetShaderiv;
|
||||||
|
PFNGLGETSHADERINFOLOGPROC gl_GetShaderInfoLog;
|
||||||
|
PFNGLGETPROGRAMIVPROC gl_GetProgramiv;
|
||||||
|
PFNGLGETPROGRAMINFOLOGPROC gl_GetProgramInfoLog;
|
||||||
|
PFNGLGETATTRIBLOCATIONPROC gl_GetAttribLocation;
|
||||||
|
PFNGLVERTEXATTRIBPOINTERPROC gl_VertexAttribPointer;
|
||||||
|
PFNGLENABLEVERTEXATTRIBARRAYPROC gl_EnableVertexAttribArray;
|
||||||
|
PFNGLGETUNIFORMLOCATIONPROC gl_GetUniformLocation;
|
||||||
|
PFNGLUNIFORMMATRIX4FVPROC gl_UniformMatrix4fv;
|
||||||
|
|
||||||
|
void initExtensionEntries(void)
|
||||||
|
{
|
||||||
|
gl_GenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) glutGetProcAddress ("glGenVertexArrays");
|
||||||
|
gl_BindVertexArray = (PFNGLBINDVERTEXARRAYPROC) glutGetProcAddress ("glBindVertexArray");
|
||||||
|
if (!gl_GenVertexArrays || !gl_BindVertexArray)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "glGenVertexArrays or glBindVertexArray not found");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
gl_GenBuffers = (PFNGLGENBUFFERSPROC) glutGetProcAddress ("glGenBuffers");
|
||||||
|
gl_BindBuffer = (PFNGLBINDBUFFERPROC) glutGetProcAddress ("glBindBuffer");
|
||||||
|
gl_BufferData = (PFNGLBUFFERDATAPROC) glutGetProcAddress ("glBufferData");
|
||||||
|
if (!gl_GenBuffers || !gl_BindBuffer || !gl_BufferData)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "glGenBuffers, glBindBuffer or glBufferData not found");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
gl_CreateShader = (PFNGLCREATESHADERPROC) glutGetProcAddress ("glCreateShader");
|
||||||
|
gl_ShaderSource = (PFNGLSHADERSOURCEPROC) glutGetProcAddress ("glShaderSource");
|
||||||
|
gl_CompileShader = (PFNGLCOMPILESHADERPROC) glutGetProcAddress ("glCompileShader");
|
||||||
|
gl_CreateProgram = (PFNGLCREATEPROGRAMPROC) glutGetProcAddress ("glCreateProgram");
|
||||||
|
gl_AttachShader = (PFNGLATTACHSHADERPROC) glutGetProcAddress ("glAttachShader");
|
||||||
|
gl_LinkProgram = (PFNGLLINKPROGRAMPROC) glutGetProcAddress ("glLinkProgram");
|
||||||
|
gl_UseProgram = (PFNGLUSEPROGRAMPROC) glutGetProcAddress ("glUseProgram");
|
||||||
|
gl_GetShaderiv = (PFNGLGETSHADERIVPROC) glutGetProcAddress ("glGetShaderiv");
|
||||||
|
gl_GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) glutGetProcAddress ("glGetShaderInfoLog");
|
||||||
|
gl_GetProgramiv = (PFNGLGETPROGRAMIVPROC) glutGetProcAddress ("glGetProgramiv");
|
||||||
|
gl_GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) glutGetProcAddress ("glGetProgramInfoLog");
|
||||||
|
gl_GetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) glutGetProcAddress ("glGetAttribLocation");
|
||||||
|
gl_VertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) glutGetProcAddress ("glVertexAttribPointer");
|
||||||
|
gl_EnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) glutGetProcAddress ("glEnableVertexAttribArray");
|
||||||
|
gl_GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) glutGetProcAddress ("glGetUniformLocation");
|
||||||
|
gl_UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) glutGetProcAddress ("glUniformMatrix4fv");
|
||||||
|
if (!gl_CreateShader || !gl_ShaderSource || !gl_CompileShader || !gl_CreateProgram || !gl_AttachShader || !gl_LinkProgram || !gl_UseProgram || !gl_GetShaderiv || !gl_GetShaderInfoLog || !gl_GetProgramiv || !gl_GetProgramInfoLog || !gl_GetAttribLocation || !gl_VertexAttribPointer || !gl_EnableVertexAttribArray || !gl_GetUniformLocation || !gl_UniformMatrix4fv)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "glCreateShader, glShaderSource, glCompileShader, glCreateProgram, glAttachShader, glLinkProgram, glUseProgram, glGetShaderiv, glGetShaderInfoLog, glGetProgramiv, glGetProgramInfoLog, glGetAttribLocation, glVertexAttribPointer, glEnableVertexAttribArray, glGetUniformLocation or glUniformMatrix4fv not found");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vertex array data for a colored 2D triangle, consisting of RGB color values
|
||||||
|
and XY coordinates */
|
||||||
|
const GLfloat varray[] = {
|
||||||
|
1.0f, 0.0f, 0.0f, /* red */
|
||||||
|
5.0f, 5.0f, /* lower left */
|
||||||
|
|
||||||
|
0.0f, 1.0f, 0.0f, /* green */
|
||||||
|
25.0f, 5.0f, /* lower right */
|
||||||
|
|
||||||
|
0.0f, 0.0f, 1.0f, /* blue */
|
||||||
|
5.0f, 25.0f /* upper left */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ISO C somehow enforces this silly use of 'enum' for compile-time constants */
|
||||||
|
enum {
|
||||||
|
numColorComponents = 3,
|
||||||
|
numVertexComponents = 2,
|
||||||
|
stride = sizeof(GLfloat) * (numColorComponents + numVertexComponents),
|
||||||
|
numElements = sizeof(varray) / stride
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the name of the vertex buffer object */
|
||||||
|
GLuint vertexBufferName;
|
||||||
|
GLuint vertexArrayName;
|
||||||
|
|
||||||
|
void initBuffer(void)
|
||||||
|
{
|
||||||
|
/* Need to setup a vertex array as otherwise invalid operation errors can
|
||||||
|
* occur when accessing vertex buffer (OpenGL 3.3 has no default zero named
|
||||||
|
* vertex array)
|
||||||
|
*/
|
||||||
|
gl_GenVertexArrays(1, &vertexArrayName);
|
||||||
|
gl_BindVertexArray(vertexArrayName);
|
||||||
|
|
||||||
|
gl_GenBuffers (1, &vertexBufferName);
|
||||||
|
gl_BindBuffer (GL_ARRAY_BUFFER, vertexBufferName);
|
||||||
|
gl_BufferData (GL_ARRAY_BUFFER, sizeof(varray), varray, GL_STATIC_DRAW);
|
||||||
|
checkError ("initBuffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
const ourGLchar *vertexShaderSource[] = {
|
||||||
|
"#version 140\n",
|
||||||
|
"uniform mat4 fg_ProjectionMatrix;\n",
|
||||||
|
"in vec4 fg_Color;\n",
|
||||||
|
"in vec4 fg_Vertex;\n",
|
||||||
|
"smooth out vec4 fg_SmoothColor;\n",
|
||||||
|
"void main()\n",
|
||||||
|
"{\n",
|
||||||
|
" fg_SmoothColor = fg_Color;\n",
|
||||||
|
" gl_Position = fg_ProjectionMatrix * fg_Vertex;\n",
|
||||||
|
"}\n"
|
||||||
|
};
|
||||||
|
|
||||||
|
const ourGLchar *fragmentShaderSource[] = {
|
||||||
|
"#version 140\n",
|
||||||
|
"smooth in vec4 fg_SmoothColor;\n",
|
||||||
|
"out vec4 fg_FragColor;\n",
|
||||||
|
"void main(void)\n",
|
||||||
|
"{\n",
|
||||||
|
" fg_FragColor = fg_SmoothColor;\n",
|
||||||
|
"}\n"
|
||||||
|
};
|
||||||
|
|
||||||
|
void compileAndCheck(GLuint shader)
|
||||||
|
{
|
||||||
|
GLint status;
|
||||||
|
gl_CompileShader (shader);
|
||||||
|
gl_GetShaderiv (shader, GL_COMPILE_STATUS, &status);
|
||||||
|
if (status == GL_FALSE) {
|
||||||
|
GLint infoLogLength;
|
||||||
|
ourGLchar *infoLog;
|
||||||
|
gl_GetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
infoLog = (ourGLchar*) malloc (infoLogLength);
|
||||||
|
gl_GetShaderInfoLog (shader, infoLogLength, NULL, infoLog);
|
||||||
|
fprintf (stderr, "compile log: %s\n", infoLog);
|
||||||
|
free (infoLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint compileShaderSource(GLenum type, GLsizei count, const ourGLchar **string)
|
||||||
|
{
|
||||||
|
GLuint shader = gl_CreateShader (type);
|
||||||
|
gl_ShaderSource (shader, count, string, NULL);
|
||||||
|
compileAndCheck (shader);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linkAndCheck(GLuint program)
|
||||||
|
{
|
||||||
|
GLint status;
|
||||||
|
gl_LinkProgram (program);
|
||||||
|
gl_GetProgramiv (program, GL_LINK_STATUS, &status);
|
||||||
|
if (status == GL_FALSE) {
|
||||||
|
GLint infoLogLength;
|
||||||
|
ourGLchar *infoLog;
|
||||||
|
gl_GetProgramiv (program, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
infoLog = (ourGLchar*) malloc (infoLogLength);
|
||||||
|
gl_GetProgramInfoLog (program, infoLogLength, NULL, infoLog);
|
||||||
|
fprintf (stderr, "link log: %s\n", infoLog);
|
||||||
|
free (infoLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint createProgram(GLuint vertexShader, GLuint fragmentShader)
|
||||||
|
{
|
||||||
|
GLuint program = gl_CreateProgram ();
|
||||||
|
if (vertexShader != 0) {
|
||||||
|
gl_AttachShader (program, vertexShader);
|
||||||
|
}
|
||||||
|
if (fragmentShader != 0) {
|
||||||
|
gl_AttachShader (program, fragmentShader);
|
||||||
|
}
|
||||||
|
linkAndCheck (program);
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint fgProjectionMatrixIndex;
|
||||||
|
GLuint fgColorIndex;
|
||||||
|
GLuint fgVertexIndex;
|
||||||
|
|
||||||
|
void initShader(void)
|
||||||
|
{
|
||||||
|
const GLsizei vertexShaderLines = sizeof(vertexShaderSource) / sizeof(ourGLchar*);
|
||||||
|
GLuint vertexShader =
|
||||||
|
compileShaderSource (GL_VERTEX_SHADER, vertexShaderLines, vertexShaderSource);
|
||||||
|
|
||||||
|
const GLsizei fragmentShaderLines = sizeof(fragmentShaderSource) / sizeof(ourGLchar*);
|
||||||
|
GLuint fragmentShader =
|
||||||
|
compileShaderSource (GL_FRAGMENT_SHADER, fragmentShaderLines, fragmentShaderSource);
|
||||||
|
|
||||||
|
GLuint program = createProgram (vertexShader, fragmentShader);
|
||||||
|
|
||||||
|
gl_UseProgram (program);
|
||||||
|
|
||||||
|
fgProjectionMatrixIndex = gl_GetUniformLocation(program, "fg_ProjectionMatrix");
|
||||||
|
|
||||||
|
fgColorIndex = gl_GetAttribLocation(program, "fg_Color");
|
||||||
|
gl_EnableVertexAttribArray (fgColorIndex);
|
||||||
|
|
||||||
|
fgVertexIndex = gl_GetAttribLocation(program, "fg_Vertex");
|
||||||
|
gl_EnableVertexAttribArray (fgVertexIndex);
|
||||||
|
|
||||||
|
checkError ("initShader");
|
||||||
|
}
|
||||||
|
|
||||||
|
void initRendering(void)
|
||||||
|
{
|
||||||
|
glClearColor (0.0, 0.0, 0.0, 0.0);
|
||||||
|
checkError ("initRendering");
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(void)
|
||||||
|
{
|
||||||
|
initExtensionEntries ();
|
||||||
|
initBuffer ();
|
||||||
|
initShader ();
|
||||||
|
initRendering ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpInfo(void)
|
||||||
|
{
|
||||||
|
printf ("Vendor: %s\n", glGetString (GL_VENDOR));
|
||||||
|
printf ("Renderer: %s\n", glGetString (GL_RENDERER));
|
||||||
|
printf ("Version: %s\n", glGetString (GL_VERSION));
|
||||||
|
printf ("GLSL: %s\n", glGetString (GL_SHADING_LANGUAGE_VERSION));
|
||||||
|
checkError ("dumpInfo");
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLvoid *bufferObjectPtr (GLsizei index)
|
||||||
|
{
|
||||||
|
return (const GLvoid *) (((char *) NULL) + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLfloat projectionMatrix[16];
|
||||||
|
|
||||||
|
void triangle(void)
|
||||||
|
{
|
||||||
|
gl_UniformMatrix4fv (fgProjectionMatrixIndex, 1, GL_FALSE, projectionMatrix);
|
||||||
|
|
||||||
|
gl_BindBuffer (GL_ARRAY_BUFFER, vertexBufferName);
|
||||||
|
gl_VertexAttribPointer (fgColorIndex, numColorComponents, GL_FLOAT, GL_FALSE,
|
||||||
|
stride, bufferObjectPtr (0));
|
||||||
|
gl_VertexAttribPointer (fgVertexIndex, numVertexComponents, GL_FLOAT, GL_FALSE,
|
||||||
|
stride, bufferObjectPtr (sizeof(GLfloat) * numColorComponents));
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, numElements);
|
||||||
|
checkError ("triangle");
|
||||||
|
}
|
||||||
|
|
||||||
|
void display(void)
|
||||||
|
{
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT);
|
||||||
|
triangle ();
|
||||||
|
glFlush ();
|
||||||
|
checkError ("display");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadOrthof(GLfloat *m, GLfloat l, GLfloat r, GLfloat b, GLfloat t,
|
||||||
|
GLfloat n, GLfloat f)
|
||||||
|
{
|
||||||
|
m[ 0] = 2.0f / (r - l);
|
||||||
|
m[ 1] = 0.0f;
|
||||||
|
m[ 2] = 0.0f;
|
||||||
|
m[ 3] = 0.0f;
|
||||||
|
|
||||||
|
m[ 4] = 0.0f;
|
||||||
|
m[ 5] = 2.0f / (t - b);
|
||||||
|
m[ 6] = 0.0f;
|
||||||
|
m[ 7] = 0.0f;
|
||||||
|
|
||||||
|
m[ 8] = 0.0f;
|
||||||
|
m[ 9] = 0.0f;
|
||||||
|
m[10] = -2.0f / (f - n);
|
||||||
|
m[11] = 0.0f;
|
||||||
|
|
||||||
|
m[12] = -(r + l) / (r - l);
|
||||||
|
m[13] = -(t + b) / (t - b);
|
||||||
|
m[14] = -(f + n) / (f - n);
|
||||||
|
m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadOrtho2Df(GLfloat *m, GLfloat l, GLfloat r, GLfloat b, GLfloat t)
|
||||||
|
{
|
||||||
|
loadOrthof (m, l, r, b, t, -1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reshape (int w, int h)
|
||||||
|
{
|
||||||
|
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
|
||||||
|
if (w <= h) {
|
||||||
|
loadOrtho2Df (projectionMatrix, 0.0f, 30.0f, 0.0f, 30.0f * (GLfloat) h/(GLfloat) w);
|
||||||
|
} else {
|
||||||
|
loadOrtho2Df (projectionMatrix, 0.0f, 30.0f * (GLfloat) w/(GLfloat) h, 0.0f, 30.0f);
|
||||||
|
}
|
||||||
|
checkError ("reshape");
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
switch (key) {
|
||||||
|
case 27:
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void samplemenu(int menuID)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int menuA;
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
|
||||||
|
/* add command line argument "classic" for a pre-3.x context */
|
||||||
|
if ((argc != 2) || (strcmp (argv[1], "classic") != 0)) {
|
||||||
|
glutInitContextVersion (3, 1);
|
||||||
|
glutInitContextFlags (GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);
|
||||||
|
}
|
||||||
|
glutInitWindowSize (500, 500);
|
||||||
|
glutInitWindowPosition (100, 100);
|
||||||
|
glutCreateWindow (argv[0]);
|
||||||
|
dumpInfo ();
|
||||||
|
init ();
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutReshapeFunc(reshape);
|
||||||
|
glutKeyboardFunc (keyboard);
|
||||||
|
|
||||||
|
/* Add a menu. They have their own context and should thus work with forward compatible main windows too. */
|
||||||
|
menuA = glutCreateMenu(samplemenu);
|
||||||
|
glutAddMenuEntry("Sub menu A1 (01)",1);
|
||||||
|
glutAddMenuEntry("Sub menu A2 (02)",2);
|
||||||
|
glutAddMenuEntry("Sub menu A3 (03)",3);
|
||||||
|
glutSetMenu(menuA);
|
||||||
|
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
/* Spaceball demo
|
||||||
|
*
|
||||||
|
* Written by John Tsiombikas <nuclear@member.fsf.org>
|
||||||
|
* (converted from the libspnav cube example)
|
||||||
|
*
|
||||||
|
* Use the spaceball to move and rotate the colored cube.
|
||||||
|
* Pressing any button will reset the cube at its original location.
|
||||||
|
*
|
||||||
|
* Press escape or q to exit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "vmath.h"
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846264338327950
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void draw_cube(void);
|
||||||
|
|
||||||
|
/* callbacks */
|
||||||
|
void disp(void);
|
||||||
|
void reshape(int x, int y);
|
||||||
|
void keyb(unsigned char key, int x, int y);
|
||||||
|
void sbmot(int x, int y, int z); /* spaceball translation */
|
||||||
|
void sbrot(int x, int y, int z); /* spaceball rotation */
|
||||||
|
void sbbut(int bn, int state); /* spaceball button */
|
||||||
|
|
||||||
|
vec3_t pos = {0, 0, -6};
|
||||||
|
quat_t rot = {0, 0, 0, 1};
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||||
|
glutCreateWindow("spaceball demo");
|
||||||
|
|
||||||
|
glutDisplayFunc(disp);
|
||||||
|
glutReshapeFunc(reshape);
|
||||||
|
glutKeyboardFunc(keyb);
|
||||||
|
glutSpaceballMotionFunc(sbmot);
|
||||||
|
glutSpaceballRotateFunc(sbrot);
|
||||||
|
glutSpaceballButtonFunc(sbbut);
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disp(void)
|
||||||
|
{
|
||||||
|
mat4_t xform;
|
||||||
|
|
||||||
|
quat_to_mat(xform, rot);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(pos.x, pos.y, pos.z);
|
||||||
|
glMultMatrixf((float*)xform);
|
||||||
|
|
||||||
|
draw_cube();
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_cube(void)
|
||||||
|
{
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
/* face +Z */
|
||||||
|
glNormal3f(0, 0, 1);
|
||||||
|
glColor3f(1, 0, 0);
|
||||||
|
glVertex3f(-1, -1, 1);
|
||||||
|
glVertex3f(1, -1, 1);
|
||||||
|
glVertex3f(1, 1, 1);
|
||||||
|
glVertex3f(-1, 1, 1);
|
||||||
|
/* face +X */
|
||||||
|
glNormal3f(1, 0, 0);
|
||||||
|
glColor3f(0, 1, 0);
|
||||||
|
glVertex3f(1, -1, 1);
|
||||||
|
glVertex3f(1, -1, -1);
|
||||||
|
glVertex3f(1, 1, -1);
|
||||||
|
glVertex3f(1, 1, 1);
|
||||||
|
/* face -Z */
|
||||||
|
glNormal3f(0, 0, -1);
|
||||||
|
glColor3f(0, 0, 1);
|
||||||
|
glVertex3f(1, -1, -1);
|
||||||
|
glVertex3f(-1, -1, -1);
|
||||||
|
glVertex3f(-1, 1, -1);
|
||||||
|
glVertex3f(1, 1, -1);
|
||||||
|
/* face -X */
|
||||||
|
glNormal3f(-1, 0, 0);
|
||||||
|
glColor3f(1, 1, 0);
|
||||||
|
glVertex3f(-1, -1, -1);
|
||||||
|
glVertex3f(-1, -1, 1);
|
||||||
|
glVertex3f(-1, 1, 1);
|
||||||
|
glVertex3f(-1, 1, -1);
|
||||||
|
/* face +Y */
|
||||||
|
glNormal3f(0, 1, 0);
|
||||||
|
glColor3f(0, 1, 1);
|
||||||
|
glVertex3f(-1, 1, 1);
|
||||||
|
glVertex3f(1, 1, 1);
|
||||||
|
glVertex3f(1, 1, -1);
|
||||||
|
glVertex3f(-1, 1, -1);
|
||||||
|
/* face -Y */
|
||||||
|
glNormal3f(0, -1, 0);
|
||||||
|
glColor3f(1, 0, 1);
|
||||||
|
glVertex3f(-1, -1, -1);
|
||||||
|
glVertex3f(1, -1, -1);
|
||||||
|
glVertex3f(1, -1, 1);
|
||||||
|
glVertex3f(-1, -1, 1);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 45deg fov */
|
||||||
|
#define FOV (M_PI / 4.0)
|
||||||
|
|
||||||
|
void reshape(int x, int y)
|
||||||
|
{
|
||||||
|
float aspect = (float)x / (float)y;
|
||||||
|
float halfy = (float)tan(FOV / 2.0);
|
||||||
|
float halfx = halfy * aspect;
|
||||||
|
|
||||||
|
glViewport(0, 0, x, y);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glFrustum(-halfx, halfx, -halfy, halfy, 1.0, 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyb(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
switch(key) {
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
case 27:
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
case ' ':
|
||||||
|
/* reset initial view */
|
||||||
|
pos = v3_cons(0, 0, -6);
|
||||||
|
rot = quat_cons(1, 0, 0, 0);
|
||||||
|
glutPostRedisplay();
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbmot(int x, int y, int z)
|
||||||
|
{
|
||||||
|
pos.x += x * 0.001f;
|
||||||
|
pos.y += y * 0.001f;
|
||||||
|
pos.z -= z * 0.001f;
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbrot(int x, int y, int z)
|
||||||
|
{
|
||||||
|
float axis_len = (float)sqrt(x * x + y * y + z * z);
|
||||||
|
rot = quat_rotate(rot, axis_len * 0.001f, -x / axis_len, -y / axis_len, z / axis_len);
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbbut(int bn, int state)
|
||||||
|
{
|
||||||
|
if(state == GLUT_DOWN) {
|
||||||
|
pos = v3_cons(0, 0, -6);
|
||||||
|
rot = quat_cons(1, 0, 0, 0);
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <math.h>
|
||||||
|
#include "vmath.h"
|
||||||
|
|
||||||
|
quat_t quat_rotate(quat_t q, float angle, float x, float y, float z)
|
||||||
|
{
|
||||||
|
quat_t rq;
|
||||||
|
float half_angle = angle * 0.5f;
|
||||||
|
float sin_half = (float)sin(half_angle);
|
||||||
|
|
||||||
|
rq.w = (float)cos(half_angle);
|
||||||
|
rq.x = x * sin_half;
|
||||||
|
rq.y = y * sin_half;
|
||||||
|
rq.z = z * sin_half;
|
||||||
|
|
||||||
|
return quat_mul(q, rq);
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef VMATH_H_
|
||||||
|
#define VMATH_H_
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
#define INLINE
|
||||||
|
#else
|
||||||
|
#define INLINE inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct { float x, y, z; } vec3_t;
|
||||||
|
typedef struct { float x, y, z, w; } vec4_t;
|
||||||
|
|
||||||
|
typedef vec4_t quat_t;
|
||||||
|
|
||||||
|
typedef float mat4_t[4][4];
|
||||||
|
|
||||||
|
/* vector functions */
|
||||||
|
static INLINE vec3_t v3_cons(float x, float y, float z);
|
||||||
|
static INLINE float v3_dot(vec3_t v1, vec3_t v2);
|
||||||
|
|
||||||
|
/* quaternion functions */
|
||||||
|
static INLINE quat_t quat_cons(float s, float x, float y, float z);
|
||||||
|
static INLINE vec3_t quat_vec(quat_t q);
|
||||||
|
static INLINE quat_t quat_mul(quat_t q1, quat_t q2);
|
||||||
|
static INLINE void quat_to_mat(mat4_t res, quat_t q);
|
||||||
|
quat_t quat_rotate(quat_t q, float angle, float x, float y, float z);
|
||||||
|
|
||||||
|
/* matrix functions */
|
||||||
|
static INLINE void m4_cons(mat4_t m,
|
||||||
|
float m11, float m12, float m13, float m14,
|
||||||
|
float m21, float m22, float m23, float m24,
|
||||||
|
float m31, float m32, float m33, float m34,
|
||||||
|
float m41, float m42, float m43, float m44);
|
||||||
|
|
||||||
|
#include "vmath.inl"
|
||||||
|
|
||||||
|
#endif /* VMATH_H_ */
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* vector functions */
|
||||||
|
static INLINE vec3_t v3_cons(float x, float y, float z)
|
||||||
|
{
|
||||||
|
vec3_t res;
|
||||||
|
res.x = x;
|
||||||
|
res.y = y;
|
||||||
|
res.z = z;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE vec3_t quat_vec(quat_t q)
|
||||||
|
{
|
||||||
|
vec3_t v;
|
||||||
|
v.x = q.x;
|
||||||
|
v.y = q.y;
|
||||||
|
v.z = q.z;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE float v3_dot(vec3_t v1, vec3_t v2)
|
||||||
|
{
|
||||||
|
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* quaternion functions */
|
||||||
|
static INLINE quat_t quat_cons(float s, float x, float y, float z)
|
||||||
|
{
|
||||||
|
quat_t q;
|
||||||
|
q.x = x;
|
||||||
|
q.y = y;
|
||||||
|
q.z = z;
|
||||||
|
q.w = s;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE quat_t quat_mul(quat_t q1, quat_t q2)
|
||||||
|
{
|
||||||
|
quat_t res;
|
||||||
|
vec3_t v1 = quat_vec(q1);
|
||||||
|
vec3_t v2 = quat_vec(q2);
|
||||||
|
|
||||||
|
res.w = q1.w * q2.w - v3_dot(v1, v2);
|
||||||
|
res.x = v2.x * q1.w + v1.x * q2.w + (v1.y * v2.z - v1.z * v2.y);
|
||||||
|
res.y = v2.y * q1.w + v1.y * q2.w + (v1.z * v2.x - v1.x * v2.z);
|
||||||
|
res.z = v2.z * q1.w + v1.z * q2.w + (v1.x * v2.y - v1.y * v2.x);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void quat_to_mat(mat4_t res, quat_t q)
|
||||||
|
{
|
||||||
|
m4_cons(res, 1.0f - 2.0f * q.y*q.y - 2.0f * q.z*q.z, 2.0f * q.x * q.y + 2.0f * q.w * q.z, 2.0f * q.z * q.x - 2.0f * q.w * q.y, 0,
|
||||||
|
2.0f * q.x * q.y - 2.0f * q.w * q.z, 1.0f - 2.0f * q.x*q.x - 2.0f * q.z*q.z, 2.0f * q.y * q.z + 2.0f * q.w * q.x, 0,
|
||||||
|
2.0f * q.z * q.x + 2.0f * q.w * q.y, 2.0f * q.y * q.z - 2.0f * q.w * q.x, 1.0f - 2.0f * q.x*q.x - 2.0f * q.y*q.y, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* matrix functions */
|
||||||
|
static INLINE void m4_cons(mat4_t m,
|
||||||
|
float m11, float m12, float m13, float m14,
|
||||||
|
float m21, float m22, float m23, float m24,
|
||||||
|
float m31, float m32, float m33, float m34,
|
||||||
|
float m41, float m42, float m43, float m44)
|
||||||
|
{
|
||||||
|
m[0][0] = m11; m[1][0] = m12; m[2][0] = m13; m[3][0] = m14;
|
||||||
|
m[0][1] = m21; m[1][1] = m22; m[2][1] = m23; m[3][1] = m24;
|
||||||
|
m[0][2] = m31; m[1][2] = m32; m[2][2] = m33; m[3][2] = m34;
|
||||||
|
m[0][3] = m41; m[1][3] = m42; m[2][3] = m43; m[3][3] = m44;
|
||||||
|
}
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*! \file subwin.c
|
||||||
|
\ingroup demos
|
||||||
|
|
||||||
|
This program is a test harness for the subwindows
|
||||||
|
in OpenGLUT. Based Originally on shape.c demo.
|
||||||
|
|
||||||
|
\author Written by Evan Felix February 2011
|
||||||
|
|
||||||
|
\author Portions Copyright (C) 2004, the OpenGLUT project contributors. <br>
|
||||||
|
OpenGLUT branched from freeglut in February, 2004.
|
||||||
|
|
||||||
|
\image html openglut_subwin.png OpenGLUT Sub Window Demonstration
|
||||||
|
\include demos/subwin/subwin.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAKS */
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAXSTR 16
|
||||||
|
char **strings;
|
||||||
|
int mainwin;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Does printf()-like work using freeglut/OpenGLUT
|
||||||
|
glutBitmapString(). Uses a fixed font. Prints
|
||||||
|
at the indicated row/column position.
|
||||||
|
|
||||||
|
Limitation: Cannot address pixels.
|
||||||
|
Limitation: Renders in screen coords, not model coords.
|
||||||
|
*/
|
||||||
|
static void shapesPrintf (int row, int col, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
static char buf[256];
|
||||||
|
int viewport[4];
|
||||||
|
void *font = GLUT_BITMAP_9_BY_15;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||||
|
(void) _vsnprintf (buf, sizeof(buf), fmt, args);
|
||||||
|
#else
|
||||||
|
(void) vsnprintf (buf, sizeof(buf), fmt, args);
|
||||||
|
#endif
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
glGetIntegerv(GL_VIEWPORT,viewport);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glOrtho(0,viewport[2],0,viewport[3],-1,1);
|
||||||
|
|
||||||
|
glRasterPos2i
|
||||||
|
(
|
||||||
|
glutBitmapWidth(font, ' ') * col,
|
||||||
|
- glutBitmapHeight(font) * (row+2) + viewport[3]
|
||||||
|
);
|
||||||
|
glutBitmapString (font, (unsigned char*)buf);
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GLUT callback Handlers */
|
||||||
|
|
||||||
|
static void
|
||||||
|
resize(int width, int height)
|
||||||
|
{
|
||||||
|
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
/*gluOrtho2D(0, width, 0, height);*/
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
int win = glutGetWindow();
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glColor3d(1,0,0);
|
||||||
|
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glColor3d(0.1,0.1,0.4);
|
||||||
|
|
||||||
|
if (win == mainwin)
|
||||||
|
{
|
||||||
|
shapesPrintf (2, 3, "Move The mouse into different windows");
|
||||||
|
shapesPrintf (3, 3, "pressing keys will add to the string");
|
||||||
|
shapesPrintf (5, 3, "Window: %d", win);
|
||||||
|
shapesPrintf (6, 3, "String: %s", strings[win]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shapesPrintf (1, 3, "Window: %d", win);
|
||||||
|
shapesPrintf (2, 3, "String: %s", strings[win]);
|
||||||
|
}
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
key(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
char *s,str[2];
|
||||||
|
int win = glutGetWindow();
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case 27 :
|
||||||
|
case 'Q':
|
||||||
|
case 'q': glutLeaveMainLoop () ; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
s=strings[win];
|
||||||
|
if (strlen(s)+1>MAXSTR) {
|
||||||
|
s[0]=0;
|
||||||
|
}
|
||||||
|
str[0]=key;
|
||||||
|
str[1]=0;
|
||||||
|
strcat(s,str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void special (int key, int x, int y)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
entry(int state)
|
||||||
|
{
|
||||||
|
int win = glutGetWindow();
|
||||||
|
printf("Win: %d, state: %d\n",win,state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Program entry point */
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int winmax,sw1,sw2,sw2sw,i;
|
||||||
|
|
||||||
|
glutInitWindowSize(640,480);
|
||||||
|
glutInitWindowPosition(40,40);
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
|
||||||
|
|
||||||
|
glutCreateWindow("FreeGLUT Sub Windows");
|
||||||
|
|
||||||
|
glutReshapeFunc(resize);
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutKeyboardFunc(key);
|
||||||
|
glutSpecialFunc(special);
|
||||||
|
glutEntryFunc(entry);
|
||||||
|
|
||||||
|
glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ;
|
||||||
|
|
||||||
|
glClearColor(1,1,1,1);
|
||||||
|
|
||||||
|
mainwin = glutGetWindow();
|
||||||
|
winmax=mainwin;
|
||||||
|
|
||||||
|
sw1=glutCreateSubWindow(mainwin,4,240,314,236);
|
||||||
|
glutReshapeFunc(resize);
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutKeyboardFunc(key);
|
||||||
|
glutSpecialFunc(special);
|
||||||
|
glutEntryFunc(entry);
|
||||||
|
glClearColor(0.7f,0.7f,0.7f,1);
|
||||||
|
winmax = sw1 > winmax ? sw1 : winmax;
|
||||||
|
|
||||||
|
sw2=glutCreateSubWindow(mainwin,322,240,314,236);
|
||||||
|
glutReshapeFunc(resize);
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutKeyboardFunc(key);
|
||||||
|
glutSpecialFunc(special);
|
||||||
|
glutEntryFunc(entry);
|
||||||
|
glClearColor(0.7f,0.7f,0.7f,1);
|
||||||
|
winmax = sw2 > winmax ? sw2 : winmax;
|
||||||
|
|
||||||
|
sw2sw=glutCreateSubWindow(sw2,10,128,294,98);
|
||||||
|
glutReshapeFunc(resize);
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutKeyboardFunc(key);
|
||||||
|
glutSpecialFunc(special);
|
||||||
|
glutEntryFunc(entry);
|
||||||
|
glClearColor(0.4f,0.4f,0.4f,1);
|
||||||
|
winmax = sw2sw > winmax ? sw2sw : winmax;
|
||||||
|
|
||||||
|
strings = malloc(sizeof(char *)*(winmax+1));
|
||||||
|
for (i=0;i<winmax+1;i++) {
|
||||||
|
strings[i] = malloc(sizeof(char)*MAXSTR+1);
|
||||||
|
strings[i][0]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAK INFORMATION */
|
||||||
|
_CrtDumpMemoryLeaks () ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
/* Timer demo
|
||||||
|
*
|
||||||
|
* Written by John Tsiombikas <nuclear@member.fsf.org>
|
||||||
|
*
|
||||||
|
* Demonstrate the use of glutTimerFunc, by changing the color of the
|
||||||
|
* framebuffer every (approximately) 1 sec.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <GL/glut.h>
|
||||||
|
|
||||||
|
void disp(void);
|
||||||
|
void timer_func(int unused);
|
||||||
|
|
||||||
|
/* color index will be advanced every time the timer expires */
|
||||||
|
int cidx = 0;
|
||||||
|
int pcidx = 2;
|
||||||
|
float color[][3] = {
|
||||||
|
{1, 0, 0},
|
||||||
|
{0, 1, 0},
|
||||||
|
{0, 0, 1},
|
||||||
|
{1, 1, 0},
|
||||||
|
{0, 1, 1},
|
||||||
|
{1, 0, 1}
|
||||||
|
};
|
||||||
|
int timerInts[] = {
|
||||||
|
250,
|
||||||
|
500,
|
||||||
|
1000
|
||||||
|
};
|
||||||
|
int timerSurroundInt = 1000, timerCenterInt = 1000;
|
||||||
|
|
||||||
|
/* menu IDs, creation/update funcs and callback */
|
||||||
|
int menuID, subMenuSurround, subMenuCenter;
|
||||||
|
|
||||||
|
void createMenuEntries(int which)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++)
|
||||||
|
{
|
||||||
|
char temp[10] = {'\0'};
|
||||||
|
/* flag current value */
|
||||||
|
if ((which == 1 ? timerSurroundInt : timerCenterInt) == timerInts[i])
|
||||||
|
temp[0] = '+';
|
||||||
|
else
|
||||||
|
temp[0] = '-';
|
||||||
|
|
||||||
|
sprintf(temp + 1, " %4d ms", timerInts[i]);
|
||||||
|
|
||||||
|
glutAddMenuEntry(temp, timerInts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateMenuEntries(int which)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++)
|
||||||
|
{
|
||||||
|
char temp[10] = { '\0' };
|
||||||
|
/* flag current value */
|
||||||
|
if ((which == 1 ? timerSurroundInt : timerCenterInt) == timerInts[i])
|
||||||
|
temp[0] = '+';
|
||||||
|
else
|
||||||
|
temp[0] = '-';
|
||||||
|
|
||||||
|
sprintf(temp + 1, " %4d ms", timerInts[i]);
|
||||||
|
|
||||||
|
glutChangeToMenuEntry(i+1, temp, timerInts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuSurround(int timerInt)
|
||||||
|
{
|
||||||
|
timerSurroundInt = timerInt;
|
||||||
|
glutSetMenu(subMenuSurround);
|
||||||
|
updateMenuEntries(1);
|
||||||
|
}
|
||||||
|
void MenuCenter(int timerInt)
|
||||||
|
{
|
||||||
|
timerCenterInt = timerInt;
|
||||||
|
glutSetMenu(subMenuCenter);
|
||||||
|
updateMenuEntries(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitWindowSize(128, 128);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||||
|
glutCreateWindow("timer test");
|
||||||
|
|
||||||
|
glutDisplayFunc(disp);
|
||||||
|
|
||||||
|
/* get timer started, its reset in the timer function itself */
|
||||||
|
glutTimerFunc(1000, timer_func, 1);
|
||||||
|
glutTimerFunc(500, timer_func, 2);
|
||||||
|
|
||||||
|
/* menus for setting timing */
|
||||||
|
subMenuSurround = glutCreateMenu(MenuSurround);
|
||||||
|
createMenuEntries(1);
|
||||||
|
|
||||||
|
subMenuCenter = glutCreateMenu(MenuCenter);
|
||||||
|
createMenuEntries(2);
|
||||||
|
|
||||||
|
menuID = glutCreateMenu(MenuSurround); /* doesn't matter, no clickable entries in this menu */
|
||||||
|
glutAddSubMenu("Center", subMenuCenter);
|
||||||
|
glutAddSubMenu("Surround", subMenuSurround);
|
||||||
|
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disp(void)
|
||||||
|
{
|
||||||
|
glClearColor(color[cidx][0], color[cidx][1], color[cidx][2], 1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glPointSize(10.f);
|
||||||
|
glColor3f(color[pcidx][0], color[pcidx][1], color[pcidx][2]);
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
glVertex2i(0,0);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_func(int which)
|
||||||
|
{
|
||||||
|
/* advance the color index and trigger a redisplay */
|
||||||
|
switch (which)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
cidx = (cidx + 1) % (sizeof color / sizeof *color);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pcidx = (pcidx + 1) % (sizeof color / sizeof *color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glutPostRedisplay();
|
||||||
|
|
||||||
|
/* (re)set the timer callback and ask glut to call it in x ms */
|
||||||
|
glutTimerFunc(which == 1 ? timerSurroundInt:timerCenterInt, timer_func, which);
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
/* Timer (callback) demo
|
||||||
|
*
|
||||||
|
* Written by John Tsiombikas <nuclear@member.fsf.org>
|
||||||
|
* Modified by Vincent Simonetti
|
||||||
|
*
|
||||||
|
* A modification of the timer sample, but with this
|
||||||
|
* offering a use of the user-data callback.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
|
struct display_index_s
|
||||||
|
{
|
||||||
|
/* color index will be advanced every time the timer expires */
|
||||||
|
int surround_color_index;
|
||||||
|
int center_color_index;
|
||||||
|
};
|
||||||
|
typedef struct display_index_s display_index_t;
|
||||||
|
|
||||||
|
struct timer_state_s
|
||||||
|
{
|
||||||
|
int* color_index_ptr;
|
||||||
|
int* timer_time_ptr;
|
||||||
|
};
|
||||||
|
typedef struct timer_state_s timer_state_t;
|
||||||
|
|
||||||
|
struct menu_state_s
|
||||||
|
{
|
||||||
|
int* timer_time_ptr;
|
||||||
|
int menu_id;
|
||||||
|
};
|
||||||
|
typedef struct menu_state_s menu_state_t;
|
||||||
|
|
||||||
|
void disp(void* uptr);
|
||||||
|
void timer_func(int which, void* uptr);
|
||||||
|
|
||||||
|
const float color[][3] = {
|
||||||
|
{1, 0, 0},
|
||||||
|
{0, 1, 0},
|
||||||
|
{0, 0, 1},
|
||||||
|
{1, 1, 0},
|
||||||
|
{0, 1, 1},
|
||||||
|
{1, 0, 1}
|
||||||
|
};
|
||||||
|
const int timerInts[] = {
|
||||||
|
250,
|
||||||
|
500,
|
||||||
|
1000
|
||||||
|
};
|
||||||
|
|
||||||
|
void createMenuEntries(menu_state_t* menuState)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++)
|
||||||
|
{
|
||||||
|
char temp[10] = {'\0'};
|
||||||
|
/* flag current value */
|
||||||
|
if ((*menuState->timer_time_ptr) == timerInts[i])
|
||||||
|
temp[0] = '+';
|
||||||
|
else
|
||||||
|
temp[0] = '-';
|
||||||
|
|
||||||
|
sprintf(temp + 1, " %4d ms", timerInts[i]);
|
||||||
|
|
||||||
|
glutAddMenuEntry(temp, timerInts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateMenuEntries(menu_state_t* menuState)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++)
|
||||||
|
{
|
||||||
|
char temp[10] = { '\0' };
|
||||||
|
/* flag current value */
|
||||||
|
if ((*menuState->timer_time_ptr) == timerInts[i])
|
||||||
|
temp[0] = '+';
|
||||||
|
else
|
||||||
|
temp[0] = '-';
|
||||||
|
|
||||||
|
sprintf(temp + 1, " %4d ms", timerInts[i]);
|
||||||
|
|
||||||
|
glutChangeToMenuEntry(i+1, temp, timerInts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuHandler(int timerInt, void* user_ptr)
|
||||||
|
{
|
||||||
|
menu_state_t* menuState;
|
||||||
|
|
||||||
|
if (!user_ptr)
|
||||||
|
{
|
||||||
|
/* In case main menu is selected somehow */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuState = (menu_state_t*)user_ptr;
|
||||||
|
|
||||||
|
*menuState->timer_time_ptr = timerInt;
|
||||||
|
glutSetMenu(menuState->menu_id);
|
||||||
|
updateMenuEntries(menuState);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int timerSurroundInt = 1000, timerCenterInt = 500;
|
||||||
|
display_index_t displayIndex = { 0, 2 };
|
||||||
|
timer_state_t surroundTimerState = { &displayIndex.surround_color_index, &timerSurroundInt };
|
||||||
|
timer_state_t centerTimerState = { &displayIndex.center_color_index, &timerCenterInt };
|
||||||
|
menu_state_t surroundMenuState = { &timerSurroundInt, 0 };
|
||||||
|
menu_state_t centerMenuState = { &timerCenterInt, 0 };
|
||||||
|
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitWindowSize(128, 128);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||||
|
glutCreateWindow("timer test");
|
||||||
|
|
||||||
|
glutDisplayFuncUcall(disp, &displayIndex);
|
||||||
|
|
||||||
|
/* get timer started, its reset in the timer function itself */
|
||||||
|
glutTimerFuncUcall(timerSurroundInt, timer_func, 1, &surroundTimerState);
|
||||||
|
glutTimerFuncUcall(timerCenterInt, timer_func, 2, ¢erTimerState);
|
||||||
|
|
||||||
|
/* menus for setting timing */
|
||||||
|
surroundMenuState.menu_id = glutCreateMenuUcall(MenuHandler, &surroundMenuState);
|
||||||
|
createMenuEntries(&surroundMenuState);
|
||||||
|
|
||||||
|
centerMenuState.menu_id = glutCreateMenuUcall(MenuHandler, ¢erMenuState);
|
||||||
|
createMenuEntries(¢erMenuState);
|
||||||
|
|
||||||
|
glutCreateMenuUcall(MenuHandler, NULL); /* doesn't matter, no clickable entries in this menu */
|
||||||
|
glutAddSubMenu("Center", centerMenuState.menu_id);
|
||||||
|
glutAddSubMenu("Surround", surroundMenuState.menu_id);
|
||||||
|
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disp(void* user_ptr)
|
||||||
|
{
|
||||||
|
const display_index_t* displayIndex;
|
||||||
|
int cidx, pcidx;
|
||||||
|
|
||||||
|
displayIndex = (display_index_t*)user_ptr;
|
||||||
|
|
||||||
|
cidx = displayIndex->surround_color_index;
|
||||||
|
glClearColor(color[cidx][0], color[cidx][1], color[cidx][2], 1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
pcidx = displayIndex->center_color_index;
|
||||||
|
glPointSize(10.f);
|
||||||
|
glColor3f(color[pcidx][0], color[pcidx][1], color[pcidx][2]);
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
glVertex2i(0,0);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_func(int which, void* user_ptr)
|
||||||
|
{
|
||||||
|
const timer_state_t* timerState;
|
||||||
|
|
||||||
|
timerState = (timer_state_t*)user_ptr;
|
||||||
|
|
||||||
|
/* advance the color index and trigger a redisplay */
|
||||||
|
*timerState->color_index_ptr = (*timerState->color_index_ptr + 1) % (sizeof color / sizeof *color);
|
||||||
|
|
||||||
|
glutPostRedisplay();
|
||||||
|
|
||||||
|
/* (re)set the timer callback and ask glut to call it in x ms */
|
||||||
|
glutTimerFuncUcall(*timerState->timer_time_ptr, timer_func, which, user_ptr);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- BEGIN_INCLUDE(manifest) -->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="freeglut.test.gles1"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0">
|
||||||
|
|
||||||
|
<!-- This is the platform API where NativeActivity was introduced. -->
|
||||||
|
<uses-sdk android:minSdkVersion="9" />
|
||||||
|
<uses-feature android:glEsVersion="0x00010001"></uses-feature>
|
||||||
|
|
||||||
|
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
||||||
|
<application android:label="@string/app_name" android:hasCode="true"
|
||||||
|
android:debuggable="true"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||||
|
|
||||||
|
<!-- Our activity is the built-in NativeActivity framework class.
|
||||||
|
This will take care of integrating with our NDK code. -->
|
||||||
|
<activity android:name="android.app.NativeActivity"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:configChanges="orientation|keyboardHidden">
|
||||||
|
<!-- Tell NativeActivity the name of or .so -->
|
||||||
|
<meta-data android:name="android.app.lib_name"
|
||||||
|
android:value="test-shapes-gles1" />
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
|
<!-- END_INCLUDE(manifest) -->
|
|
@ -0,0 +1,42 @@
|
||||||
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
project(test-shapes-gles1)
|
||||||
|
|
||||||
|
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||||
|
IF(!ANDROID)
|
||||||
|
# not setting -ansi as EGL/KHR headers doesn't support it
|
||||||
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
|
||||||
|
# FreeGLUT
|
||||||
|
include(FindPkgConfig)
|
||||||
|
pkg_check_modules(freeglut REQUIRED freeglut-gles>=3.0.0)
|
||||||
|
if(freeglut_FOUND)
|
||||||
|
include_directories(${freeglut_STATIC_INCLUDE_DIRS})
|
||||||
|
link_directories(${freeglut_STATIC_LIBRARY_DIRS})
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${freeglut_STATIC_CFLAGS_OTHER}")
|
||||||
|
add_definitions(${freeglut_STATIC_CFLAGS_OTHER})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ANDROID)
|
||||||
|
add_library(test-shapes-gles1 SHARED test-shapes-gles1.c)
|
||||||
|
add_custom_target(apk ALL
|
||||||
|
DEPENDS test-shapes-gles1
|
||||||
|
COMMAND ant clean || true
|
||||||
|
COMMAND rm -rf libs/ src/ res/ bin/ gen/
|
||||||
|
COMMAND mkdir -p libs/armeabi/ src/ res/values/
|
||||||
|
COMMAND cp -a ${PROJECT_SOURCE_DIR}/AndroidManifest.xml ${PROJECT_BINARY_DIR}
|
||||||
|
COMMAND cp -a $<TARGET_FILE:test-shapes-gles1> libs/armeabi/
|
||||||
|
COMMAND echo '<?xml version="1.0" encoding="utf-8"?><resources><string name="app_name">FG_GLES1 test</string></resources>'
|
||||||
|
> res/values/strings.xml
|
||||||
|
COMMAND android update project --name cmake-apk --path . --target "android-10"
|
||||||
|
COMMAND ant debug
|
||||||
|
COMMAND ant installd
|
||||||
|
COMMAND adb shell am start -a android.intenon.MAIN -n freeglut.test.gles1/android.app.NativeActivity
|
||||||
|
)
|
||||||
|
# Note: at least one resource and an empty src/ dir is necessary for ant...
|
||||||
|
else()
|
||||||
|
add_executable(test-shapes-gles1 test-shapes-gles1.c)
|
||||||
|
endif()
|
||||||
|
target_link_libraries(test-shapes-gles1 ${freeglut_STATIC_LIBRARIES})
|
|
@ -0,0 +1 @@
|
||||||
|
../../android_toolchain.cmake
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- BEGIN_INCLUDE(manifest) -->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.wikibooks.OpenGL"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0">
|
||||||
|
|
||||||
|
<!-- This is the platform API where NativeActivity was introduced. -->
|
||||||
|
<uses-sdk android:minSdkVersion="9" />
|
||||||
|
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
|
||||||
|
|
||||||
|
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
||||||
|
<application android:label="@string/app_name" android:hasCode="true"
|
||||||
|
android:icon="@drawable/icon"
|
||||||
|
android:debuggable="true"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||||
|
|
||||||
|
<!-- Our activity is the built-in NativeActivity framework class.
|
||||||
|
This will take care of integrating with our NDK code. -->
|
||||||
|
<activity android:name="android.app.NativeActivity"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:configChanges="orientation|keyboardHidden">
|
||||||
|
<!-- Tell NativeActivity the name of or .so -->
|
||||||
|
<meta-data android:name="android.app.lib_name"
|
||||||
|
android:value="native-activity" />
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
|
<!-- END_INCLUDE(manifest) -->
|
|
@ -0,0 +1,14 @@
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := native-activity
|
||||||
|
LOCAL_SRC_FILES :=
|
||||||
|
LOCAL_CPPFLAGS := -I/usr/src/glm
|
||||||
|
LOCAL_CXXFLAGS := -gstabs+
|
||||||
|
LOCAL_LDLIBS := -llog -landroid -lGLESv2 -lEGL
|
||||||
|
LOCAL_STATIC_LIBRARIES := freeglut
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
$(call import-module,freeglut)
|
|
@ -0,0 +1,2 @@
|
||||||
|
APP_PLATFORM := android-9
|
||||||
|
APP_STL := gnustl_static
|
|
@ -0,0 +1,341 @@
|
||||||
|
/*! \file shapes.c
|
||||||
|
\ingroup demos
|
||||||
|
|
||||||
|
This program is a test harness for the various shapes
|
||||||
|
in OpenGLUT. It may also be useful to see which
|
||||||
|
parameters control what behavior in the OpenGLUT
|
||||||
|
objects.
|
||||||
|
|
||||||
|
Spinning wireframe and solid-shaded shapes are
|
||||||
|
displayed. Some parameters can be adjusted.
|
||||||
|
|
||||||
|
Keys:
|
||||||
|
- <tt>Esc </tt> Quit
|
||||||
|
- <tt>q Q </tt> Quit
|
||||||
|
- <tt>i I </tt> Show info
|
||||||
|
- <tt>p P </tt> Toggle perspective or orthographic projection
|
||||||
|
- <tt>= + </tt> Increase \a slices
|
||||||
|
- <tt>- _ </tt> Decreate \a slices
|
||||||
|
- <tt>, < </tt> Decreate \a stacks
|
||||||
|
- <tt>. > </tt> Increase \a stacks
|
||||||
|
- <tt>9 ( </tt> Decreate \a depth (Sierpinski Sponge)
|
||||||
|
- <tt>0 ) </tt> Increase \a depth (Sierpinski Sponge)
|
||||||
|
- <tt>up </tt> Increase "outer radius"
|
||||||
|
- <tt>down </tt> Decrease "outer radius"
|
||||||
|
- <tt>left </tt> Decrease "inner radius"
|
||||||
|
- <tt>right</tt> Increase "inner radius"
|
||||||
|
- <tt>PgUp </tt> Next shape-drawing function
|
||||||
|
- <tt>PgDn </tt> Prev shape-drawing function
|
||||||
|
|
||||||
|
\author Written by Nigel Stewart November 2003
|
||||||
|
|
||||||
|
\author Portions Copyright (C) 2004, the OpenGLUT project contributors. <br>
|
||||||
|
OpenGLUT branched from freeglut in February, 2004.
|
||||||
|
|
||||||
|
\image html openglut_shapes.png OpenGLUT Geometric Shapes Demonstration
|
||||||
|
\include demos/shapes/shapes.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <GL/freeglut_ext.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAKS */
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This macro is only intended to be used on arrays, of course.
|
||||||
|
*/
|
||||||
|
#define NUMBEROF(x) ((sizeof(x))/(sizeof(x[0])))
|
||||||
|
|
||||||
|
#define glRotated glRotatef
|
||||||
|
#define glTranslated glTranslatef
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These global variables control which object is drawn,
|
||||||
|
* and how it is drawn. No object uses all of these
|
||||||
|
* variables.
|
||||||
|
*/
|
||||||
|
static int function_index;
|
||||||
|
static int slices = 16;
|
||||||
|
static int stacks = 16;
|
||||||
|
static double irad = .25;
|
||||||
|
static double orad = 1.0; /* doubles as size for objects other than Torus */
|
||||||
|
static int depth = 4;
|
||||||
|
static double offset[ 3 ] = { 0, 0, 0 };
|
||||||
|
static GLboolean show_info = GL_TRUE;
|
||||||
|
static float ar;
|
||||||
|
static GLboolean persProject = GL_TRUE;
|
||||||
|
static GLboolean animateXRot = GL_FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These one-liners draw particular objects, fetching appropriate
|
||||||
|
* information from the above globals. They are just thin wrappers
|
||||||
|
* for the FreeGLUT objects.
|
||||||
|
*/
|
||||||
|
static void drawSolidTetrahedron(void) { glutSolidTetrahedron (); }
|
||||||
|
static void drawWireTetrahedron(void) { glutWireTetrahedron (); }
|
||||||
|
static void drawSolidCube(void) { glutSolidCube(orad); } /* orad doubles as size input */
|
||||||
|
static void drawWireCube(void) { glutWireCube(orad); } /* orad doubles as size input */
|
||||||
|
static void drawSolidOctahedron(void) { glutSolidOctahedron (); }
|
||||||
|
static void drawWireOctahedron(void) { glutWireOctahedron (); }
|
||||||
|
static void drawSolidDodecahedron(void) { glutSolidDodecahedron (); }
|
||||||
|
static void drawWireDodecahedron(void) { glutWireDodecahedron (); }
|
||||||
|
static void drawSolidRhombicDodecahedron(void) { glutSolidRhombicDodecahedron (); }
|
||||||
|
static void drawWireRhombicDodecahedron(void) { glutWireRhombicDodecahedron (); }
|
||||||
|
static void drawSolidIcosahedron(void) { glutSolidIcosahedron (); }
|
||||||
|
static void drawWireIcosahedron(void) { glutWireIcosahedron (); }
|
||||||
|
static void drawSolidSierpinskiSponge(void) { glutSolidSierpinskiSponge (depth, offset, orad);} /* orad doubles as size input */
|
||||||
|
static void drawWireSierpinskiSponge(void) { glutWireSierpinskiSponge (depth, offset, orad); } /* orad doubles as size input */
|
||||||
|
static void drawSolidTorus(void) { glutSolidTorus(irad,orad,slices,stacks); }
|
||||||
|
static void drawWireTorus(void) { glutWireTorus (irad,orad,slices,stacks); }
|
||||||
|
static void drawSolidSphere(void) { glutSolidSphere(orad,slices,stacks); } /* orad doubles as size input */
|
||||||
|
static void drawWireSphere(void) { glutWireSphere(orad,slices,stacks); } /* orad doubles as size input */
|
||||||
|
static void drawSolidCone(void) { glutSolidCone(orad,orad,slices,stacks); } /* orad doubles as size input */
|
||||||
|
static void drawWireCone(void) { glutWireCone(orad,orad,slices,stacks); } /* orad doubles as size input */
|
||||||
|
static void drawSolidCylinder(void) { glutSolidCylinder(orad,orad,slices,stacks); } /* orad doubles as size input */
|
||||||
|
static void drawWireCylinder(void) { glutWireCylinder(orad,orad,slices,stacks); } /* orad doubles as size input */
|
||||||
|
static void drawSolidTeapot(void)
|
||||||
|
{ glFrontFace(GL_CW); glutSolidTeapot(orad); glFrontFace(GL_CCW); /* orad doubles as size input */}
|
||||||
|
static void drawWireTeapot(void)
|
||||||
|
{ glFrontFace(GL_CW); glutWireTeapot(orad); glFrontFace(GL_CCW); /* orad doubles as size input */}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure defines an entry in our function-table.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char * const name;
|
||||||
|
void (*solid) (void);
|
||||||
|
void (*wire) (void);
|
||||||
|
} entry;
|
||||||
|
|
||||||
|
#define ENTRY(e) {#e, drawSolid##e, drawWire##e}
|
||||||
|
static const entry table [] =
|
||||||
|
{
|
||||||
|
ENTRY (Tetrahedron),
|
||||||
|
ENTRY (Cube),
|
||||||
|
ENTRY (Octahedron),
|
||||||
|
ENTRY (Dodecahedron),
|
||||||
|
ENTRY (RhombicDodecahedron),
|
||||||
|
ENTRY (Icosahedron),
|
||||||
|
ENTRY (SierpinskiSponge),
|
||||||
|
ENTRY (Teapot),
|
||||||
|
ENTRY (Torus),
|
||||||
|
ENTRY (Sphere),
|
||||||
|
ENTRY (Cone),
|
||||||
|
ENTRY (Cylinder),
|
||||||
|
/* ENTRY (Cuboctahedron) */
|
||||||
|
};
|
||||||
|
#undef ENTRY
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Does printf()-like work using freeglut
|
||||||
|
glutBitmapString(). Uses a fixed font. Prints
|
||||||
|
at the indicated row/column position.
|
||||||
|
|
||||||
|
Limitation: Cannot address pixels.
|
||||||
|
Limitation: Renders in screen coords, not model coords.
|
||||||
|
*/
|
||||||
|
static void shapesPrintf (int row, int col, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GLUT callback Handlers */
|
||||||
|
|
||||||
|
static void
|
||||||
|
resize(int width, int height)
|
||||||
|
{
|
||||||
|
ar = (float) width / (float) height;
|
||||||
|
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display(void)
|
||||||
|
{
|
||||||
|
const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
|
||||||
|
const double a = t*90.0;
|
||||||
|
const double b = (animateXRot?t:1)*60.0;
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glFrustumf(-ar, ar, -1.0, 1.0, 2.0, 100.0);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
|
||||||
|
glColor4f(1,0,0,1);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslated(0,1.2,-6);
|
||||||
|
glRotated(b,1,0,0);
|
||||||
|
glRotated(a,0,0,1);
|
||||||
|
table [function_index].solid ();
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslated(0,-1.2,-6);
|
||||||
|
glRotated(b,1,0,0);
|
||||||
|
glRotated(a,0,0,1);
|
||||||
|
table [function_index].wire ();
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glColor4f(0.1,0.1,0.4,1.0);
|
||||||
|
|
||||||
|
glutSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
key(unsigned char key, int x, int y)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case 27 :
|
||||||
|
case 'Q':
|
||||||
|
case 'q': glutLeaveMainLoop () ; break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
case 'i': show_info = ( show_info == GL_TRUE ) ? GL_FALSE : GL_TRUE; break;
|
||||||
|
|
||||||
|
case '=':
|
||||||
|
case '+': slices++; printf("%d,%d\n", slices, stacks); break;
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
case '_': if( slices > -1 ) slices--; break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
case '<': if( stacks > -1 ) stacks--; break;
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
case '>': stacks++; break;
|
||||||
|
|
||||||
|
case '9':
|
||||||
|
case '(': if( depth > -1 ) depth--; break;
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
case ')': ++depth; break;
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
case 'p': persProject=!persProject; break;
|
||||||
|
|
||||||
|
case 'R':
|
||||||
|
case 'r': animateXRot=!animateXRot; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void special (int key, int x, int y)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case GLUT_KEY_PAGE_UP: ++function_index; break;
|
||||||
|
case GLUT_KEY_PAGE_DOWN: --function_index; break;
|
||||||
|
case GLUT_KEY_UP: orad *= 2; break;
|
||||||
|
case GLUT_KEY_DOWN: orad /= 2; break;
|
||||||
|
|
||||||
|
case GLUT_KEY_RIGHT: irad *= 2; break;
|
||||||
|
case GLUT_KEY_LEFT: irad /= 2; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 > function_index)
|
||||||
|
function_index = NUMBEROF (table) - 1;
|
||||||
|
|
||||||
|
if (NUMBEROF (table) <= ( unsigned )function_index)
|
||||||
|
function_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
idle(void)
|
||||||
|
{
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
onMouseClick(int button, int state, int x, int y) {
|
||||||
|
if (state == GLUT_DOWN)
|
||||||
|
special(GLUT_KEY_PAGE_UP, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
|
||||||
|
|
||||||
|
const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
|
||||||
|
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
|
||||||
|
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
const GLfloat high_shininess[] = { 100.0f };
|
||||||
|
|
||||||
|
/* Program entry point */
|
||||||
|
|
||||||
|
void init_context() {
|
||||||
|
printf("init_context\n"); fflush(stdout);
|
||||||
|
glClearColor(1,1,1,1);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
glEnable(GL_NORMALIZE);
|
||||||
|
glEnable(GL_COLOR_MATERIAL);
|
||||||
|
|
||||||
|
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
|
||||||
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
||||||
|
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
|
||||||
|
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
|
||||||
|
|
||||||
|
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
|
||||||
|
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||||
|
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
|
||||||
|
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
glutInitWindowSize(640,480);
|
||||||
|
glutInitWindowPosition(40,40);
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
|
||||||
|
|
||||||
|
glutCreateWindow("FreeGLUT Shapes");
|
||||||
|
|
||||||
|
glutReshapeFunc(resize);
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutKeyboardFunc(key);
|
||||||
|
glutSpecialFunc(special);
|
||||||
|
glutIdleFunc(idle);
|
||||||
|
glutMouseFunc(onMouseClick);
|
||||||
|
glutInitContextFunc(init_context);
|
||||||
|
|
||||||
|
glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ;
|
||||||
|
|
||||||
|
glutMainLoop();
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* DUMP MEMORY LEAK INFORMATION */
|
||||||
|
_CrtDumpMemoryLeaks () ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* fg_cursor_android.c
|
||||||
|
*
|
||||||
|
* The Windows-specific mouse cursor related stuff.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "../fg_internal.h"
|
||||||
|
|
||||||
|
void fgPlatformSetCursor ( SFG_Window *window, int cursorID )
|
||||||
|
{
|
||||||
|
/* No-op: no visible cursor on touchscreens */
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformWarpPointer ( int x, int y )
|
||||||
|
{
|
||||||
|
/* Even if there's no pointer on touchscreen, keep track of the
|
||||||
|
last position, e.g. for menus */
|
||||||
|
SFG_Window* window = fgStructure.CurrentWindow;
|
||||||
|
window->State.MouseX = x;
|
||||||
|
window->State.MouseY = y;
|
||||||
|
/* TODO: this should simulate a fake motion event */
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* fg_ext_android.c
|
||||||
|
*
|
||||||
|
* Functions related to OpenGL extensions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
|
||||||
|
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "../fg_internal.h"
|
||||||
|
|
||||||
|
GLUTproc fgPlatformGetGLUTProcAddress( const char* procName )
|
||||||
|
{
|
||||||
|
/* optimization: quick initial check */
|
||||||
|
if( strncmp( procName, "glut", 4 ) != 0 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x;
|
||||||
|
CHECK_NAME(glutJoystickFunc);
|
||||||
|
CHECK_NAME(glutForceJoystickFunc);
|
||||||
|
CHECK_NAME(glutGameModeString);
|
||||||
|
CHECK_NAME(glutEnterGameMode);
|
||||||
|
CHECK_NAME(glutLeaveGameMode);
|
||||||
|
CHECK_NAME(glutGameModeGet);
|
||||||
|
#undef CHECK_NAME
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* fg_gamemode_x11.c
|
||||||
|
*
|
||||||
|
* The game mode handling code.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Changes the current display mode to match user's settings
|
||||||
|
*/
|
||||||
|
GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformChangeDisplayMode: STUB\n");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformEnterGameMode( void )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformEnterGameMode: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformRememberState( void )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformRememberState: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformRestoreState( void )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformRestoreState: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformLeaveGameMode( void )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformLeaveGameMode: STUB\n");
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* fg_init_android.c
|
||||||
|
*
|
||||||
|
* Various freeglut initialization functions.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "fg_init.h"
|
||||||
|
#include "egl/fg_init_egl.h"
|
||||||
|
|
||||||
|
void fgPlatformInitialize()
|
||||||
|
{
|
||||||
|
fghPlatformInitializeEGL();
|
||||||
|
|
||||||
|
/* Get start time */
|
||||||
|
fgState.Time = fgSystemTime();
|
||||||
|
|
||||||
|
fgState.Initialised = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformCloseDisplay()
|
||||||
|
{
|
||||||
|
fghPlatformCloseDisplayEGL();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close joystick and serial input devices
|
||||||
|
*/
|
||||||
|
void fgPlatformDeinitialiseInputDevices ( void )
|
||||||
|
{
|
||||||
|
fghCloseInputDevices ();
|
||||||
|
fgState.JoysticksInitialised = GL_FALSE;
|
||||||
|
fgState.InputDevsInitialised = GL_FALSE;
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* fg_input_devices_android.c
|
||||||
|
*
|
||||||
|
* Handles miscellaneous input devices via direct serial-port access.
|
||||||
|
*
|
||||||
|
* Written by Joe Krahn <krahn@niehs.nih.gov> 2005
|
||||||
|
* Copyright (c) 2005 Stephen J. Baker. All Rights Reserved.
|
||||||
|
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
|
||||||
|
* Copyright 2012 (C) Sylvain Beucler
|
||||||
|
* Creation date: Thur Feb 2 2012
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA OR STEPHEN J. BAKER BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
typedef struct _serialport SERIALPORT;
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is only used if the user calls:
|
||||||
|
* glutDeviceGet(GLUT_HAS_DIAL_AND_BUTTON_BOX)
|
||||||
|
* and has old hardware called 'dials&buttons box'.
|
||||||
|
* http://www.reputable.com/sgipix/sgi-dialnbutton1.jpg
|
||||||
|
*
|
||||||
|
* Not implemented on Android :)
|
||||||
|
* http://sourceforge.net/mailarchive/message.php?msg_id=29209505
|
||||||
|
*/
|
||||||
|
void fgPlatformRegisterDialDevice ( const char *dial_device ) {
|
||||||
|
fgWarning("GLUT_HAS_DIAL_AND_BUTTON_BOX: not implemented");
|
||||||
|
}
|
||||||
|
SERIALPORT *fg_serial_open ( const char *device ) { return NULL; }
|
||||||
|
void fg_serial_close(SERIALPORT *port) {}
|
||||||
|
int fg_serial_getchar(SERIALPORT *port) { return EOF; }
|
||||||
|
int fg_serial_putchar(SERIALPORT *port, unsigned char ch) { return 0; }
|
||||||
|
void fg_serial_flush ( SERIALPORT *port ) {}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* fg_internal_android.h
|
||||||
|
*
|
||||||
|
* The freeglut library private include file.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREEGLUT_INTERNAL_ANDROID_H
|
||||||
|
#define FREEGLUT_INTERNAL_ANDROID_H
|
||||||
|
|
||||||
|
|
||||||
|
/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */
|
||||||
|
/* Android OpenGL ES is accessed through EGL */
|
||||||
|
#include "egl/fg_internal_egl.h"
|
||||||
|
|
||||||
|
/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */
|
||||||
|
/* The structure used by display initialization in fg_init.c */
|
||||||
|
typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay;
|
||||||
|
struct android_app;
|
||||||
|
struct tagSFG_PlatformDisplay
|
||||||
|
{
|
||||||
|
struct tagSFG_PlatformDisplayEGL egl;
|
||||||
|
EGLNativeWindowType single_native_window;
|
||||||
|
struct android_app* app;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct tagSFG_PlatformContext SFG_PlatformContext;
|
||||||
|
/* SFG_PlatformContext is used for SFG_Window.Window */
|
||||||
|
struct tagSFG_PlatformContext
|
||||||
|
{
|
||||||
|
struct tagSFG_PlatformContextEGL egl;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual PAD (spots on touchscreen that simulate keys)
|
||||||
|
*/
|
||||||
|
struct vpad_state {
|
||||||
|
bool on;
|
||||||
|
bool left;
|
||||||
|
bool right;
|
||||||
|
bool up;
|
||||||
|
bool down;
|
||||||
|
};
|
||||||
|
struct touchscreen {
|
||||||
|
struct vpad_state vpad;
|
||||||
|
bool in_mmotion;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */
|
||||||
|
/*
|
||||||
|
* Initial defines from "js.h" starting around line 33 with the existing "fg_joystick.c"
|
||||||
|
* interspersed
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We'll put these values in and that should
|
||||||
|
* allow the code to at least compile when there is
|
||||||
|
* no support. The JS open routine should error out
|
||||||
|
* and shut off all the code downstream anyway and if
|
||||||
|
* the application doesn't use a joystick we'll be fine.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct JS_DATA_TYPE
|
||||||
|
{
|
||||||
|
int buttons;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
# define JS_RETURN (sizeof(struct JS_DATA_TYPE))
|
||||||
|
|
||||||
|
/* XXX It might be better to poll the operating system for the numbers of buttons and
|
||||||
|
* XXX axes and then dynamically allocate the arrays.
|
||||||
|
*/
|
||||||
|
# define _JS_MAX_AXES 16
|
||||||
|
typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick;
|
||||||
|
struct tagSFG_PlatformJoystick
|
||||||
|
{
|
||||||
|
struct JS_DATA_TYPE js;
|
||||||
|
|
||||||
|
char fname [ 128 ];
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Window's state description. This structure should be kept portable. */
|
||||||
|
typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
|
||||||
|
struct tagSFG_PlatformWindowState
|
||||||
|
{
|
||||||
|
char unused;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Menu font and color definitions */
|
||||||
|
#define FREEGLUT_MENU_FONT NULL
|
||||||
|
|
||||||
|
#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
|
||||||
|
#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f}
|
||||||
|
#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
|
||||||
|
#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f}
|
||||||
|
|
||||||
|
#endif /* FREEGLUT_INTERNAL_ANDROID_H */
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* fg_joystick_android.c
|
||||||
|
*
|
||||||
|
* Joystick handling code
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
* Written by Steve Baker, <sjbaker1@airmail.net>
|
||||||
|
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Android has no joysticks at the moment (only touchscreens/touchpads),
|
||||||
|
* but we could expose the accelerometer as a 3-axis joystick.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
|
||||||
|
{
|
||||||
|
fgWarning("fgPlatformJoystickRawRead: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformJoystickOpen( SFG_Joystick* joy )
|
||||||
|
{
|
||||||
|
fgWarning("fgPlatformJoystickOpen: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident )
|
||||||
|
{
|
||||||
|
fgWarning("fgJoystick: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformJoystickClose ( int ident )
|
||||||
|
{
|
||||||
|
fgWarning("fgPlatformJoystickClose: STUB\n");
|
||||||
|
}
|
|
@ -0,0 +1,558 @@
|
||||||
|
/*
|
||||||
|
* fg_main_android.c
|
||||||
|
*
|
||||||
|
* The Android-specific windows message processing methods.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
|
||||||
|
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "egl/fg_window_egl.h"
|
||||||
|
|
||||||
|
#include <android/log.h>
|
||||||
|
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "FreeGLUT", __VA_ARGS__))
|
||||||
|
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "FreeGLUT", __VA_ARGS__))
|
||||||
|
#include <android/native_app_glue/android_native_app_glue.h>
|
||||||
|
#include <android/keycodes.h>
|
||||||
|
|
||||||
|
extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify);
|
||||||
|
extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify);
|
||||||
|
extern void fgPlatformFullScreenToggle( SFG_Window *win );
|
||||||
|
extern void fgPlatformPositionWindow( SFG_Window *window, int x, int y );
|
||||||
|
extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height );
|
||||||
|
extern void fgPlatformPushWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformPopWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformHideWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformIconifyWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformShowWindow( SFG_Window *window );
|
||||||
|
|
||||||
|
static struct touchscreen touchscreen;
|
||||||
|
static unsigned char key_a2fg[256];
|
||||||
|
|
||||||
|
/* Cf. http://developer.android.com/reference/android/view/KeyEvent.html */
|
||||||
|
/* These codes are missing in <android/keycodes.h> */
|
||||||
|
/* Don't convert to enum, since it may conflict with future version of
|
||||||
|
that <android/keycodes.h> */
|
||||||
|
#define AKEYCODE_FORWARD_DEL 112
|
||||||
|
#define AKEYCODE_CTRL_LEFT 113
|
||||||
|
#define AKEYCODE_CTRL_RIGHT 114
|
||||||
|
#define AKEYCODE_MOVE_HOME 122
|
||||||
|
#define AKEYCODE_MOVE_END 123
|
||||||
|
#define AKEYCODE_INSERT 124
|
||||||
|
#define AKEYCODE_ESCAPE 127
|
||||||
|
#define AKEYCODE_F1 131
|
||||||
|
#define AKEYCODE_F2 132
|
||||||
|
#define AKEYCODE_F3 133
|
||||||
|
#define AKEYCODE_F4 134
|
||||||
|
#define AKEYCODE_F5 135
|
||||||
|
#define AKEYCODE_F6 136
|
||||||
|
#define AKEYCODE_F7 137
|
||||||
|
#define AKEYCODE_F8 138
|
||||||
|
#define AKEYCODE_F9 139
|
||||||
|
#define AKEYCODE_F10 140
|
||||||
|
#define AKEYCODE_F11 141
|
||||||
|
#define AKEYCODE_F12 142
|
||||||
|
|
||||||
|
#define EVENT_HANDLED 1
|
||||||
|
#define EVENT_NOT_HANDLED 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Android keycode to GLUT keycode mapping
|
||||||
|
*/
|
||||||
|
static void key_init() {
|
||||||
|
memset(key_a2fg, 0, sizeof(key_a2fg));
|
||||||
|
|
||||||
|
key_a2fg[AKEYCODE_F1] = GLUT_KEY_F1;
|
||||||
|
key_a2fg[AKEYCODE_F2] = GLUT_KEY_F2;
|
||||||
|
key_a2fg[AKEYCODE_F3] = GLUT_KEY_F3;
|
||||||
|
key_a2fg[AKEYCODE_F4] = GLUT_KEY_F4;
|
||||||
|
key_a2fg[AKEYCODE_F5] = GLUT_KEY_F5;
|
||||||
|
key_a2fg[AKEYCODE_F6] = GLUT_KEY_F6;
|
||||||
|
key_a2fg[AKEYCODE_F7] = GLUT_KEY_F7;
|
||||||
|
key_a2fg[AKEYCODE_F8] = GLUT_KEY_F8;
|
||||||
|
key_a2fg[AKEYCODE_F9] = GLUT_KEY_F9;
|
||||||
|
key_a2fg[AKEYCODE_F10] = GLUT_KEY_F10;
|
||||||
|
key_a2fg[AKEYCODE_F11] = GLUT_KEY_F11;
|
||||||
|
key_a2fg[AKEYCODE_F12] = GLUT_KEY_F12;
|
||||||
|
|
||||||
|
key_a2fg[AKEYCODE_PAGE_UP] = GLUT_KEY_PAGE_UP;
|
||||||
|
key_a2fg[AKEYCODE_PAGE_DOWN] = GLUT_KEY_PAGE_DOWN;
|
||||||
|
key_a2fg[AKEYCODE_MOVE_HOME] = GLUT_KEY_HOME;
|
||||||
|
key_a2fg[AKEYCODE_MOVE_END] = GLUT_KEY_END;
|
||||||
|
key_a2fg[AKEYCODE_INSERT] = GLUT_KEY_INSERT;
|
||||||
|
|
||||||
|
key_a2fg[AKEYCODE_DPAD_UP] = GLUT_KEY_UP;
|
||||||
|
key_a2fg[AKEYCODE_DPAD_DOWN] = GLUT_KEY_DOWN;
|
||||||
|
key_a2fg[AKEYCODE_DPAD_LEFT] = GLUT_KEY_LEFT;
|
||||||
|
key_a2fg[AKEYCODE_DPAD_RIGHT] = GLUT_KEY_RIGHT;
|
||||||
|
|
||||||
|
key_a2fg[AKEYCODE_ALT_LEFT] = GLUT_KEY_ALT_L;
|
||||||
|
key_a2fg[AKEYCODE_ALT_RIGHT] = GLUT_KEY_ALT_R;
|
||||||
|
key_a2fg[AKEYCODE_SHIFT_LEFT] = GLUT_KEY_SHIFT_L;
|
||||||
|
key_a2fg[AKEYCODE_SHIFT_RIGHT] = GLUT_KEY_SHIFT_R;
|
||||||
|
key_a2fg[AKEYCODE_CTRL_LEFT] = GLUT_KEY_CTRL_L;
|
||||||
|
key_a2fg[AKEYCODE_CTRL_RIGHT] = GLUT_KEY_CTRL_R;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an Android key event to ASCII.
|
||||||
|
*/
|
||||||
|
static unsigned char key_ascii(struct android_app* app, AInputEvent* event) {
|
||||||
|
int32_t code = AKeyEvent_getKeyCode(event);
|
||||||
|
|
||||||
|
/* Handle a few special cases: */
|
||||||
|
switch (code) {
|
||||||
|
case AKEYCODE_DEL:
|
||||||
|
return 8;
|
||||||
|
case AKEYCODE_FORWARD_DEL:
|
||||||
|
return 127;
|
||||||
|
case AKEYCODE_ESCAPE:
|
||||||
|
return 27;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get usable JNI context */
|
||||||
|
JNIEnv* env = app->activity->env;
|
||||||
|
JavaVM* vm = app->activity->vm;
|
||||||
|
(*vm)->AttachCurrentThread(vm, &env, NULL);
|
||||||
|
|
||||||
|
jclass KeyEventClass = (*env)->FindClass(env, "android/view/KeyEvent");
|
||||||
|
jmethodID KeyEventConstructor = (*env)->GetMethodID(env, KeyEventClass, "<init>", "(II)V");
|
||||||
|
jobject keyEvent = (*env)->NewObject(env, KeyEventClass, KeyEventConstructor,
|
||||||
|
AKeyEvent_getAction(event), AKeyEvent_getKeyCode(event));
|
||||||
|
jmethodID KeyEvent_getUnicodeChar = (*env)->GetMethodID(env, KeyEventClass, "getUnicodeChar", "(I)I");
|
||||||
|
int ascii = (*env)->CallIntMethod(env, keyEvent, KeyEvent_getUnicodeChar, AKeyEvent_getMetaState(event));
|
||||||
|
|
||||||
|
/* LOGI("getUnicodeChar(%d) = %d ('%c')", AKeyEvent_getKeyCode(event), ascii, ascii); */
|
||||||
|
(*vm)->DetachCurrentThread(vm);
|
||||||
|
|
||||||
|
return ascii;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long fgPlatformSystemTime ( void )
|
||||||
|
{
|
||||||
|
struct timeval now;
|
||||||
|
gettimeofday( &now, NULL );
|
||||||
|
return now.tv_usec/1000 + now.tv_sec*1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does the magic required to relinquish the CPU until something interesting
|
||||||
|
* happens.
|
||||||
|
*/
|
||||||
|
void fgPlatformSleepForEvents( fg_time_t msec )
|
||||||
|
{
|
||||||
|
/* Android's NativeActivity relies on a Looper/ALooper object to
|
||||||
|
notify about events. The Looper object is plugged on two
|
||||||
|
internal pipe(2)s to detect system and input events. Sadly you
|
||||||
|
can only ask the Looper for an event, not just ask whether
|
||||||
|
there is a pending event (and process it later). Consequently,
|
||||||
|
short of redesigning NativeActivity, we cannot
|
||||||
|
SleepForEvents. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the next input event.
|
||||||
|
*/
|
||||||
|
int32_t handle_input(struct android_app* app, AInputEvent* event) {
|
||||||
|
SFG_Window* window = fgWindowByHandle(app->window);
|
||||||
|
if (window == NULL)
|
||||||
|
return EVENT_NOT_HANDLED;
|
||||||
|
|
||||||
|
/* FIXME: in Android, when a key is repeated, down
|
||||||
|
and up events happen most often at the exact same time. This
|
||||||
|
makes it impossible to animate based on key press time. */
|
||||||
|
/* e.g. down/up/wait/down/up rather than down/wait/down/wait/up */
|
||||||
|
/* This looks like a bug in the Android virtual keyboard system :/
|
||||||
|
Real buttons such as the Back button appear to work correctly
|
||||||
|
(series of down events with proper getRepeatCount value). */
|
||||||
|
|
||||||
|
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
|
||||||
|
/* LOGI("action: %d", AKeyEvent_getAction(event)); */
|
||||||
|
/* LOGI("keycode: %d", code); */
|
||||||
|
int32_t code = AKeyEvent_getKeyCode(event);
|
||||||
|
|
||||||
|
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) {
|
||||||
|
int32_t keypress = 0;
|
||||||
|
unsigned char ascii = 0;
|
||||||
|
if ((keypress = key_a2fg[code]) && FETCH_WCB(*window, Special)) {
|
||||||
|
INVOKE_WCB(*window, Special, (keypress, window->State.MouseX, window->State.MouseY));
|
||||||
|
return EVENT_HANDLED;
|
||||||
|
} else if ((ascii = key_ascii(app, event)) && FETCH_WCB(*window, Keyboard)) {
|
||||||
|
INVOKE_WCB(*window, Keyboard, (ascii, window->State.MouseX, window->State.MouseY));
|
||||||
|
return EVENT_HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) {
|
||||||
|
int32_t keypress = 0;
|
||||||
|
unsigned char ascii = 0;
|
||||||
|
if ((keypress = key_a2fg[code]) && FETCH_WCB(*window, Special)) {
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (keypress, window->State.MouseX, window->State.MouseY));
|
||||||
|
return EVENT_HANDLED;
|
||||||
|
} else if ((ascii = key_ascii(app, event)) && FETCH_WCB(*window, Keyboard)) {
|
||||||
|
INVOKE_WCB(*window, KeyboardUp, (ascii, window->State.MouseX, window->State.MouseY));
|
||||||
|
return EVENT_HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t source = AInputEvent_getSource(event);
|
||||||
|
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION
|
||||||
|
&& source == AINPUT_SOURCE_TOUCHSCREEN) {
|
||||||
|
int32_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK;
|
||||||
|
/* Pointer ID for clicks */
|
||||||
|
int32_t pidx = AMotionEvent_getAction(event) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||||
|
/* TODO: Handle multi-touch; also handle multiple sources/devices */
|
||||||
|
/* cf. http://sourceforge.net/mailarchive/forum.php?thread_name=20120518071314.GA28061%40perso.beuc.net&forum_name=freeglut-developer */
|
||||||
|
if (0) {
|
||||||
|
LOGI("motion action=%d index=%d source=%d", action, pidx, source);
|
||||||
|
int count = AMotionEvent_getPointerCount(event);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
LOGI("multi(%d): %.01f,%.01f",
|
||||||
|
AMotionEvent_getPointerId(event, i),
|
||||||
|
AMotionEvent_getX(event, i), AMotionEvent_getY(event, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float x = AMotionEvent_getX(event, 0);
|
||||||
|
float y = AMotionEvent_getY(event, 0);
|
||||||
|
|
||||||
|
/* Virtual arrows PAD */
|
||||||
|
/* Don't interfere with existing mouse move event */
|
||||||
|
if (!touchscreen.in_mmotion) {
|
||||||
|
struct vpad_state prev_vpad = touchscreen.vpad;
|
||||||
|
touchscreen.vpad.left = touchscreen.vpad.right
|
||||||
|
= touchscreen.vpad.up = touchscreen.vpad.down = false;
|
||||||
|
|
||||||
|
/* int32_t width = ANativeWindow_getWidth(window->Window.Handle); */
|
||||||
|
int32_t height = ANativeWindow_getHeight(window->Window.Handle);
|
||||||
|
if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_MOVE) {
|
||||||
|
if ((x > 0 && x < 100) && (y > (height - 100) && y < height))
|
||||||
|
touchscreen.vpad.left = true;
|
||||||
|
if ((x > 200 && x < 300) && (y > (height - 100) && y < height))
|
||||||
|
touchscreen.vpad.right = true;
|
||||||
|
if ((x > 100 && x < 200) && (y > (height - 100) && y < height))
|
||||||
|
touchscreen.vpad.down = true;
|
||||||
|
if ((x > 100 && x < 200) && (y > (height - 200) && y < (height - 100)))
|
||||||
|
touchscreen.vpad.up = true;
|
||||||
|
}
|
||||||
|
if (action == AMOTION_EVENT_ACTION_DOWN &&
|
||||||
|
(touchscreen.vpad.left || touchscreen.vpad.right || touchscreen.vpad.down || touchscreen.vpad.up))
|
||||||
|
touchscreen.vpad.on = true;
|
||||||
|
if (action == AMOTION_EVENT_ACTION_UP)
|
||||||
|
touchscreen.vpad.on = false;
|
||||||
|
if (prev_vpad.left != touchscreen.vpad.left
|
||||||
|
|| prev_vpad.right != touchscreen.vpad.right
|
||||||
|
|| prev_vpad.up != touchscreen.vpad.up
|
||||||
|
|| prev_vpad.down != touchscreen.vpad.down
|
||||||
|
|| prev_vpad.on != touchscreen.vpad.on) {
|
||||||
|
if (FETCH_WCB(*window, Special)) {
|
||||||
|
if (prev_vpad.left == false && touchscreen.vpad.left == true)
|
||||||
|
INVOKE_WCB(*window, Special, (GLUT_KEY_LEFT, x, y));
|
||||||
|
else if (prev_vpad.right == false && touchscreen.vpad.right == true)
|
||||||
|
INVOKE_WCB(*window, Special, (GLUT_KEY_RIGHT, x, y));
|
||||||
|
else if (prev_vpad.up == false && touchscreen.vpad.up == true)
|
||||||
|
INVOKE_WCB(*window, Special, (GLUT_KEY_UP, x, y));
|
||||||
|
else if (prev_vpad.down == false && touchscreen.vpad.down == true)
|
||||||
|
INVOKE_WCB(*window, Special, (GLUT_KEY_DOWN, x, y));
|
||||||
|
}
|
||||||
|
if (FETCH_WCB(*window, SpecialUp)) {
|
||||||
|
if (prev_vpad.left == true && touchscreen.vpad.left == false)
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_LEFT, x, y));
|
||||||
|
if (prev_vpad.right == true && touchscreen.vpad.right == false)
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_RIGHT, x, y));
|
||||||
|
if (prev_vpad.up == true && touchscreen.vpad.up == false)
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_UP, x, y));
|
||||||
|
if (prev_vpad.down == true && touchscreen.vpad.down == false)
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_DOWN, x, y));
|
||||||
|
}
|
||||||
|
return EVENT_HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normal mouse events */
|
||||||
|
if (!touchscreen.vpad.on) {
|
||||||
|
window->State.MouseX = x;
|
||||||
|
window->State.MouseY = y;
|
||||||
|
if (action == AMOTION_EVENT_ACTION_DOWN && FETCH_WCB(*window, Mouse)) {
|
||||||
|
touchscreen.in_mmotion = true;
|
||||||
|
INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_DOWN, x, y));
|
||||||
|
} else if (action == AMOTION_EVENT_ACTION_UP && FETCH_WCB(*window, Mouse)) {
|
||||||
|
touchscreen.in_mmotion = false;
|
||||||
|
INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_UP, x, y));
|
||||||
|
} else if (action == AMOTION_EVENT_ACTION_MOVE && FETCH_WCB(*window, Motion)) {
|
||||||
|
INVOKE_WCB(*window, Motion, (x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EVENT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let Android handle other events (e.g. Back and Menu buttons) */
|
||||||
|
return EVENT_NOT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the next main command.
|
||||||
|
*/
|
||||||
|
void handle_cmd(struct android_app* app, int32_t cmd) {
|
||||||
|
SFG_Window* window = fgWindowByHandle(app->window); /* may be NULL */
|
||||||
|
switch (cmd) {
|
||||||
|
/* App life cycle, in that order: */
|
||||||
|
case APP_CMD_START:
|
||||||
|
LOGI("handle_cmd: APP_CMD_START");
|
||||||
|
break;
|
||||||
|
case APP_CMD_RESUME:
|
||||||
|
LOGI("handle_cmd: APP_CMD_RESUME");
|
||||||
|
/* Cf. fgPlatformProcessSingleEvent */
|
||||||
|
break;
|
||||||
|
case APP_CMD_INIT_WINDOW: /* surfaceCreated */
|
||||||
|
/* The window is being shown, get it ready. */
|
||||||
|
LOGI("handle_cmd: APP_CMD_INIT_WINDOW %p", app->window);
|
||||||
|
fgDisplay.pDisplay.single_native_window = app->window;
|
||||||
|
/* start|resume: glPlatformOpenWindow was waiting for Handle to be
|
||||||
|
defined and will now continue processing */
|
||||||
|
break;
|
||||||
|
case APP_CMD_GAINED_FOCUS:
|
||||||
|
LOGI("handle_cmd: APP_CMD_GAINED_FOCUS");
|
||||||
|
break;
|
||||||
|
case APP_CMD_WINDOW_RESIZED:
|
||||||
|
LOGI("handle_cmd: APP_CMD_WINDOW_RESIZED");
|
||||||
|
if (window->Window.pContext.egl.Surface != EGL_NO_SURFACE)
|
||||||
|
/* Make ProcessSingleEvent detect the new size, only available
|
||||||
|
after the next SwapBuffer */
|
||||||
|
glutPostRedisplay();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_SAVE_STATE: /* onSaveInstanceState */
|
||||||
|
/* The system has asked us to save our current state, when it
|
||||||
|
pauses the application without destroying it right after. */
|
||||||
|
app->savedState = strdup("Detect me as non-NULL on next android_main");
|
||||||
|
app->savedStateSize = strlen(app->savedState) + 1;
|
||||||
|
LOGI("handle_cmd: APP_CMD_SAVE_STATE");
|
||||||
|
break;
|
||||||
|
case APP_CMD_PAUSE:
|
||||||
|
LOGI("handle_cmd: APP_CMD_PAUSE");
|
||||||
|
/* Cf. fgPlatformProcessSingleEvent */
|
||||||
|
break;
|
||||||
|
case APP_CMD_LOST_FOCUS:
|
||||||
|
LOGI("handle_cmd: APP_CMD_LOST_FOCUS");
|
||||||
|
break;
|
||||||
|
case APP_CMD_TERM_WINDOW: /* surfaceDestroyed */
|
||||||
|
/* The application is being hidden, but may be restored */
|
||||||
|
LOGI("handle_cmd: APP_CMD_TERM_WINDOW");
|
||||||
|
fghPlatformCloseWindowEGL(window);
|
||||||
|
fgDisplay.pDisplay.single_native_window = NULL;
|
||||||
|
break;
|
||||||
|
case APP_CMD_STOP:
|
||||||
|
LOGI("handle_cmd: APP_CMD_STOP");
|
||||||
|
break;
|
||||||
|
case APP_CMD_DESTROY: /* Activity.onDestroy */
|
||||||
|
LOGI("handle_cmd: APP_CMD_DESTROY");
|
||||||
|
/* User closed the application for good, let's kill the window */
|
||||||
|
{
|
||||||
|
/* Can't use fgWindowByHandle as app->window is NULL */
|
||||||
|
SFG_Window* window = fgStructure.CurrentWindow;
|
||||||
|
if (window != NULL) {
|
||||||
|
fgDestroyWindow(window);
|
||||||
|
} else {
|
||||||
|
LOGI("APP_CMD_DESTROY: No current window");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* glue has already set android_app->destroyRequested=1 */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_CONFIG_CHANGED:
|
||||||
|
/* Handle rotation / orientation change */
|
||||||
|
LOGI("handle_cmd: APP_CMD_CONFIG_CHANGED");
|
||||||
|
break;
|
||||||
|
case APP_CMD_LOW_MEMORY:
|
||||||
|
LOGI("handle_cmd: APP_CMD_LOW_MEMORY");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGI("handle_cmd: unhandled cmd=%d", cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformOpenWindow( SFG_Window* window, const char* title,
|
||||||
|
GLboolean positionUse, int x, int y,
|
||||||
|
GLboolean sizeUse, int w, int h,
|
||||||
|
GLboolean gameMode, GLboolean isSubWindow );
|
||||||
|
|
||||||
|
void fgPlatformProcessSingleEvent ( void )
|
||||||
|
{
|
||||||
|
/* When the screen is resized, the window handle still points to the
|
||||||
|
old window until the next SwapBuffer, while it's crucial to set
|
||||||
|
the size (onShape) correctly before the next onDisplay callback.
|
||||||
|
Plus we don't know if the next SwapBuffer already occurred at the
|
||||||
|
time we process the event (e.g. during onDisplay). */
|
||||||
|
/* So we do the check each time rather than on event. */
|
||||||
|
/* Interestingly, on a Samsung Galaxy S/PowerVR SGX540 GPU/Android
|
||||||
|
2.3, that next SwapBuffer is fake (but still necessary to get the
|
||||||
|
new size). */
|
||||||
|
SFG_Window* window = fgStructure.CurrentWindow;
|
||||||
|
if (window != NULL && window->Window.Handle != NULL) {
|
||||||
|
int32_t width = ANativeWindow_getWidth(window->Window.Handle);
|
||||||
|
int32_t height = ANativeWindow_getHeight(window->Window.Handle);
|
||||||
|
fghOnReshapeNotify(window,width,height,GL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read pending event. */
|
||||||
|
int ident;
|
||||||
|
int events;
|
||||||
|
struct android_poll_source* source;
|
||||||
|
/* This is called "ProcessSingleEvent" but this means we'd only
|
||||||
|
process ~60 (screen Hz) mouse events per second, plus other ports
|
||||||
|
are processing all events already. So let's process all pending
|
||||||
|
events. */
|
||||||
|
/* if ((ident=ALooper_pollOnce(0, NULL, &events, (void**)&source)) >= 0) { */
|
||||||
|
while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) {
|
||||||
|
/* Process this event. */
|
||||||
|
if (source != NULL) {
|
||||||
|
source->process(source->app, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're not in RESUME state, Android paused us, so wait */
|
||||||
|
struct android_app* app = fgDisplay.pDisplay.app;
|
||||||
|
if (app->destroyRequested != 1 && app->activityState != APP_CMD_RESUME) {
|
||||||
|
INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_PAUSE));
|
||||||
|
|
||||||
|
int FOREVER = -1;
|
||||||
|
while (app->destroyRequested != 1 && (app->activityState != APP_CMD_RESUME)) {
|
||||||
|
if ((ident=ALooper_pollOnce(FOREVER, NULL, &events, (void**)&source)) >= 0) {
|
||||||
|
/* Process this event. */
|
||||||
|
if (source != NULL) {
|
||||||
|
source->process(source->app, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Coming back from a pause: */
|
||||||
|
/* - Recreate window context and surface */
|
||||||
|
/* - Call user-defined hook to restore resources (textures...) */
|
||||||
|
/* - Exit pause loop */
|
||||||
|
if (app->destroyRequested != 1) {
|
||||||
|
/* Android is full-screen only, simplified call.. */
|
||||||
|
/* Ideally we'd have a fgPlatformReopenWindow() */
|
||||||
|
/* If we're hidden by a non-fullscreen or translucent activity,
|
||||||
|
we'll be paused but not stopped, and keep the current
|
||||||
|
surface; in which case fgPlatformOpenWindow will no-op. */
|
||||||
|
fgPlatformOpenWindow(window, "", GL_FALSE, 0, 0, GL_FALSE, 0, 0, GL_FALSE, GL_FALSE);
|
||||||
|
|
||||||
|
/* TODO: should there be a whole GLUT_INIT_WORK forced? probably...
|
||||||
|
* Could queue that up in APP_CMD_TERM_WINDOW handler, but it'll
|
||||||
|
* be not possible to ensure InitContext CB gets called before
|
||||||
|
* Resume CB like that.. so maybe just force calling initContext CB
|
||||||
|
* here is best. Or we could force work on the window in question..
|
||||||
|
* 1) save old work mask, 2) set mask to init only, 3) call fgProcessWork directly
|
||||||
|
* 4) set work mask back to the one saved in step 1.
|
||||||
|
*/
|
||||||
|
if (!FETCH_WCB(*window, InitContext))
|
||||||
|
fgWarning("Resuming application, but no callback to reload context resources (glutInitContextFunc)");
|
||||||
|
}
|
||||||
|
|
||||||
|
INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_RESUME));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformMainLoopPreliminaryWork ( void )
|
||||||
|
{
|
||||||
|
LOGI("fgPlatformMainLoopPreliminaryWork\n");
|
||||||
|
|
||||||
|
key_init();
|
||||||
|
|
||||||
|
/* Make sure glue isn't stripped. */
|
||||||
|
/* JNI entry points need to be bundled even when linking statically */
|
||||||
|
app_dummy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deal with work list items */
|
||||||
|
void fgPlatformInitWork(SFG_Window* window)
|
||||||
|
{
|
||||||
|
/* notify windowStatus/visibility */
|
||||||
|
INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) );
|
||||||
|
|
||||||
|
/* Position callback, always at 0,0 */
|
||||||
|
fghOnPositionNotify(window, 0, 0, GL_TRUE);
|
||||||
|
|
||||||
|
/* Size gets notified on window creation with size detection in mainloop above
|
||||||
|
* XXX CHECK: does this messages happen too early like on windows,
|
||||||
|
* so client code cannot have registered a callback yet and the message
|
||||||
|
* is thus never received by client?
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask)
|
||||||
|
{
|
||||||
|
if (workMask & GLUT_FULL_SCREEN_WORK)
|
||||||
|
fgPlatformFullScreenToggle( window );
|
||||||
|
if (workMask & GLUT_POSITION_WORK)
|
||||||
|
fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos );
|
||||||
|
if (workMask & GLUT_SIZE_WORK)
|
||||||
|
fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight );
|
||||||
|
if (workMask & GLUT_ZORDER_WORK)
|
||||||
|
{
|
||||||
|
if (window->State.DesiredZOrder < 0)
|
||||||
|
fgPlatformPushWindow( window );
|
||||||
|
else
|
||||||
|
fgPlatformPopWindow( window );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformVisibilityWork(SFG_Window* window)
|
||||||
|
{
|
||||||
|
/* Visibility status of window should get updated in the window message handlers
|
||||||
|
* For now, none of these functions called below do anything, so don't worry
|
||||||
|
* about it
|
||||||
|
*/
|
||||||
|
SFG_Window *win = window;
|
||||||
|
switch (window->State.DesiredVisibility)
|
||||||
|
{
|
||||||
|
case DesireHiddenState:
|
||||||
|
fgPlatformHideWindow( window );
|
||||||
|
break;
|
||||||
|
case DesireIconicState:
|
||||||
|
/* Call on top-level window */
|
||||||
|
while (win->Parent)
|
||||||
|
win = win->Parent;
|
||||||
|
fgPlatformIconifyWindow( win );
|
||||||
|
break;
|
||||||
|
case DesireNormalState:
|
||||||
|
fgPlatformShowWindow( window );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dummy functions, not applicable on android */
|
||||||
|
void fgPlatformSetColor(int idx, float r, float g, float b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float fgPlatformGetColor(int idx, int comp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformCopyColormap(int win)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* fg_main_android.h
|
||||||
|
*
|
||||||
|
* The Android-specific windows message processing methods.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FG_MAIN_ANDROID_H__
|
||||||
|
#define __FG_MAIN_ANDROID_H__
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
|
||||||
|
extern void fgPlatformProcessSingleEvent(void);
|
||||||
|
extern unsigned long fgPlatformSystemTime(void);
|
||||||
|
extern void fgPlatformSleepForEvents(fg_time_t msec);
|
||||||
|
extern void fgPlatformMainLoopPreliminaryWork(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,169 @@
|
||||||
|
/*
|
||||||
|
* fg_runtime_android.c
|
||||||
|
*
|
||||||
|
* Android runtime
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Parts taken from Android NDK's 'native-activity' sample: */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <android/asset_manager.h>
|
||||||
|
#include <android/native_window.h>
|
||||||
|
#include "android/native_app_glue/android_native_app_glue.h"
|
||||||
|
#include "android/fg_main_android.h"
|
||||||
|
|
||||||
|
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "FreeGLUT-jnicb", __VA_ARGS__))
|
||||||
|
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "FreeGLUT-jnicb", __VA_ARGS__))
|
||||||
|
|
||||||
|
/* Cf. fg_main_android.c */
|
||||||
|
extern int32_t handle_input(struct android_app* app, AInputEvent* event);
|
||||||
|
extern void handle_cmd(struct android_app* app, int32_t cmd);
|
||||||
|
|
||||||
|
extern int main(int argc, char* argv[]);
|
||||||
|
|
||||||
|
/** NativeActivity Callbacks **/
|
||||||
|
/* Caution: they are called in the native_activity thread, not the
|
||||||
|
FreeGLUT thread. Use android_app_write_cmd. */
|
||||||
|
|
||||||
|
/* Could be used instead of onNativeWindowRedrawNeeded */
|
||||||
|
/* Deals with status bar presence */
|
||||||
|
static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) {
|
||||||
|
LOGI("onContentRectChanged: l=%d,t=%d,r=%d,b=%d", rect->left, rect->top, rect->right, rect->bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bug: not called during a resize in android-9, only once on startup :/ */
|
||||||
|
static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) {
|
||||||
|
LOGI("onNativeWindowResized: %p\n", (void*)activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called after a resize, compensate broken onNativeWindowResized */
|
||||||
|
static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) {
|
||||||
|
LOGI("onNativeWindowRedrawNeeded: %p\n", (void*)activity);
|
||||||
|
struct android_app* app = (struct android_app*)activity->instance;
|
||||||
|
android_app_write_cmd(app, APP_CMD_WINDOW_RESIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract all .apk assets to the application directory so they can be
|
||||||
|
* accessed using accessed.
|
||||||
|
* TODO: parse directories recursively
|
||||||
|
*/
|
||||||
|
static void extract_assets(struct android_app* app) {
|
||||||
|
/* Get usable JNI context */
|
||||||
|
JNIEnv* env = app->activity->env;
|
||||||
|
JavaVM* vm = app->activity->vm;
|
||||||
|
(*vm)->AttachCurrentThread(vm, &env, NULL);
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Get a handle on our calling NativeActivity class */
|
||||||
|
jclass activityClass = (*env)->GetObjectClass(env, app->activity->clazz);
|
||||||
|
|
||||||
|
/* Get path to cache dir (/data/data/org.myapp/cache) */
|
||||||
|
jmethodID getCacheDir = (*env)->GetMethodID(env, activityClass, "getCacheDir", "()Ljava/io/File;");
|
||||||
|
jobject file = (*env)->CallObjectMethod(env, app->activity->clazz, getCacheDir);
|
||||||
|
jclass fileClass = (*env)->FindClass(env, "java/io/File");
|
||||||
|
jmethodID getAbsolutePath = (*env)->GetMethodID(env, fileClass, "getAbsolutePath", "()Ljava/lang/String;");
|
||||||
|
jstring jpath = (jstring)(*env)->CallObjectMethod(env, file, getAbsolutePath);
|
||||||
|
const char* app_dir = (*env)->GetStringUTFChars(env, jpath, NULL);
|
||||||
|
|
||||||
|
/* chdir in the application cache directory */
|
||||||
|
LOGI("app_dir: %s", app_dir);
|
||||||
|
chdir(app_dir);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, jpath, app_dir);
|
||||||
|
|
||||||
|
/* Pre-extract assets, to avoid Android-specific file opening */
|
||||||
|
{
|
||||||
|
AAssetManager* mgr = app->activity->assetManager;
|
||||||
|
AAssetDir* assetDir = AAssetManager_openDir(mgr, "");
|
||||||
|
const char* filename = (const char*)NULL;
|
||||||
|
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
|
||||||
|
AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
int nb_read = 0;
|
||||||
|
FILE* out = fopen(filename, "w");
|
||||||
|
while ((nb_read = AAsset_read(asset, buf, BUFSIZ)) > 0)
|
||||||
|
fwrite(buf, nb_read, 1, out);
|
||||||
|
fclose(out);
|
||||||
|
AAsset_close(asset);
|
||||||
|
}
|
||||||
|
AAssetDir_close(assetDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*vm)->DetachCurrentThread(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the main entry point of a native application that is using
|
||||||
|
* android_native_app_glue. It runs in its own thread, with its own
|
||||||
|
* event loop for receiving input events and doing other things.
|
||||||
|
*/
|
||||||
|
void android_main(struct android_app* app) {
|
||||||
|
LOGI("android_main savedState=%p", app->savedState);
|
||||||
|
|
||||||
|
/* Register window resize callback */
|
||||||
|
app->activity->callbacks->onNativeWindowResized = onNativeWindowResized;
|
||||||
|
app->activity->callbacks->onContentRectChanged = onContentRectChanged;
|
||||||
|
app->activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
|
||||||
|
|
||||||
|
app->onAppCmd = handle_cmd;
|
||||||
|
app->onInputEvent = handle_input;
|
||||||
|
|
||||||
|
extract_assets(app);
|
||||||
|
|
||||||
|
/* Call user's main */
|
||||||
|
{
|
||||||
|
char progname[5] = "self";
|
||||||
|
char* argv[] = {progname, NULL};
|
||||||
|
fgDisplay.pDisplay.app = app;
|
||||||
|
main(1, argv);
|
||||||
|
/* FreeGLUT will exit() by itself if
|
||||||
|
GLUT_ACTION_ON_WINDOW_CLOSE == GLUT_ACTION_EXIT */
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGI("android_main: end");
|
||||||
|
|
||||||
|
/* Let NativeActivity restart us */
|
||||||
|
/* Users may want to forcibly exit() in their main() anyway because
|
||||||
|
NativeActivity doesn't dlclose() us, so all statically-assigned
|
||||||
|
variables keep their old values on restart.. */
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* fg_spaceball_android.c
|
||||||
|
*
|
||||||
|
* Spaceball support for Windows
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
|
||||||
|
* Written by Evan Felix <karcaw at gmail.com>
|
||||||
|
* Creation date: Sat Feb 4, 2012
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This code is a very complicated way of doing nothing.
|
||||||
|
* But is needed for Android platform builds.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
|
||||||
|
void fgPlatformInitializeSpaceball(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformSpaceballClose(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fgPlatformHasSpaceball(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fgPlatformSpaceballNumButtons(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformSpaceballSetWindow(SFG_Window *window)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* fg_state_android.c
|
||||||
|
*
|
||||||
|
* Android-specific freeglut state query methods.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
|
||||||
|
* Written by John F. Fay, <fayjf@sourceforge.net>
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <android/native_window.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "egl/fg_state_egl.h"
|
||||||
|
|
||||||
|
int fgPlatformGlutDeviceGet ( GLenum eWhat )
|
||||||
|
{
|
||||||
|
switch( eWhat )
|
||||||
|
{
|
||||||
|
case GLUT_HAS_KEYBOARD:
|
||||||
|
/* Android has a keyboard, though it may be virtual. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case GLUT_HAS_MOUSE:
|
||||||
|
/* Android has a touchscreen; until we get proper touchscreen
|
||||||
|
support, consider it as a mouse. */
|
||||||
|
return 1 ;
|
||||||
|
|
||||||
|
case GLUT_NUM_MOUSE_BUTTONS:
|
||||||
|
/* Android has a touchscreen; until we get proper touchscreen
|
||||||
|
support, consider it as a 1-button mouse. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And now -- the failure. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fgPlatformGlutGet ( GLenum eWhat )
|
||||||
|
{
|
||||||
|
switch (eWhat) {
|
||||||
|
/* One full-screen window only */
|
||||||
|
case GLUT_WINDOW_X:
|
||||||
|
case GLUT_WINDOW_Y:
|
||||||
|
case GLUT_WINDOW_BORDER_WIDTH:
|
||||||
|
case GLUT_WINDOW_HEADER_HEIGHT:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case GLUT_WINDOW_WIDTH:
|
||||||
|
case GLUT_WINDOW_HEIGHT:
|
||||||
|
{
|
||||||
|
if ( fgStructure.CurrentWindow == NULL )
|
||||||
|
return 0;
|
||||||
|
int32_t width = ANativeWindow_getWidth(fgStructure.CurrentWindow->Window.Handle);
|
||||||
|
int32_t height = ANativeWindow_getHeight(fgStructure.CurrentWindow->Window.Handle);
|
||||||
|
switch ( eWhat )
|
||||||
|
{
|
||||||
|
case GLUT_WINDOW_WIDTH:
|
||||||
|
return width;
|
||||||
|
case GLUT_WINDOW_HEIGHT:
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLUT_WINDOW_COLORMAP_SIZE:
|
||||||
|
/* 0 for RGBA/non-indexed mode */
|
||||||
|
/* Under Android and GLES more generally, no indexed-mode */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fghPlatformGlutGetEGL(eWhat);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* fg_structure_android.c
|
||||||
|
*
|
||||||
|
* Windows and menus need tree structure
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "egl/fg_structure_egl.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize default platform-specific fields in SFG_Window
|
||||||
|
*/
|
||||||
|
void fgPlatformCreateWindow ( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fghPlatformCreateWindowEGL(window);
|
||||||
|
}
|
|
@ -0,0 +1,183 @@
|
||||||
|
/*
|
||||||
|
* fg_window_android.c
|
||||||
|
*
|
||||||
|
* Window management methods for Android
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
|
||||||
|
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FREEGLUT_BUILDING_LIB
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "egl/fg_window_egl.h"
|
||||||
|
#include <android/native_app_glue/android_native_app_glue.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opens a window. Requires a SFG_Window object created and attached
|
||||||
|
* to the freeglut structure. OpenGL context is created here.
|
||||||
|
*/
|
||||||
|
void fgPlatformOpenWindow( SFG_Window* window, const char* title,
|
||||||
|
GLboolean positionUse, int x, int y,
|
||||||
|
GLboolean sizeUse, int w, int h,
|
||||||
|
GLboolean gameMode, GLboolean isSubWindow )
|
||||||
|
{
|
||||||
|
/* TODO: only one full-screen window possible? */
|
||||||
|
if (fgDisplay.pDisplay.single_native_window != NULL) {
|
||||||
|
fgWarning("You can't have more than one window on Android");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First, wait until Activity surface is available */
|
||||||
|
/* Normally events are processed through glutMainLoop(), but the
|
||||||
|
user didn't call it yet, and the Android may not have initialized
|
||||||
|
the View yet. So we need to wait for that to happen. */
|
||||||
|
/* We can't return from this function before the OpenGL context is
|
||||||
|
properly made current with a valid surface. So we wait for the
|
||||||
|
surface. */
|
||||||
|
while (fgDisplay.pDisplay.single_native_window == NULL) {
|
||||||
|
/* APP_CMD_INIT_WINDOW will do the job */
|
||||||
|
int ident;
|
||||||
|
int events;
|
||||||
|
struct android_poll_source* source;
|
||||||
|
if ((ident=ALooper_pollOnce(0, NULL, &events, (void**)&source)) >= 0)
|
||||||
|
if (source != NULL) source->process(source->app, source);
|
||||||
|
/* fgPlatformProcessSingleEvent(); */
|
||||||
|
}
|
||||||
|
window->Window.Handle = fgDisplay.pDisplay.single_native_window;
|
||||||
|
window->State.WorkMask |= GLUT_INIT_WORK;
|
||||||
|
|
||||||
|
/* Create context */
|
||||||
|
fghChooseConfig(&window->Window.pContext.egl.Config);
|
||||||
|
window->Window.Context = fghCreateNewContextEGL(window);
|
||||||
|
|
||||||
|
EGLDisplay display = fgDisplay.pDisplay.egl.Display;
|
||||||
|
|
||||||
|
/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
|
||||||
|
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
|
||||||
|
* As soon as we picked a EGLConfig, we can safely reconfigure the
|
||||||
|
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
|
||||||
|
EGLint vid;
|
||||||
|
eglGetConfigAttrib(display, window->Window.pContext.egl.Config,
|
||||||
|
EGL_NATIVE_VISUAL_ID, &vid);
|
||||||
|
ANativeWindow_setBuffersGeometry(window->Window.Handle, 0, 0, vid);
|
||||||
|
|
||||||
|
fghPlatformOpenWindowEGL(window);
|
||||||
|
|
||||||
|
/* Bind context to the current thread if it's lost */
|
||||||
|
if (eglGetCurrentContext() == EGL_NO_CONTEXT &&
|
||||||
|
eglMakeCurrent(fgDisplay.pDisplay.egl.Display,
|
||||||
|
window->Window.pContext.egl.Surface,
|
||||||
|
window->Window.pContext.egl.Surface,
|
||||||
|
window->Window.Context) == EGL_FALSE)
|
||||||
|
fgError("eglMakeCurrent: err=%x\n", eglGetError());
|
||||||
|
|
||||||
|
window->State.Visible = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request a window resize
|
||||||
|
*/
|
||||||
|
void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformReshapeWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Closes a window, destroying the frame and OpenGL context
|
||||||
|
*/
|
||||||
|
void fgPlatformCloseWindow( SFG_Window* window )
|
||||||
|
{
|
||||||
|
fghPlatformCloseWindowEGL(window);
|
||||||
|
/* Window pre-created by Android, no way to delete it */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function makes the specified window visible
|
||||||
|
*/
|
||||||
|
void fgPlatformShowWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformShowWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function hides the specified window
|
||||||
|
*/
|
||||||
|
void fgPlatformHideWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformHideWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iconify the specified window (top-level windows only)
|
||||||
|
*/
|
||||||
|
void fgPlatformIconifyWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformGlutIconifyWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the current window's title
|
||||||
|
*/
|
||||||
|
void fgPlatformGlutSetWindowTitle( const char* title )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformGlutSetWindowTitle: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the current window's iconified title
|
||||||
|
*/
|
||||||
|
void fgPlatformGlutSetIconTitle( const char* title )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformGlutSetIconTitle: STUB\n");}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change the specified window's position
|
||||||
|
*/
|
||||||
|
void fgPlatformPositionWindow( SFG_Window *window, int x, int y )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformPositionWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lowers the specified window (by Z order change)
|
||||||
|
*/
|
||||||
|
void fgPlatformPushWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformPushWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Raises the specified window (by Z order change)
|
||||||
|
*/
|
||||||
|
void fgPlatformPopWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformPopWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle the window's full screen state.
|
||||||
|
*/
|
||||||
|
void fgPlatformFullScreenToggle( SFG_Window *win )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformFullScreenToggle: STUB\n");
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
This code is copied from the Android NDK r7, from
|
||||||
|
source/android/native_app_glue/ .
|
||||||
|
|
||||||
|
A few GCC warnings were suppressed.
|
||||||
|
|
||||||
|
'android_app_write_cmd' was made non-static so that resize events can
|
||||||
|
be injected from FreeGLUT.
|
|
@ -0,0 +1,436 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#include "android_native_app_glue.h"
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
|
||||||
|
|
||||||
|
static void free_saved_state(struct android_app* android_app) {
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
if (android_app->savedState != NULL) {
|
||||||
|
free(android_app->savedState);
|
||||||
|
android_app->savedState = NULL;
|
||||||
|
android_app->savedStateSize = 0;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t android_app_read_cmd(struct android_app* android_app) {
|
||||||
|
int8_t cmd;
|
||||||
|
if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
|
||||||
|
switch (cmd) {
|
||||||
|
case APP_CMD_SAVE_STATE:
|
||||||
|
free_saved_state(android_app);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
} else {
|
||||||
|
LOGI("No data on command pipe!");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_cur_config(struct android_app* android_app) {
|
||||||
|
char lang[2], country[2];
|
||||||
|
AConfiguration_getLanguage(android_app->config, lang);
|
||||||
|
AConfiguration_getCountry(android_app->config, country);
|
||||||
|
|
||||||
|
LOGI("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
|
||||||
|
"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
|
||||||
|
"modetype=%d modenight=%d",
|
||||||
|
AConfiguration_getMcc(android_app->config),
|
||||||
|
AConfiguration_getMnc(android_app->config),
|
||||||
|
lang[0], lang[1], country[0], country[1],
|
||||||
|
AConfiguration_getOrientation(android_app->config),
|
||||||
|
AConfiguration_getTouchscreen(android_app->config),
|
||||||
|
AConfiguration_getDensity(android_app->config),
|
||||||
|
AConfiguration_getKeyboard(android_app->config),
|
||||||
|
AConfiguration_getNavigation(android_app->config),
|
||||||
|
AConfiguration_getKeysHidden(android_app->config),
|
||||||
|
AConfiguration_getNavHidden(android_app->config),
|
||||||
|
AConfiguration_getSdkVersion(android_app->config),
|
||||||
|
AConfiguration_getScreenSize(android_app->config),
|
||||||
|
AConfiguration_getScreenLong(android_app->config),
|
||||||
|
AConfiguration_getUiModeType(android_app->config),
|
||||||
|
AConfiguration_getUiModeNight(android_app->config));
|
||||||
|
}
|
||||||
|
|
||||||
|
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
|
||||||
|
switch (cmd) {
|
||||||
|
case APP_CMD_INPUT_CHANGED:
|
||||||
|
LOGI("APP_CMD_INPUT_CHANGED\n");
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
if (android_app->inputQueue != NULL) {
|
||||||
|
AInputQueue_detachLooper(android_app->inputQueue);
|
||||||
|
}
|
||||||
|
android_app->inputQueue = android_app->pendingInputQueue;
|
||||||
|
if (android_app->inputQueue != NULL) {
|
||||||
|
LOGI("Attaching input queue to looper");
|
||||||
|
AInputQueue_attachLooper(android_app->inputQueue,
|
||||||
|
android_app->looper, LOOPER_ID_INPUT, NULL,
|
||||||
|
&android_app->inputPollSource);
|
||||||
|
}
|
||||||
|
pthread_cond_broadcast(&android_app->cond);
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_INIT_WINDOW:
|
||||||
|
LOGI("APP_CMD_INIT_WINDOW\n");
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app->window = android_app->pendingWindow;
|
||||||
|
pthread_cond_broadcast(&android_app->cond);
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_TERM_WINDOW:
|
||||||
|
LOGI("APP_CMD_TERM_WINDOW\n");
|
||||||
|
pthread_cond_broadcast(&android_app->cond);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_RESUME:
|
||||||
|
case APP_CMD_START:
|
||||||
|
case APP_CMD_PAUSE:
|
||||||
|
case APP_CMD_STOP:
|
||||||
|
LOGI("activityState=%d\n", cmd);
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app->activityState = cmd;
|
||||||
|
pthread_cond_broadcast(&android_app->cond);
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_CONFIG_CHANGED:
|
||||||
|
LOGI("APP_CMD_CONFIG_CHANGED\n");
|
||||||
|
AConfiguration_fromAssetManager(android_app->config,
|
||||||
|
android_app->activity->assetManager);
|
||||||
|
print_cur_config(android_app);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_DESTROY:
|
||||||
|
LOGI("APP_CMD_DESTROY\n");
|
||||||
|
android_app->destroyRequested = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
|
||||||
|
switch (cmd) {
|
||||||
|
case APP_CMD_TERM_WINDOW:
|
||||||
|
LOGI("APP_CMD_TERM_WINDOW\n");
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app->window = NULL;
|
||||||
|
pthread_cond_broadcast(&android_app->cond);
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_SAVE_STATE:
|
||||||
|
LOGI("APP_CMD_SAVE_STATE\n");
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app->stateSaved = 1;
|
||||||
|
pthread_cond_broadcast(&android_app->cond);
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_CMD_RESUME:
|
||||||
|
free_saved_state(android_app);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_dummy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void android_app_destroy(struct android_app* android_app) {
|
||||||
|
LOGI("android_app_destroy!");
|
||||||
|
free_saved_state(android_app);
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
if (android_app->inputQueue != NULL) {
|
||||||
|
AInputQueue_detachLooper(android_app->inputQueue);
|
||||||
|
}
|
||||||
|
AConfiguration_delete(android_app->config);
|
||||||
|
android_app->destroyed = 1;
|
||||||
|
pthread_cond_broadcast(&android_app->cond);
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
/* // Can't touch android_app object after this. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_input(struct android_app* app, struct android_poll_source* source) {
|
||||||
|
AInputEvent* event = NULL;
|
||||||
|
if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
|
||||||
|
LOGI("New input event: type=%d\n", AInputEvent_getType(event));
|
||||||
|
if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int32_t handled = 0;
|
||||||
|
if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
|
||||||
|
AInputQueue_finishEvent(app->inputQueue, event, handled);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGI("Failure reading next input event: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_cmd(struct android_app* app, struct android_poll_source* source) {
|
||||||
|
int8_t cmd = android_app_read_cmd(app);
|
||||||
|
android_app_pre_exec_cmd(app, cmd);
|
||||||
|
if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
|
||||||
|
android_app_post_exec_cmd(app, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* android_app_entry(void* param) {
|
||||||
|
struct android_app* android_app = (struct android_app*)param;
|
||||||
|
ALooper* looper;
|
||||||
|
|
||||||
|
android_app->config = AConfiguration_new();
|
||||||
|
AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
|
||||||
|
|
||||||
|
print_cur_config(android_app);
|
||||||
|
|
||||||
|
android_app->cmdPollSource.id = LOOPER_ID_MAIN;
|
||||||
|
android_app->cmdPollSource.app = android_app;
|
||||||
|
android_app->cmdPollSource.process = process_cmd;
|
||||||
|
android_app->inputPollSource.id = LOOPER_ID_INPUT;
|
||||||
|
android_app->inputPollSource.app = android_app;
|
||||||
|
android_app->inputPollSource.process = process_input;
|
||||||
|
|
||||||
|
looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||||
|
ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
|
||||||
|
&android_app->cmdPollSource);
|
||||||
|
android_app->looper = looper;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app->running = 1;
|
||||||
|
pthread_cond_broadcast(&android_app->cond);
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
|
||||||
|
android_main(android_app);
|
||||||
|
|
||||||
|
android_app_destroy(android_app);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* // -------------------------------------------------------------------- */
|
||||||
|
/* // Native activity interaction (called from main thread) */
|
||||||
|
/* // -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static struct android_app* android_app_create(ANativeActivity* activity,
|
||||||
|
void* savedState, size_t savedStateSize) {
|
||||||
|
struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
|
||||||
|
int msgpipe[2];
|
||||||
|
pthread_attr_t attr;
|
||||||
|
memset(android_app, 0, sizeof(struct android_app));
|
||||||
|
android_app->activity = activity;
|
||||||
|
|
||||||
|
pthread_mutex_init(&android_app->mutex, NULL);
|
||||||
|
pthread_cond_init(&android_app->cond, NULL);
|
||||||
|
|
||||||
|
if (savedState != NULL) {
|
||||||
|
android_app->savedState = malloc(savedStateSize);
|
||||||
|
android_app->savedStateSize = savedStateSize;
|
||||||
|
memcpy(android_app->savedState, savedState, savedStateSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipe(msgpipe)) {
|
||||||
|
LOGI("could not create pipe: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
android_app->msgread = msgpipe[0];
|
||||||
|
android_app->msgwrite = msgpipe[1];
|
||||||
|
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
|
||||||
|
|
||||||
|
/* // Wait for thread to start. */
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
while (!android_app->running) {
|
||||||
|
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
|
||||||
|
return android_app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
|
||||||
|
if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
|
||||||
|
LOGI("Failure writing android_app cmd: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app->pendingInputQueue = inputQueue;
|
||||||
|
android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
|
||||||
|
while (android_app->inputQueue != android_app->pendingInputQueue) {
|
||||||
|
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
if (android_app->pendingWindow != NULL) {
|
||||||
|
android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
|
||||||
|
}
|
||||||
|
android_app->pendingWindow = window;
|
||||||
|
if (window != NULL) {
|
||||||
|
android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
|
||||||
|
}
|
||||||
|
while (android_app->window != android_app->pendingWindow) {
|
||||||
|
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app_write_cmd(android_app, cmd);
|
||||||
|
while (android_app->activityState != cmd) {
|
||||||
|
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void android_app_free(struct android_app* android_app) {
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app_write_cmd(android_app, APP_CMD_DESTROY);
|
||||||
|
while (!android_app->destroyed) {
|
||||||
|
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
|
||||||
|
close(android_app->msgread);
|
||||||
|
close(android_app->msgwrite);
|
||||||
|
pthread_cond_destroy(&android_app->cond);
|
||||||
|
pthread_mutex_destroy(&android_app->mutex);
|
||||||
|
free(android_app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onDestroy(ANativeActivity* activity) {
|
||||||
|
LOGI("Destroy: %p\n", (void*)activity);
|
||||||
|
android_app_free((struct android_app*)activity->instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onStart(ANativeActivity* activity) {
|
||||||
|
LOGI("Start: %p\n", (void*)activity);
|
||||||
|
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onResume(ANativeActivity* activity) {
|
||||||
|
LOGI("Resume: %p\n", (void*)activity);
|
||||||
|
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
|
||||||
|
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||||
|
void* savedState = NULL;
|
||||||
|
|
||||||
|
LOGI("SaveInstanceState: %p\n", (void*)activity);
|
||||||
|
pthread_mutex_lock(&android_app->mutex);
|
||||||
|
android_app->stateSaved = 0;
|
||||||
|
android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
|
||||||
|
while (!android_app->stateSaved) {
|
||||||
|
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (android_app->savedState != NULL) {
|
||||||
|
savedState = android_app->savedState;
|
||||||
|
*outLen = android_app->savedStateSize;
|
||||||
|
android_app->savedState = NULL;
|
||||||
|
android_app->savedStateSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&android_app->mutex);
|
||||||
|
|
||||||
|
return savedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onPause(ANativeActivity* activity) {
|
||||||
|
LOGI("Pause: %p\n", (void*)activity);
|
||||||
|
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onStop(ANativeActivity* activity) {
|
||||||
|
LOGI("Stop: %p\n", (void*)activity);
|
||||||
|
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onConfigurationChanged(ANativeActivity* activity) {
|
||||||
|
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||||
|
LOGI("ConfigurationChanged: %p\n", (void*)activity);
|
||||||
|
android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onLowMemory(ANativeActivity* activity) {
|
||||||
|
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||||
|
LOGI("LowMemory: %p\n", (void*)activity);
|
||||||
|
android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
|
||||||
|
LOGI("WindowFocusChanged: %p -- %d\n", (void*)activity, focused);
|
||||||
|
android_app_write_cmd((struct android_app*)activity->instance,
|
||||||
|
focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
|
||||||
|
LOGI("NativeWindowCreated: %p -- %p\n", (void*)activity, (void*)window);
|
||||||
|
android_app_set_window((struct android_app*)activity->instance, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
|
||||||
|
LOGI("NativeWindowDestroyed: %p -- %p\n", (void*)activity, (void*)window);
|
||||||
|
android_app_set_window((struct android_app*)activity->instance, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
|
||||||
|
LOGI("InputQueueCreated: %p -- %p\n", (void*)activity, (void*)queue);
|
||||||
|
android_app_set_input((struct android_app*)activity->instance, queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
|
||||||
|
LOGI("InputQueueDestroyed: %p -- %p\n", (void*)activity, (void*)queue);
|
||||||
|
android_app_set_input((struct android_app*)activity->instance, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ANativeActivity_onCreate(ANativeActivity* activity,
|
||||||
|
void* savedState, size_t savedStateSize) {
|
||||||
|
LOGI("Creating: %p\n", (void*)activity);
|
||||||
|
activity->callbacks->onDestroy = onDestroy;
|
||||||
|
activity->callbacks->onStart = onStart;
|
||||||
|
activity->callbacks->onResume = onResume;
|
||||||
|
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
|
||||||
|
activity->callbacks->onPause = onPause;
|
||||||
|
activity->callbacks->onStop = onStop;
|
||||||
|
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
|
||||||
|
activity->callbacks->onLowMemory = onLowMemory;
|
||||||
|
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
|
||||||
|
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
|
||||||
|
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
|
||||||
|
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
|
||||||
|
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
|
||||||
|
|
||||||
|
activity->instance = android_app_create(activity, savedState, savedStateSize);
|
||||||
|
}
|
|
@ -0,0 +1,351 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ANDROID_NATIVE_APP_GLUE_H
|
||||||
|
#define _ANDROID_NATIVE_APP_GLUE_H
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
|
#include <android/configuration.h>
|
||||||
|
#include <android/looper.h>
|
||||||
|
#include <android/native_activity.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The native activity interface provided by <android/native_activity.h>
|
||||||
|
* is based on a set of application-provided callbacks that will be called
|
||||||
|
* by the Activity's main thread when certain events occur.
|
||||||
|
*
|
||||||
|
* This means that each one of this callbacks _should_ _not_ block, or they
|
||||||
|
* risk having the system force-close the application. This programming
|
||||||
|
* model is direct, lightweight, but constraining.
|
||||||
|
*
|
||||||
|
* The 'threaded_native_app' static library is used to provide a different
|
||||||
|
* execution model where the application can implement its own main event
|
||||||
|
* loop in a different thread instead. Here's how it works:
|
||||||
|
*
|
||||||
|
* 1/ The application must provide a function named "android_main()" that
|
||||||
|
* will be called when the activity is created, in a new thread that is
|
||||||
|
* distinct from the activity's main thread.
|
||||||
|
*
|
||||||
|
* 2/ android_main() receives a pointer to a valid "android_app" structure
|
||||||
|
* that contains references to other important objects, e.g. the
|
||||||
|
* ANativeActivity obejct instance the application is running in.
|
||||||
|
*
|
||||||
|
* 3/ the "android_app" object holds an ALooper instance that already
|
||||||
|
* listens to two important things:
|
||||||
|
*
|
||||||
|
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
|
||||||
|
* declarations below.
|
||||||
|
*
|
||||||
|
* - input events coming from the AInputQueue attached to the activity.
|
||||||
|
*
|
||||||
|
* Each of these correspond to an ALooper identifier returned by
|
||||||
|
* ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
|
||||||
|
* respectively.
|
||||||
|
*
|
||||||
|
* Your application can use the same ALooper to listen to additional
|
||||||
|
* file-descriptors. They can either be callback based, or with return
|
||||||
|
* identifiers starting with LOOPER_ID_USER.
|
||||||
|
*
|
||||||
|
* 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
|
||||||
|
* the returned data will point to an android_poll_source structure. You
|
||||||
|
* can call the process() function on it, and fill in android_app->onAppCmd
|
||||||
|
* and android_app->onInputEvent to be called for your own processing
|
||||||
|
* of the event.
|
||||||
|
*
|
||||||
|
* Alternatively, you can call the low-level functions to read and process
|
||||||
|
* the data directly... look at the process_cmd() and process_input()
|
||||||
|
* implementations in the glue to see how to do this.
|
||||||
|
*
|
||||||
|
* See the sample named "native-activity" that comes with the NDK with a
|
||||||
|
* full usage example. Also look at the JavaDoc of NativeActivity.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct android_app;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data associated with an ALooper fd that will be returned as the "outData"
|
||||||
|
* when that source has data ready.
|
||||||
|
*/
|
||||||
|
struct android_poll_source {
|
||||||
|
/* // The identifier of this source. May be LOOPER_ID_MAIN or */
|
||||||
|
/* // LOOPER_ID_INPUT. */
|
||||||
|
int32_t id;
|
||||||
|
|
||||||
|
/* // The android_app this ident is associated with. */
|
||||||
|
struct android_app* app;
|
||||||
|
|
||||||
|
/* // Function to call to perform the standard processing of data from */
|
||||||
|
/* // this source. */
|
||||||
|
void (*process)(struct android_app* app, struct android_poll_source* source);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the interface for the standard glue code of a threaded
|
||||||
|
* application. In this model, the application's code is running
|
||||||
|
* in its own thread separate from the main thread of the process.
|
||||||
|
* It is not required that this thread be associated with the Java
|
||||||
|
* VM, although it will need to be in order to make JNI calls any
|
||||||
|
* Java objects.
|
||||||
|
*/
|
||||||
|
struct android_app {
|
||||||
|
/* // The application can place a pointer to its own state object */
|
||||||
|
/* // here if it likes. */
|
||||||
|
void* userData;
|
||||||
|
|
||||||
|
/* // Fill this in with the function to process main app commands (APP_CMD_*) */
|
||||||
|
void (*onAppCmd)(struct android_app* app, int32_t cmd);
|
||||||
|
|
||||||
|
/* // Fill this in with the function to process input events. At this point */
|
||||||
|
/* // the event has already been pre-dispatched, and it will be finished upon */
|
||||||
|
/* // return. Return 1 if you have handled the event, 0 for any default */
|
||||||
|
/* // dispatching. */
|
||||||
|
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
|
||||||
|
|
||||||
|
/* // The ANativeActivity object instance that this app is running in. */
|
||||||
|
ANativeActivity* activity;
|
||||||
|
|
||||||
|
/* // The current configuration the app is running in. */
|
||||||
|
AConfiguration* config;
|
||||||
|
|
||||||
|
/* // This is the last instance's saved state, as provided at creation time. */
|
||||||
|
/* // It is NULL if there was no state. You can use this as you need; the */
|
||||||
|
/* // memory will remain around until you call android_app_exec_cmd() for */
|
||||||
|
/* // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. */
|
||||||
|
/* // These variables should only be changed when processing a APP_CMD_SAVE_STATE, */
|
||||||
|
/* // at which point they will be initialized to NULL and you can malloc your */
|
||||||
|
/* // state and place the information here. In that case the memory will be */
|
||||||
|
/* // freed for you later. */
|
||||||
|
void* savedState;
|
||||||
|
size_t savedStateSize;
|
||||||
|
|
||||||
|
/* // The ALooper associated with the app's thread. */
|
||||||
|
ALooper* looper;
|
||||||
|
|
||||||
|
/* // When non-NULL, this is the input queue from which the app will */
|
||||||
|
/* // receive user input events. */
|
||||||
|
AInputQueue* inputQueue;
|
||||||
|
|
||||||
|
/* // When non-NULL, this is the window surface that the app can draw in. */
|
||||||
|
ANativeWindow* window;
|
||||||
|
|
||||||
|
/* // Current content rectangle of the window; this is the area where the */
|
||||||
|
/* // window's content should be placed to be seen by the user. */
|
||||||
|
ARect contentRect;
|
||||||
|
|
||||||
|
/* // Current state of the app's activity. May be either APP_CMD_START, */
|
||||||
|
/* // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. */
|
||||||
|
int activityState;
|
||||||
|
|
||||||
|
/* // This is non-zero when the application's NativeActivity is being */
|
||||||
|
/* // destroyed and waiting for the app thread to complete. */
|
||||||
|
int destroyRequested;
|
||||||
|
|
||||||
|
/* // ------------------------------------------------- */
|
||||||
|
/* // Below are "private" implementation of the glue code. */
|
||||||
|
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
|
||||||
|
int msgread;
|
||||||
|
int msgwrite;
|
||||||
|
|
||||||
|
pthread_t thread;
|
||||||
|
|
||||||
|
struct android_poll_source cmdPollSource;
|
||||||
|
struct android_poll_source inputPollSource;
|
||||||
|
|
||||||
|
int running;
|
||||||
|
int stateSaved;
|
||||||
|
int destroyed;
|
||||||
|
int redrawNeeded;
|
||||||
|
AInputQueue* pendingInputQueue;
|
||||||
|
ANativeWindow* pendingWindow;
|
||||||
|
ARect pendingContentRect;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/**
|
||||||
|
* Looper data ID of commands coming from the app's main thread, which
|
||||||
|
* is returned as an identifier from ALooper_pollOnce(). The data for this
|
||||||
|
* identifier is a pointer to an android_poll_source structure.
|
||||||
|
* These can be retrieved and processed with android_app_read_cmd()
|
||||||
|
* and android_app_exec_cmd().
|
||||||
|
*/
|
||||||
|
LOOPER_ID_MAIN = 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looper data ID of events coming from the AInputQueue of the
|
||||||
|
* application's window, which is returned as an identifier from
|
||||||
|
* ALooper_pollOnce(). The data for this identifier is a pointer to an
|
||||||
|
* android_poll_source structure. These can be read via the inputQueue
|
||||||
|
* object of android_app.
|
||||||
|
*/
|
||||||
|
LOOPER_ID_INPUT = 2,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start of user-defined ALooper identifiers.
|
||||||
|
*/
|
||||||
|
LOOPER_ID_USER = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/**
|
||||||
|
* Command from main thread: the AInputQueue has changed. Upon processing
|
||||||
|
* this command, android_app->inputQueue will be updated to the new queue
|
||||||
|
* (or NULL).
|
||||||
|
*/
|
||||||
|
APP_CMD_INPUT_CHANGED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: a new ANativeWindow is ready for use. Upon
|
||||||
|
* receiving this command, android_app->window will contain the new window
|
||||||
|
* surface.
|
||||||
|
*/
|
||||||
|
APP_CMD_INIT_WINDOW,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the existing ANativeWindow needs to be
|
||||||
|
* terminated. Upon receiving this command, android_app->window still
|
||||||
|
* contains the existing window; after calling android_app_exec_cmd
|
||||||
|
* it will be set to NULL.
|
||||||
|
*/
|
||||||
|
APP_CMD_TERM_WINDOW,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the current ANativeWindow has been resized.
|
||||||
|
* Please redraw with its new size.
|
||||||
|
*/
|
||||||
|
APP_CMD_WINDOW_RESIZED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the system needs that the current ANativeWindow
|
||||||
|
* be redrawn. You should redraw the window before handing this to
|
||||||
|
* android_app_exec_cmd() in order to avoid transient drawing glitches.
|
||||||
|
*/
|
||||||
|
APP_CMD_WINDOW_REDRAW_NEEDED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the content area of the window has changed,
|
||||||
|
* such as from the soft input window being shown or hidden. You can
|
||||||
|
* find the new content rect in android_app::contentRect.
|
||||||
|
*/
|
||||||
|
APP_CMD_CONTENT_RECT_CHANGED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the app's activity window has gained
|
||||||
|
* input focus.
|
||||||
|
*/
|
||||||
|
APP_CMD_GAINED_FOCUS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the app's activity window has lost
|
||||||
|
* input focus.
|
||||||
|
*/
|
||||||
|
APP_CMD_LOST_FOCUS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the current device configuration has changed.
|
||||||
|
*/
|
||||||
|
APP_CMD_CONFIG_CHANGED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the system is running low on memory.
|
||||||
|
* Try to reduce your memory use.
|
||||||
|
*/
|
||||||
|
APP_CMD_LOW_MEMORY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the app's activity has been started.
|
||||||
|
*/
|
||||||
|
APP_CMD_START,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the app's activity has been resumed.
|
||||||
|
*/
|
||||||
|
APP_CMD_RESUME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the app should generate a new saved state
|
||||||
|
* for itself, to restore from later if needed. If you have saved state,
|
||||||
|
* allocate it with malloc and place it in android_app.savedState with
|
||||||
|
* the size in android_app.savedStateSize. The will be freed for you
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
APP_CMD_SAVE_STATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the app's activity has been paused.
|
||||||
|
*/
|
||||||
|
APP_CMD_PAUSE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the app's activity has been stopped.
|
||||||
|
*/
|
||||||
|
APP_CMD_STOP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command from main thread: the app's activity is being destroyed,
|
||||||
|
* and waiting for the app thread to clean up and exit before proceeding.
|
||||||
|
*/
|
||||||
|
APP_CMD_DESTROY
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
|
||||||
|
* app command message.
|
||||||
|
*/
|
||||||
|
int8_t android_app_read_cmd(struct android_app* android_app);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call with the command returned by android_app_read_cmd() to do the
|
||||||
|
* initial pre-processing of the given command. You can perform your own
|
||||||
|
* actions for the command after calling this function.
|
||||||
|
*/
|
||||||
|
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call with the command returned by android_app_read_cmd() to do the
|
||||||
|
* final post-processing of the given command. You must have done your own
|
||||||
|
* actions for the command before calling this function.
|
||||||
|
*/
|
||||||
|
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy function you can call to ensure glue code isn't stripped.
|
||||||
|
*/
|
||||||
|
void app_dummy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the function that application code must implement, representing
|
||||||
|
* the main entry to the app.
|
||||||
|
*/
|
||||||
|
extern void android_main(struct android_app* app);
|
||||||
|
|
||||||
|
/* static */void android_app_write_cmd(struct android_app* android_app, int8_t cmd);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ANDROID_NATIVE_APP_GLUE_H */
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* fg_init_blackberry.c
|
||||||
|
*
|
||||||
|
* Various freeglut initialization functions.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
* Copyright (C) 2013 Vincent Simonetti
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "fg_init.h"
|
||||||
|
#include "egl/fg_init_egl.h"
|
||||||
|
#include <bps/bps.h>
|
||||||
|
#include <screen/screen.h>
|
||||||
|
|
||||||
|
void fgPlatformInitialize()
|
||||||
|
{
|
||||||
|
bps_initialize();
|
||||||
|
|
||||||
|
fghPlatformInitializeEGL();
|
||||||
|
|
||||||
|
/* Prepare for screen events */
|
||||||
|
fgDisplay.pDisplay.event = NULL;
|
||||||
|
fgDisplay.pDisplay.screenContext = NULL;
|
||||||
|
|
||||||
|
/* Create window */
|
||||||
|
if (screen_create_context(&fgDisplay.pDisplay.screenContext, 0)) {
|
||||||
|
fgError("Could not create screen context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get screen size */
|
||||||
|
int displayCount;
|
||||||
|
screen_display_t* displays;
|
||||||
|
int vals[2];
|
||||||
|
if(screen_get_context_property_iv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount)) {
|
||||||
|
fgWarning("Could not get display count. Screen size not determined and will be left at default values");
|
||||||
|
} else if(displayCount >= 1) {
|
||||||
|
displays = (screen_display_t*)calloc(displayCount, sizeof(screen_display_t));
|
||||||
|
if(screen_get_context_property_pv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DISPLAYS, (void**)displays)) {
|
||||||
|
fgWarning("Could not get displays. Screen size not determined and will be left at default values");
|
||||||
|
} else {
|
||||||
|
/* We only care about the first one, which is the device display */
|
||||||
|
if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_SIZE, vals)) {
|
||||||
|
fgWarning("Could not get display size. Values will be left at default");
|
||||||
|
} else {
|
||||||
|
if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_ROTATION, &displayCount) || (displayCount == 0 || displayCount == 180)) {
|
||||||
|
fgDisplay.ScreenWidth = vals[0];
|
||||||
|
fgDisplay.ScreenHeight = vals[1];
|
||||||
|
} else {
|
||||||
|
fgDisplay.ScreenWidth = vals[1];
|
||||||
|
fgDisplay.ScreenHeight = vals[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_PHYSICAL_SIZE, vals)) {
|
||||||
|
fgWarning("Could not get physical display size. Values will be left at default");
|
||||||
|
} else {
|
||||||
|
fgDisplay.ScreenWidthMM = vals[0];
|
||||||
|
fgDisplay.ScreenHeightMM = vals[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(displays);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get start time */
|
||||||
|
fgState.Time = fgSystemTime();
|
||||||
|
|
||||||
|
fgState.Initialised = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformCloseDisplay()
|
||||||
|
{
|
||||||
|
fghPlatformCloseDisplayEGL();
|
||||||
|
|
||||||
|
screen_destroy_context(fgDisplay.pDisplay.screenContext);
|
||||||
|
fgDisplay.pDisplay.screenContext = NULL;
|
||||||
|
|
||||||
|
bps_shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close joystick and serial input devices
|
||||||
|
*/
|
||||||
|
void fgPlatformDeinitialiseInputDevices ( void )
|
||||||
|
{
|
||||||
|
fghCloseInputDevices ();
|
||||||
|
fgState.JoysticksInitialised = GL_FALSE;
|
||||||
|
fgState.InputDevsInitialised = GL_FALSE;
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* fg_internal_blackberry.h
|
||||||
|
*
|
||||||
|
* The freeglut library private include file.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
* Copyright (C) 2013 Vincent Simonetti
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREEGLUT_INTERNAL_BLACKBERRY_H
|
||||||
|
#define FREEGLUT_INTERNAL_BLACKBERRY_H
|
||||||
|
|
||||||
|
//Minor modified version of fg_internal_android.h
|
||||||
|
|
||||||
|
/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */
|
||||||
|
/* BlackBerry OpenGL ES is accessed through EGL */
|
||||||
|
#include "egl/fg_internal_egl.h"
|
||||||
|
#include <screen/screen.h>
|
||||||
|
#include <bps/event.h>
|
||||||
|
#include <bps/navigator.h>
|
||||||
|
|
||||||
|
/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */
|
||||||
|
/* The structure used by display initialization in fg_init.c */
|
||||||
|
typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay;
|
||||||
|
struct tagSFG_PlatformDisplay
|
||||||
|
{
|
||||||
|
struct tagSFG_PlatformDisplayEGL egl;
|
||||||
|
screen_context_t screenContext;
|
||||||
|
bps_event_t* event;
|
||||||
|
EGLNativeWindowType single_native_window;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct tagSFG_PlatformContext SFG_PlatformContext;
|
||||||
|
/* SFG_PlatformContext is used for SFG_Window.Window */
|
||||||
|
struct tagSFG_PlatformContext
|
||||||
|
{
|
||||||
|
struct tagSFG_PlatformContextEGL egl;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual PAD (spots on touchscreen that simulate keys)
|
||||||
|
*/
|
||||||
|
struct vpad_state {
|
||||||
|
bool on;
|
||||||
|
bool left;
|
||||||
|
bool right;
|
||||||
|
bool up;
|
||||||
|
bool down;
|
||||||
|
};
|
||||||
|
struct touchscreen {
|
||||||
|
struct vpad_state vpad;
|
||||||
|
bool in_mmotion;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* -- INPUT DEFINITIONS ---------------------------------------------------- */
|
||||||
|
#define WHEEL_DELTA 120 //This is taken from http://msdn.microsoft.com/en-us/library/windows/desktop/ms646254(v=vs.85).aspx
|
||||||
|
|
||||||
|
|
||||||
|
/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */
|
||||||
|
/*
|
||||||
|
* Initial defines from "js.h" starting around line 33 with the existing "fg_joystick.c"
|
||||||
|
* interspersed
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We'll put these values in and that should
|
||||||
|
* allow the code to at least compile when there is
|
||||||
|
* no support. The JS open routine should error out
|
||||||
|
* and shut off all the code downstream anyway and if
|
||||||
|
* the application doesn't use a joystick we'll be fine.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct JS_DATA_TYPE
|
||||||
|
{
|
||||||
|
int buttons;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define JS_RETURN (sizeof(struct JS_DATA_TYPE))
|
||||||
|
|
||||||
|
/* XXX It might be better to poll the operating system for the numbers of buttons and
|
||||||
|
* XXX axes and then dynamically allocate the arrays.
|
||||||
|
*/
|
||||||
|
#define _JS_MAX_AXES 16
|
||||||
|
typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick;
|
||||||
|
struct tagSFG_PlatformJoystick
|
||||||
|
{
|
||||||
|
struct JS_DATA_TYPE js;
|
||||||
|
|
||||||
|
char fname [ 128 ];
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Window's state description. This structure should be kept portable. */
|
||||||
|
typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
|
||||||
|
struct tagSFG_PlatformWindowState
|
||||||
|
{
|
||||||
|
int newWidth;
|
||||||
|
int newHeight;
|
||||||
|
int originalRotation;
|
||||||
|
navigator_window_state_t windowState;
|
||||||
|
GLboolean windowCovered;
|
||||||
|
int keyboardHeight;
|
||||||
|
GLboolean keyboardOpen;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Menu font and color definitions */
|
||||||
|
#define FREEGLUT_MENU_FONT NULL
|
||||||
|
|
||||||
|
#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
|
||||||
|
#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f}
|
||||||
|
#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
|
||||||
|
#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f}
|
||||||
|
|
||||||
|
#endif /* FREEGLUT_INTERNAL_BLACKBERRY_H */
|
|
@ -0,0 +1,893 @@
|
||||||
|
/*
|
||||||
|
* fg_main_blackberry.c
|
||||||
|
*
|
||||||
|
* The BlackBerry-specific windows message processing methods.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
|
||||||
|
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
* Copyright (C) 2013 Vincent Simonetti
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "egl/fg_window_egl.h"
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define LOGI(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __PLAYBOOK__
|
||||||
|
#include <sys/slog.h>
|
||||||
|
#ifndef LOGI
|
||||||
|
#define LOGI(...) ((void)slogf(1337, _SLOG_INFO, __VA_ARGS__))
|
||||||
|
#endif
|
||||||
|
#define LOGW(...) ((void)slogf(1337, _SLOG_WARNING, __VA_ARGS__))
|
||||||
|
#ifndef SLOG2_FA_SIGNED
|
||||||
|
#define SLOG2_FA_SIGNED(x) (x)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <slog2.h>
|
||||||
|
#ifndef LOGI
|
||||||
|
#define LOGI(...) ((void)slog2fa(NULL, 1337, SLOG2_INFO, __VA_ARGS__, SLOG2_FA_END))
|
||||||
|
#endif
|
||||||
|
#define LOGW(...) ((void)slog2fa(NULL, 1337, SLOG2_WARNING, __VA_ARGS__, SLOG2_FA_END))
|
||||||
|
#endif
|
||||||
|
#include <sys/keycodes.h>
|
||||||
|
#include <input/screen_helpers.h>
|
||||||
|
#include <bps/bps.h>
|
||||||
|
#include <bps/event.h>
|
||||||
|
#include <bps/screen.h>
|
||||||
|
#include <bps/navigator.h>
|
||||||
|
#include <bps/virtualkeyboard.h>
|
||||||
|
|
||||||
|
extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify);
|
||||||
|
extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify);
|
||||||
|
extern void fgPlatformFullScreenToggle( SFG_Window *win );
|
||||||
|
extern void fgPlatformPositionWindow( SFG_Window *window, int x, int y );
|
||||||
|
extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height );
|
||||||
|
extern void fgPlatformPushWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformPopWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformHideWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformIconifyWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformShowWindow( SFG_Window *window );
|
||||||
|
extern void fgPlatformMainLoopPostWork ( void );
|
||||||
|
extern void fgPlatformRotateWindow( SFG_Window *window, int rotation );
|
||||||
|
extern void fgPlatformFlushCommands ( void );
|
||||||
|
|
||||||
|
static struct touchscreen touchscreen;
|
||||||
|
|
||||||
|
#define ESCAPE_BUTTON_KEY 0x001B
|
||||||
|
|
||||||
|
unsigned int key_special(int qnxKeycode)
|
||||||
|
{
|
||||||
|
switch(qnxKeycode) {
|
||||||
|
case KEYCODE_F1:
|
||||||
|
return GLUT_KEY_F1;
|
||||||
|
case KEYCODE_F2:
|
||||||
|
return GLUT_KEY_F2;
|
||||||
|
case KEYCODE_F3:
|
||||||
|
return GLUT_KEY_F3;
|
||||||
|
case KEYCODE_F4:
|
||||||
|
return GLUT_KEY_F4;
|
||||||
|
case KEYCODE_F5:
|
||||||
|
return GLUT_KEY_F5;
|
||||||
|
case KEYCODE_F6:
|
||||||
|
return GLUT_KEY_F6;
|
||||||
|
case KEYCODE_F7:
|
||||||
|
return GLUT_KEY_F7;
|
||||||
|
case KEYCODE_F8:
|
||||||
|
return GLUT_KEY_F8;
|
||||||
|
case KEYCODE_F9:
|
||||||
|
return GLUT_KEY_F9;
|
||||||
|
case KEYCODE_F10:
|
||||||
|
return GLUT_KEY_F10;
|
||||||
|
case KEYCODE_F11:
|
||||||
|
return GLUT_KEY_F11;
|
||||||
|
case KEYCODE_F12:
|
||||||
|
return GLUT_KEY_F12;
|
||||||
|
case KEYCODE_PG_UP:
|
||||||
|
return GLUT_KEY_PAGE_UP;
|
||||||
|
case KEYCODE_PG_DOWN:
|
||||||
|
return GLUT_KEY_PAGE_DOWN;
|
||||||
|
case KEYCODE_HOME:
|
||||||
|
return GLUT_KEY_HOME;
|
||||||
|
case KEYCODE_END:
|
||||||
|
return GLUT_KEY_END;
|
||||||
|
case KEYCODE_INSERT:
|
||||||
|
return GLUT_KEY_INSERT;
|
||||||
|
case KEYCODE_UP:
|
||||||
|
//case KEYCODE_KP_UP:
|
||||||
|
return GLUT_KEY_UP;
|
||||||
|
case KEYCODE_DOWN:
|
||||||
|
//case KEYCODE_KP_DOWN:
|
||||||
|
return GLUT_KEY_DOWN;
|
||||||
|
case KEYCODE_LEFT:
|
||||||
|
//case KEYCODE_KP_LEFT:
|
||||||
|
return GLUT_KEY_LEFT;
|
||||||
|
case KEYCODE_RIGHT:
|
||||||
|
//case KEYCODE_KP_RIGHT:
|
||||||
|
return GLUT_KEY_RIGHT;
|
||||||
|
case KEYCODE_NUM_LOCK:
|
||||||
|
return GLUT_KEY_NUM_LOCK;
|
||||||
|
case KEYCODE_LEFT_ALT:
|
||||||
|
return GLUT_KEY_ALT_L;
|
||||||
|
case KEYCODE_RIGHT_ALT:
|
||||||
|
return GLUT_KEY_ALT_R;
|
||||||
|
case KEYCODE_LEFT_SHIFT:
|
||||||
|
return GLUT_KEY_SHIFT_L;
|
||||||
|
case KEYCODE_RIGHT_SHIFT:
|
||||||
|
return GLUT_KEY_SHIFT_R;
|
||||||
|
case KEYCODE_LEFT_CTRL:
|
||||||
|
return GLUT_KEY_CTRL_L;
|
||||||
|
case KEYCODE_RIGHT_CTRL:
|
||||||
|
return GLUT_KEY_CTRL_R;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char key_ascii(int qnxKeycode)
|
||||||
|
{
|
||||||
|
if (qnxKeycode >= KEYCODE_PC_KEYS && qnxKeycode <= UNICODE_PRIVATE_USE_AREA_LAST) {
|
||||||
|
switch (qnxKeycode) {
|
||||||
|
case KEYCODE_BACKSPACE:
|
||||||
|
return 0x0008;
|
||||||
|
case KEYCODE_TAB:
|
||||||
|
return 0x0009;
|
||||||
|
case KEYCODE_KP_ENTER:
|
||||||
|
case KEYCODE_RETURN:
|
||||||
|
return 0x000A;
|
||||||
|
case KEYCODE_ESCAPE:
|
||||||
|
return ESCAPE_BUTTON_KEY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return qnxKeycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
//From fg_main_x11
|
||||||
|
fg_time_t fgPlatformSystemTime ( void )
|
||||||
|
{
|
||||||
|
#ifdef CLOCK_MONOTONIC
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
return now.tv_nsec/1000000 + now.tv_sec*1000;
|
||||||
|
#elif defined(HAVE_GETTIMEOFDAY)
|
||||||
|
struct timeval now;
|
||||||
|
gettimeofday( &now, NULL );
|
||||||
|
return now.tv_usec/1000 + now.tv_sec*1000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does the magic required to relinquish the CPU until something interesting
|
||||||
|
* happens.
|
||||||
|
*/
|
||||||
|
void fgPlatformSleepForEvents( fg_time_t msec )
|
||||||
|
{
|
||||||
|
if(fgStructure.CurrentWindow && fgDisplay.pDisplay.event == NULL &&
|
||||||
|
bps_get_event(&fgDisplay.pDisplay.event, (int)msec) != BPS_SUCCESS) {
|
||||||
|
LOGW("BPS couldn't get event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_left_mouse(int x, int y, int height, int eventType, SFG_Window* window)
|
||||||
|
{
|
||||||
|
bool handled = false;
|
||||||
|
/* Virtual arrows PAD */
|
||||||
|
/* Don't interfere with existing mouse move event */
|
||||||
|
if (!touchscreen.in_mmotion) {
|
||||||
|
struct vpad_state prev_vpad = touchscreen.vpad;
|
||||||
|
touchscreen.vpad.left = touchscreen.vpad.right = touchscreen.vpad.up = touchscreen.vpad.down = false;
|
||||||
|
|
||||||
|
if (eventType == SCREEN_EVENT_MTOUCH_TOUCH || eventType == SCREEN_EVENT_MTOUCH_MOVE) {
|
||||||
|
if ((x > 0 && x < 100) && (y > (height - 100) && y < height))
|
||||||
|
{
|
||||||
|
touchscreen.vpad.left = true;
|
||||||
|
}
|
||||||
|
if ((x > 200 && x < 300) && (y > (height - 100) && y < height))
|
||||||
|
{
|
||||||
|
touchscreen.vpad.right = true;
|
||||||
|
}
|
||||||
|
if ((x > 100 && x < 200) && (y > (height - 100) && y < height))
|
||||||
|
{
|
||||||
|
touchscreen.vpad.down = true;
|
||||||
|
}
|
||||||
|
if ((x > 100 && x < 200) && (y > (height - 200) && y < (height - 100)))
|
||||||
|
{
|
||||||
|
touchscreen.vpad.up = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventType == SCREEN_EVENT_MTOUCH_TOUCH &&
|
||||||
|
(touchscreen.vpad.left || touchscreen.vpad.right || touchscreen.vpad.down || touchscreen.vpad.up)) {
|
||||||
|
touchscreen.vpad.on = true;
|
||||||
|
}
|
||||||
|
if (eventType == SCREEN_EVENT_MTOUCH_RELEASE) {
|
||||||
|
touchscreen.vpad.on = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_vpad.left != touchscreen.vpad.left
|
||||||
|
|| prev_vpad.right != touchscreen.vpad.right
|
||||||
|
|| prev_vpad.up != touchscreen.vpad.up
|
||||||
|
|| prev_vpad.down != touchscreen.vpad.down
|
||||||
|
|| prev_vpad.on != touchscreen.vpad.on) {
|
||||||
|
if (FETCH_WCB(*window, Special)) {
|
||||||
|
if (prev_vpad.left == false && touchscreen.vpad.left == true) {
|
||||||
|
INVOKE_WCB(*window, Special, (GLUT_KEY_LEFT, x, y));
|
||||||
|
}
|
||||||
|
else if (prev_vpad.right == false && touchscreen.vpad.right == true) {
|
||||||
|
INVOKE_WCB(*window, Special, (GLUT_KEY_RIGHT, x, y));
|
||||||
|
}
|
||||||
|
else if (prev_vpad.up == false && touchscreen.vpad.up == true) {
|
||||||
|
INVOKE_WCB(*window, Special, (GLUT_KEY_UP, x, y));
|
||||||
|
}
|
||||||
|
else if (prev_vpad.down == false && touchscreen.vpad.down == true) {
|
||||||
|
INVOKE_WCB(*window, Special, (GLUT_KEY_DOWN, x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FETCH_WCB(*window, SpecialUp)) {
|
||||||
|
if (prev_vpad.left == true && touchscreen.vpad.left == false) {
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_LEFT, x, y));
|
||||||
|
}
|
||||||
|
if (prev_vpad.right == true && touchscreen.vpad.right == false) {
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_RIGHT, x, y));
|
||||||
|
}
|
||||||
|
if (prev_vpad.up == true && touchscreen.vpad.up == false) {
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_UP, x, y));
|
||||||
|
}
|
||||||
|
if (prev_vpad.down == true && touchscreen.vpad.down == false) {
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_DOWN, x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normal mouse events */
|
||||||
|
if (!handled && !touchscreen.vpad.on) {
|
||||||
|
window->State.MouseX = x;
|
||||||
|
window->State.MouseY = y;
|
||||||
|
|
||||||
|
if(eventType == SCREEN_EVENT_MTOUCH_MOVE) {
|
||||||
|
INVOKE_WCB(*window, Motion, (x, y));
|
||||||
|
} else if(FETCH_WCB(*window, Mouse)) {
|
||||||
|
touchscreen.in_mmotion = eventType == SCREEN_EVENT_MTOUCH_TOUCH;
|
||||||
|
int glutTouchType = eventType == SCREEN_EVENT_MTOUCH_TOUCH ? GLUT_DOWN : GLUT_UP;
|
||||||
|
INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, glutTouchType, x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine a GLUT modifier mask based on BlackBerry modifier info.
|
||||||
|
*/
|
||||||
|
int fgPlatformGetModifiers (int mod)
|
||||||
|
{
|
||||||
|
return (((mod & KEYMOD_SHIFT) ? GLUT_ACTIVE_SHIFT : 0) |
|
||||||
|
((mod & KEYMOD_CTRL) ? GLUT_ACTIVE_CTRL : 0) |
|
||||||
|
((mod & KEYMOD_ALT) ? GLUT_ACTIVE_ALT : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformHandleKeyboardHeight(SFG_Window* window, int height)
|
||||||
|
{
|
||||||
|
int size[2];
|
||||||
|
int screenHeight;
|
||||||
|
int nScreenHeight = -1;
|
||||||
|
|
||||||
|
screenHeight = glutGet(GLUT_WINDOW_HEIGHT); //Using this takes rotation into account
|
||||||
|
if(height == 0) {
|
||||||
|
nScreenHeight = screenHeight;
|
||||||
|
}
|
||||||
|
else if(!screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_POSITION, size)) {
|
||||||
|
/* Calculate the new screen size */ //XXX Make sure to use display size instead of screen size
|
||||||
|
nScreenHeight = ((size[1] + screenHeight) - height) - size[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nScreenHeight != -1) {
|
||||||
|
/* If nScreenHeight is less then zero then window is covered. If nScreenHeight == height, then no change in size. Else, change in size */
|
||||||
|
|
||||||
|
int screenWidth = glutGet(GLUT_WINDOW_WIDTH);
|
||||||
|
if(nScreenHeight < 0) {
|
||||||
|
LOGI("fgPlatformHandleKeyboardHeight: Covered window state");
|
||||||
|
window->State.Visible = GL_FALSE;
|
||||||
|
window->State.pWState.windowCovered = GL_TRUE;
|
||||||
|
INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_COVERED));
|
||||||
|
fghOnReshapeNotify(window, screenWidth, 0, GL_FALSE);
|
||||||
|
} else {
|
||||||
|
if(window->State.pWState.windowCovered == GL_TRUE) {
|
||||||
|
LOGI("fgPlatformHandleKeyboardHeight: Resetting window state");
|
||||||
|
|
||||||
|
/* Reset window status if it was previously covered */
|
||||||
|
switch(window->State.pWState.windowState) {
|
||||||
|
case NAVIGATOR_WINDOW_FULLSCREEN:
|
||||||
|
window->State.Visible = GL_TRUE;
|
||||||
|
INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED));
|
||||||
|
break;
|
||||||
|
case NAVIGATOR_WINDOW_THUMBNAIL:
|
||||||
|
window->State.Visible = GL_TRUE;
|
||||||
|
INVOKE_WCB(*window, WindowStatus, (GLUT_PARTIALLY_RETAINED));
|
||||||
|
break;
|
||||||
|
case NAVIGATOR_WINDOW_INVISIBLE:
|
||||||
|
window->State.Visible = GL_FALSE;
|
||||||
|
INVOKE_WCB(*window, WindowStatus, (GLUT_HIDDEN));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
window->State.pWState.windowCovered = GL_FALSE;
|
||||||
|
}
|
||||||
|
fghOnReshapeNotify(window, screenWidth, nScreenHeight, GL_FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformProcessSingleEvent ( void )
|
||||||
|
{
|
||||||
|
if(fgStructure.CurrentWindow == NULL) {
|
||||||
|
//XXX Is this right? Would this just cause a whole lot of busy looping while we wait for events?
|
||||||
|
LOGW("fgPlatformProcessSingleEvent: Missing current window. Skipping event processing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fgDisplay.pDisplay.event == NULL)
|
||||||
|
/* Nothing to do */
|
||||||
|
return;
|
||||||
|
|
||||||
|
int domain;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
SFG_Window* window = fgStructure.CurrentWindow;
|
||||||
|
/* Get the keyboard height before doing anything since we otherwise don't get it until it changes */
|
||||||
|
if(window->State.pWState.keyboardHeight == 0) {
|
||||||
|
virtualkeyboard_get_height(&window->State.pWState.keyboardHeight);
|
||||||
|
}
|
||||||
|
domain = bps_event_get_domain(fgDisplay.pDisplay.event);
|
||||||
|
if (domain == screen_get_domain()) {
|
||||||
|
int eventType;
|
||||||
|
int mod;
|
||||||
|
screen_event_t screenEvent = screen_event_get_event(fgDisplay.pDisplay.event);
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_TYPE, &eventType);
|
||||||
|
switch (eventType) {
|
||||||
|
|
||||||
|
//Mostly from fg_main_android
|
||||||
|
case SCREEN_EVENT_MTOUCH_TOUCH:
|
||||||
|
case SCREEN_EVENT_MTOUCH_RELEASE:
|
||||||
|
case SCREEN_EVENT_MTOUCH_MOVE:
|
||||||
|
{
|
||||||
|
mtouch_event_t touchEvent;
|
||||||
|
screen_get_mtouch_event(screenEvent, &touchEvent, 0);
|
||||||
|
#ifndef __PLAYBOOK__
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
|
||||||
|
#else
|
||||||
|
mod = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_MTOUCH_*: Type: 0x%X, X: %d, Y: %d, Contact Id: %d, Mod: 0x%X", SLOG2_FA_SIGNED(eventType), SLOG2_FA_SIGNED(touchEvent.x), SLOG2_FA_SIGNED(touchEvent.y), SLOG2_FA_SIGNED(touchEvent.contact_id), SLOG2_FA_SIGNED(mod));
|
||||||
|
|
||||||
|
/* Remember the current modifiers state so user can query it from their callback */
|
||||||
|
fgState.Modifiers = fgPlatformGetModifiers(mod);
|
||||||
|
|
||||||
|
if(touchEvent.contact_id == 0) {
|
||||||
|
int size[2];
|
||||||
|
screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size);
|
||||||
|
handle_left_mouse(touchEvent.x, touchEvent.y, size[1], eventType, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Now handle mutlitouch (adapted from fg_main_windows)
|
||||||
|
if (eventType == SCREEN_EVENT_MTOUCH_TOUCH) {
|
||||||
|
INVOKE_WCB( *window, MultiEntry, ( touchEvent.contact_id, GLUT_ENTERED ) );
|
||||||
|
INVOKE_WCB( *window, MultiButton, ( touchEvent.contact_id, touchEvent.x, touchEvent.y, 0, GLUT_DOWN ) );
|
||||||
|
} else if (eventType == SCREEN_EVENT_MTOUCH_MOVE) {
|
||||||
|
INVOKE_WCB( *window, MultiMotion, ( touchEvent.contact_id, touchEvent.x, touchEvent.y ) );
|
||||||
|
//XXX No motion is performed without contact, thus MultiPassive is never used
|
||||||
|
} else if (eventType == SCREEN_EVENT_MTOUCH_RELEASE) {
|
||||||
|
INVOKE_WCB( *window, MultiButton, ( touchEvent.contact_id, touchEvent.x, touchEvent.y, 0, GLUT_UP ) );
|
||||||
|
INVOKE_WCB( *window, MultiEntry, ( touchEvent.contact_id, GLUT_LEFT ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
fgState.Modifiers = INVALID_MODIFIERS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SCREEN_EVENT_POINTER:
|
||||||
|
{
|
||||||
|
//Based off/part taken from GamePlay3d PlatformBlackBerry
|
||||||
|
static int mouse_pressed = 0;
|
||||||
|
int buttons;
|
||||||
|
int position[2];
|
||||||
|
int wheel;
|
||||||
|
// A move event will be fired unless a button state changed.
|
||||||
|
bool move = true;
|
||||||
|
bool left_move = false;
|
||||||
|
// This is a mouse move event, it is applicable to a device with a usb mouse or simulator.
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons);
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position);
|
||||||
|
#ifndef __PLAYBOOK__
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel);
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
|
||||||
|
#else
|
||||||
|
wheel = mod = 0;
|
||||||
|
#endif
|
||||||
|
int size[2];
|
||||||
|
screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size);
|
||||||
|
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_POINTER: Buttons: 0x%X, X: %d, Y: %d, Wheel: %d, Mod: 0x%X", SLOG2_FA_SIGNED(buttons), SLOG2_FA_SIGNED(position[0]), SLOG2_FA_SIGNED(position[1]), SLOG2_FA_SIGNED(wheel), SLOG2_FA_SIGNED(mod));
|
||||||
|
|
||||||
|
//XXX Is multitouch be handled in a good way?
|
||||||
|
|
||||||
|
/* Remember the current modifiers state so user can query it from their callback */
|
||||||
|
fgState.Modifiers = fgPlatformGetModifiers(mod);
|
||||||
|
|
||||||
|
// Handle left mouse. Interpret as touch if the left mouse event is not consumed.
|
||||||
|
if (buttons & SCREEN_LEFT_MOUSE_BUTTON) {
|
||||||
|
if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON) {
|
||||||
|
left_move = true;
|
||||||
|
} else {
|
||||||
|
move = false;
|
||||||
|
mouse_pressed |= SCREEN_LEFT_MOUSE_BUTTON;
|
||||||
|
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_TOUCH, window);
|
||||||
|
}
|
||||||
|
} else if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON) {
|
||||||
|
move = false;
|
||||||
|
mouse_pressed &= ~SCREEN_LEFT_MOUSE_BUTTON;
|
||||||
|
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_RELEASE, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle right mouse.
|
||||||
|
if (buttons & SCREEN_RIGHT_MOUSE_BUTTON) {
|
||||||
|
if ((mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) == 0) {
|
||||||
|
move = false;
|
||||||
|
mouse_pressed |= SCREEN_RIGHT_MOUSE_BUTTON;
|
||||||
|
INVOKE_WCB(*window, Mouse, (GLUT_RIGHT_BUTTON, GLUT_DOWN, position[0], position[1]));
|
||||||
|
}
|
||||||
|
} else if (mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) {
|
||||||
|
move = false;
|
||||||
|
mouse_pressed &= ~SCREEN_RIGHT_MOUSE_BUTTON;
|
||||||
|
INVOKE_WCB(*window, Mouse, (GLUT_RIGHT_BUTTON, GLUT_UP, position[0], position[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle middle mouse.
|
||||||
|
if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON) {
|
||||||
|
if ((mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) == 0) {
|
||||||
|
move = false;
|
||||||
|
mouse_pressed |= SCREEN_MIDDLE_MOUSE_BUTTON;
|
||||||
|
INVOKE_WCB(*window, Mouse, (GLUT_MIDDLE_BUTTON, GLUT_DOWN, position[0], position[1]));
|
||||||
|
}
|
||||||
|
} else if (mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) {
|
||||||
|
move = false;
|
||||||
|
mouse_pressed &= ~SCREEN_MIDDLE_MOUSE_BUTTON;
|
||||||
|
INVOKE_WCB(*window, Mouse, (GLUT_MIDDLE_BUTTON, GLUT_UP, position[0], position[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire a move event if none of the buttons changed.
|
||||||
|
if (left_move || move) {
|
||||||
|
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_MOVE, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wheel) {
|
||||||
|
/* Very slightly modified from fg_main_mswin.
|
||||||
|
* Because we don't want MouseWheel to be called every. single. time.
|
||||||
|
* That the action occurs, we mimic the Windows version with "wheel deltas"
|
||||||
|
* XXX Do we even want this?
|
||||||
|
* XXX If we want this, it's possible to get horizontal scroll as well.
|
||||||
|
* XXX -Vertical scroll=wheel 0, horizontal=wheel 1? */
|
||||||
|
fgState.MouseWheelTicks -= wheel;
|
||||||
|
if (abs(fgState.MouseWheelTicks) >= WHEEL_DELTA)
|
||||||
|
{
|
||||||
|
int wheel_number = 0;
|
||||||
|
int direction = (fgState.MouseWheelTicks > 0) ? -1 : 1;
|
||||||
|
|
||||||
|
if (!FETCH_WCB(*window, MouseWheel) && !FETCH_WCB(*window, Mouse))
|
||||||
|
break;
|
||||||
|
|
||||||
|
//XXX fgSetWindow(window);
|
||||||
|
|
||||||
|
while(abs(fgState.MouseWheelTicks) >= WHEEL_DELTA)
|
||||||
|
{
|
||||||
|
if (FETCH_WCB(*window, MouseWheel))
|
||||||
|
INVOKE_WCB(*window, MouseWheel, (wheel_number, direction, window->State.MouseX, window->State.MouseY));
|
||||||
|
else /* No mouse wheel, call the mouse button callback twice */
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Map wheel zero to button 3 and 4; +1 to 3, -1 to 4
|
||||||
|
* " " one +1 to 5, -1 to 6, ...
|
||||||
|
*
|
||||||
|
* XXX The below assumes that you have no more than 3 mouse
|
||||||
|
* XXX buttons. Sorry.
|
||||||
|
*/
|
||||||
|
int button = wheel_number * 2 + 3;
|
||||||
|
if (direction < 0)
|
||||||
|
++button;
|
||||||
|
INVOKE_WCB(*window, Mouse, (button, GLUT_DOWN, window->State.MouseX, window->State.MouseY));
|
||||||
|
INVOKE_WCB(*window, Mouse, (button, GLUT_UP, window->State.MouseX, window->State.MouseY));
|
||||||
|
}
|
||||||
|
|
||||||
|
fgState.MouseWheelTicks -= WHEEL_DELTA * direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fgState.Modifiers = INVALID_MODIFIERS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Based off fg_main_android
|
||||||
|
case SCREEN_EVENT_KEYBOARD:
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
int value;
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags);
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_SYM, &value);
|
||||||
|
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
|
||||||
|
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Flags: 0x%X, Sym: 0x%X, Mod: 0x%X", SLOG2_FA_SIGNED(flags), SLOG2_FA_SIGNED(value), SLOG2_FA_SIGNED(mod));
|
||||||
|
|
||||||
|
/* Suppress key repeats if desired. Based off fg_main_mswin */
|
||||||
|
if ((flags & KEY_REPEAT) == 0 || (fgState.KeyRepeat == GLUT_KEY_REPEAT_OFF && fgStructure.CurrentWindow->State.IgnoreKeyRepeat == GL_TRUE)) {
|
||||||
|
unsigned int keypress = 0;
|
||||||
|
unsigned char ascii = 0;
|
||||||
|
|
||||||
|
/* Remember the current modifiers state so user can query it from their callback */
|
||||||
|
fgState.Modifiers = fgPlatformGetModifiers(mod);
|
||||||
|
|
||||||
|
/* Process keys */
|
||||||
|
if ((keypress = key_special(value))) {
|
||||||
|
if(flags & KEY_DOWN) {
|
||||||
|
INVOKE_WCB(*window, Special, (keypress, window->State.MouseX, window->State.MouseY));
|
||||||
|
} else {
|
||||||
|
INVOKE_WCB(*window, SpecialUp, (keypress, window->State.MouseX, window->State.MouseY));
|
||||||
|
}
|
||||||
|
} else if((flags & KEY_SYM_VALID) && (ascii = key_ascii(value))) {
|
||||||
|
if(flags & KEY_DOWN) {
|
||||||
|
INVOKE_WCB(*window, Keyboard, (ascii, window->State.MouseX, window->State.MouseY));
|
||||||
|
} else {
|
||||||
|
INVOKE_WCB(*window, KeyboardUp, (ascii, window->State.MouseX, window->State.MouseY));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGW("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Unhandled key event");
|
||||||
|
}
|
||||||
|
|
||||||
|
fgState.Modifiers = INVALID_MODIFIERS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SCREEN_EVENT_PROPERTY:
|
||||||
|
case SCREEN_EVENT_IDLE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOGW("fgPlatformProcessSingleEvent: unknown screen event: 0x%X", SLOG2_FA_SIGNED(eventType));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (domain == navigator_get_domain()) {
|
||||||
|
unsigned int eventType = bps_event_get_code(fgDisplay.pDisplay.event);
|
||||||
|
switch (eventType) {
|
||||||
|
|
||||||
|
case NAVIGATOR_WINDOW_STATE:
|
||||||
|
{
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE");
|
||||||
|
|
||||||
|
/* Covered only happens due to keyboard. When the app is minimized, the keyboard is closed.
|
||||||
|
When the keyboard is open, and the app is fullscreened, the keyboard is also closed.
|
||||||
|
If a window is covered and the app is minimized, the state will be set and the keyboard event
|
||||||
|
will adjust the screen size and change window status. */
|
||||||
|
navigator_window_state_t state = navigator_event_get_window_state(fgDisplay.pDisplay.event);
|
||||||
|
if(window->State.pWState.windowCovered == GL_FALSE)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case NAVIGATOR_WINDOW_FULLSCREEN:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_FULLSCREEN");
|
||||||
|
window->State.Visible = GL_TRUE;
|
||||||
|
INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED));
|
||||||
|
break;
|
||||||
|
case NAVIGATOR_WINDOW_THUMBNAIL:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_THUMBNAIL");
|
||||||
|
window->State.Visible = GL_TRUE;
|
||||||
|
INVOKE_WCB(*window, WindowStatus, (GLUT_PARTIALLY_RETAINED));
|
||||||
|
break;
|
||||||
|
case NAVIGATOR_WINDOW_INVISIBLE:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_INVISIBLE");
|
||||||
|
window->State.Visible = GL_FALSE;
|
||||||
|
INVOKE_WCB(*window, WindowStatus, (GLUT_HIDDEN));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE unknown: 0x%X", SLOG2_FA_SIGNED(state));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window->State.pWState.windowState = state;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NAVIGATOR_EXIT:
|
||||||
|
{
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_EXIT");
|
||||||
|
|
||||||
|
fgPlatformMainLoopPostWork();
|
||||||
|
|
||||||
|
/* User closed the application for good, let's kill the window */
|
||||||
|
SFG_Window* window = fgStructure.CurrentWindow;
|
||||||
|
if (window != NULL) {
|
||||||
|
fgDestroyWindow(window);
|
||||||
|
} else {
|
||||||
|
LOGW("NAVIGATOR_EXIT: No current window");
|
||||||
|
}
|
||||||
|
|
||||||
|
//XXX Should this be a bit more "forceful" so that it doesn't continue to loop through events?
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NAVIGATOR_SWIPE_DOWN:
|
||||||
|
/* XXX Open app menu */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Orientation is a bunch of handshakes.
|
||||||
|
- First the app get's asked if it wants to rotate (NAVIGATOR_ORIENTATION_CHECK)
|
||||||
|
- If the app wants to rotate, then it will be told what size it will be after rotate (NAVIGATOR_ORIENTATION_SIZE).
|
||||||
|
- Once the OS confirms that it's ready to rotate, it tells the app to handle rotation (NAVIGATOR_ORIENTATION).
|
||||||
|
- Once rotation is complete, the OS tells the app it's done (NAVIGATOR_ORIENTATION_DONE) */
|
||||||
|
case NAVIGATOR_ORIENTATION_CHECK:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_CHECK");
|
||||||
|
|
||||||
|
/* Reset sizes */
|
||||||
|
window->State.pWState.newWidth = 0;
|
||||||
|
window->State.pWState.newHeight = 0;
|
||||||
|
|
||||||
|
#ifdef __PLAYBOOK__
|
||||||
|
/* On rotation, the keyboard is closed. This prevents two resize calls */
|
||||||
|
window->State.pWState.keyboardOpen = GL_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Notify that we want to rotate */
|
||||||
|
navigator_orientation_check_response(fgDisplay.pDisplay.event, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_ORIENTATION:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION");
|
||||||
|
|
||||||
|
/* NAVIGATOR_ORIENTATION occurs before NAVIGATOR_KEYBOARD_POSITION */
|
||||||
|
|
||||||
|
/* Rotate and resize the window */
|
||||||
|
fgPlatformRotateWindow(window, navigator_event_get_orientation_angle(fgDisplay.pDisplay.event));
|
||||||
|
fgPlatformFlushCommands();
|
||||||
|
#ifdef __PLAYBOOK__
|
||||||
|
/* PlayBook doesn't indicate what the new size will be, so we need to retrieve it from the window itself */
|
||||||
|
window->State.pWState.newWidth = glutGet(GLUT_WINDOW_WIDTH);
|
||||||
|
window->State.pWState.newHeight = glutGet(GLUT_WINDOW_HEIGHT);
|
||||||
|
fghOnReshapeNotify(window, window->State.pWState.newWidth, window->State.pWState.newHeight, GL_FALSE);
|
||||||
|
#else
|
||||||
|
if(window->State.pWState.keyboardOpen == GL_FALSE) {
|
||||||
|
/* On rotation, if the keyboard is open, it will get the keyboard resize events anyway. Otherwise, handle the resize. */
|
||||||
|
fghOnReshapeNotify(window, window->State.pWState.newWidth, window->State.pWState.newHeight, GL_FALSE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Reset sizes */
|
||||||
|
window->State.pWState.newWidth = 0;
|
||||||
|
window->State.pWState.newHeight = 0;
|
||||||
|
|
||||||
|
/* Done rotating */
|
||||||
|
navigator_done_orientation(fgDisplay.pDisplay.event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_BACK:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_BACK");
|
||||||
|
INVOKE_WCB(*window, Keyboard, (ESCAPE_BUTTON_KEY, window->State.MouseX, window->State.MouseY));
|
||||||
|
INVOKE_WCB(*window, KeyboardUp, (ESCAPE_BUTTON_KEY, window->State.MouseX, window->State.MouseY));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_WINDOW_ACTIVE:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_ACTIVE");
|
||||||
|
INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_RESUME));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_WINDOW_INACTIVE:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_INACTIVE");
|
||||||
|
INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_PAUSE));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_ORIENTATION_DONE:
|
||||||
|
case NAVIGATOR_ORIENTATION_RESULT:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_DONE/NAVIGATOR_ORIENTATION_RESULT");
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifndef __PLAYBOOK__
|
||||||
|
case NAVIGATOR_KEYBOARD_STATE:
|
||||||
|
case NAVIGATOR_KEYBOARD_POSITION:
|
||||||
|
/* See virtual keyboard handling for info on why this is not used. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_DEVICE_LOCK_STATE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_WINDOW_COVER:
|
||||||
|
case NAVIGATOR_WINDOW_COVER_ENTER:
|
||||||
|
case NAVIGATOR_WINDOW_COVER_EXIT:
|
||||||
|
/* BlackBerry specific. Let app status and window status take care of everything */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_APP_STATE:
|
||||||
|
/* Can do the same as NAVIGATOR_WINDOW_ACTIVE/NAVIGATOR_WINDOW_INACTIVE but
|
||||||
|
seems like it doesn't work when the app comes to the foreground. Might be a bug */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAVIGATOR_ORIENTATION_SIZE:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_SIZE");
|
||||||
|
|
||||||
|
/* Get new window size */
|
||||||
|
window->State.pWState.newWidth = navigator_event_get_orientation_size_width(fgDisplay.pDisplay.event);
|
||||||
|
window->State.pWState.newHeight = navigator_event_get_orientation_size_height(fgDisplay.pDisplay.event);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 0: //Doesn't exist in header, but shows up when keyboard shows and resizes
|
||||||
|
case NAVIGATOR_OTHER:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOGW("fgPlatformProcessSingleEvent: unknown navigator event: 0x%X", SLOG2_FA_SIGNED(eventType));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* BlackBerry 10 navigator provides keyboard events, but they conflict with how we handle keyboard events.
|
||||||
|
* Causing multiple reshape messages and can leave window state incorrectly setup.
|
||||||
|
*/
|
||||||
|
else if(domain == virtualkeyboard_get_domain()) {
|
||||||
|
unsigned int eventType = bps_event_get_code(fgDisplay.pDisplay.event);
|
||||||
|
switch (eventType) {
|
||||||
|
case VIRTUALKEYBOARD_EVENT_VISIBLE:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_VISIBLE");
|
||||||
|
if(window->State.pWState.keyboardOpen != GL_TRUE) {
|
||||||
|
window->State.pWState.keyboardOpen = GL_TRUE;
|
||||||
|
fgPlatformHandleKeyboardHeight(window, window->State.pWState.keyboardHeight);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIRTUALKEYBOARD_EVENT_HIDDEN:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_HIDDEN");
|
||||||
|
if(window->State.pWState.keyboardOpen != GL_FALSE) {
|
||||||
|
window->State.pWState.keyboardOpen = GL_FALSE;
|
||||||
|
fgPlatformHandleKeyboardHeight(window, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIRTUALKEYBOARD_EVENT_INFO:
|
||||||
|
LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_INFO");
|
||||||
|
window->State.pWState.keyboardHeight = virtualkeyboard_event_get_height(fgDisplay.pDisplay.event);
|
||||||
|
if(window->State.pWState.keyboardOpen == GL_TRUE) {
|
||||||
|
fgPlatformHandleKeyboardHeight(window, window->State.pWState.keyboardHeight);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOGW("fgPlatformProcessSingleEvent: unknown virtualkeyboard event: 0x%X", eventType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(bps_get_event(&fgDisplay.pDisplay.event, 1) == BPS_SUCCESS && fgDisplay.pDisplay.event != NULL);
|
||||||
|
|
||||||
|
/* Reset event to reduce chances of triggering something */
|
||||||
|
fgDisplay.pDisplay.event = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformMainLoopPreliminaryWork ( void )
|
||||||
|
{
|
||||||
|
LOGI("fgPlatformMainLoopPreliminaryWork");
|
||||||
|
|
||||||
|
/* Request navigator events */
|
||||||
|
navigator_request_events(NAVIGATOR_EXTENDED_DATA);
|
||||||
|
|
||||||
|
/* Allow rotation */
|
||||||
|
navigator_rotation_lock(false);
|
||||||
|
|
||||||
|
/* Request keyboard events */
|
||||||
|
virtualkeyboard_request_events(0);
|
||||||
|
|
||||||
|
/* Request window events */
|
||||||
|
screen_request_events(fgDisplay.pDisplay.screenContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformMainLoopPostWork ( void )
|
||||||
|
{
|
||||||
|
LOGI("fgPlatformMainLoopPostWork");
|
||||||
|
|
||||||
|
/* Stop all events */
|
||||||
|
screen_stop_events(fgDisplay.pDisplay.screenContext);
|
||||||
|
|
||||||
|
#ifndef __PLAYBOOK__
|
||||||
|
navigator_stop_events(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* deal with work list items */
|
||||||
|
void fgPlatformInitWork(SFG_Window* window)
|
||||||
|
{
|
||||||
|
LOGI("fgPlatformInitWork");
|
||||||
|
|
||||||
|
/* Position callback, always at 0,0 */
|
||||||
|
fghOnPositionNotify(window, 0, 0, GL_TRUE);
|
||||||
|
|
||||||
|
/* Get window size */
|
||||||
|
int size[2];
|
||||||
|
screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size);
|
||||||
|
fghOnReshapeNotify(window, size[0], size[1], GL_FALSE);
|
||||||
|
|
||||||
|
/* Size gets notified on window creation with size detection in mainloop above
|
||||||
|
* XXX CHECK: does this messages happen too early like on windows,
|
||||||
|
* so client code cannot have registered a callback yet and the message
|
||||||
|
* is thus never received by client?
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask)
|
||||||
|
{
|
||||||
|
if (workMask & GLUT_FULL_SCREEN_WORK)
|
||||||
|
fgPlatformFullScreenToggle( window );
|
||||||
|
if (workMask & GLUT_POSITION_WORK)
|
||||||
|
fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos );
|
||||||
|
if (workMask & GLUT_SIZE_WORK)
|
||||||
|
fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight );
|
||||||
|
if (workMask & GLUT_ZORDER_WORK)
|
||||||
|
{
|
||||||
|
if (window->State.DesiredZOrder < 0)
|
||||||
|
fgPlatformPushWindow( window );
|
||||||
|
else
|
||||||
|
fgPlatformPopWindow( window );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformVisibilityWork(SFG_Window* window)
|
||||||
|
{
|
||||||
|
/* Visibility status of window should get updated in the window message handlers
|
||||||
|
* For now, none of these functions called below do anything, so don't worry
|
||||||
|
* about it
|
||||||
|
*/
|
||||||
|
SFG_Window *win = window;
|
||||||
|
switch (window->State.DesiredVisibility)
|
||||||
|
{
|
||||||
|
case DesireHiddenState:
|
||||||
|
fgPlatformHideWindow( window );
|
||||||
|
break;
|
||||||
|
case DesireIconicState:
|
||||||
|
/* Call on top-level window */
|
||||||
|
while (win->Parent)
|
||||||
|
win = win->Parent;
|
||||||
|
fgPlatformIconifyWindow( win );
|
||||||
|
break;
|
||||||
|
case DesireNormalState:
|
||||||
|
fgPlatformShowWindow( window );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dummy functions, not applicable on blackberry */
|
||||||
|
void fgPlatformSetColor(int idx, float r, float g, float b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float fgPlatformGetColor(int idx, int comp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformCopyColormap(int win)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* fg_state_blackberry.c
|
||||||
|
*
|
||||||
|
* BlackBerry-specific freeglut state query methods.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
|
||||||
|
* Written by John F. Fay, <fayjf@sourceforge.net>
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
* Copyright (C) 2013 Vincent Simonetti
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <screen/screen.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "egl/fg_state_egl.h"
|
||||||
|
|
||||||
|
//From fg_state_android.c
|
||||||
|
int fgPlatformGlutDeviceGet ( GLenum eWhat )
|
||||||
|
{
|
||||||
|
#ifndef __PLAYBOOK__
|
||||||
|
int deviceCount, i, value;
|
||||||
|
screen_device_t* devices;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch( eWhat )
|
||||||
|
{
|
||||||
|
case GLUT_HAS_KEYBOARD:
|
||||||
|
/* BlackBerry has a keyboard, though it may be virtual. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case GLUT_HAS_MOUSE:
|
||||||
|
/* BlackBerry has a touchscreen. Consider it as a mouse since we have no guarantee
|
||||||
|
that a mouse will be used (in which case it's a simulator). */
|
||||||
|
return 1 ;
|
||||||
|
|
||||||
|
case GLUT_NUM_MOUSE_BUTTONS:
|
||||||
|
/* BlackBerry has a touchscreen, which we can consider a 1-button mouse at min.
|
||||||
|
Otherwise check for an actual mouse, else get max touch points. PlayBook does not support this. */
|
||||||
|
#ifndef __PLAYBOOK__
|
||||||
|
if(!screen_get_context_property_iv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DEVICE_COUNT, &deviceCount)) {
|
||||||
|
devices = (screen_device_t*)calloc(deviceCount, sizeof(screen_device_t));
|
||||||
|
if(!screen_get_context_property_pv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DEVICES, (void**)devices)) {
|
||||||
|
/* Check for a pointer */
|
||||||
|
for(i = 0; i < deviceCount; i++) {
|
||||||
|
if(!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_TYPE, &value) &&
|
||||||
|
value == SCREEN_EVENT_POINTER &&
|
||||||
|
!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_BUTTON_COUNT, &value)) {
|
||||||
|
free(devices);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check for mtouch */
|
||||||
|
for(i = 0; i < deviceCount; i++) {
|
||||||
|
if(!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_TYPE, &value) &&
|
||||||
|
value == SCREEN_EVENT_MTOUCH_TOUCH &&
|
||||||
|
!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_MAXIMUM_TOUCH_ID, &value)) {
|
||||||
|
free(devices);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(devices);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Backup, pretend it's a 1-button mouse */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And now -- the failure. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fgPlatformGlutGet ( GLenum eWhat )
|
||||||
|
{
|
||||||
|
switch (eWhat) {
|
||||||
|
/* One full-screen window only */
|
||||||
|
case GLUT_WINDOW_X:
|
||||||
|
case GLUT_WINDOW_Y:
|
||||||
|
case GLUT_WINDOW_BORDER_WIDTH:
|
||||||
|
case GLUT_WINDOW_HEADER_HEIGHT:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case GLUT_WINDOW_WIDTH:
|
||||||
|
case GLUT_WINDOW_HEIGHT:
|
||||||
|
{
|
||||||
|
if ( fgStructure.CurrentWindow == NULL )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int size[2];
|
||||||
|
int orientation;
|
||||||
|
if ( screen_get_window_property_iv(fgStructure.CurrentWindow->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size) != 0 )
|
||||||
|
return 0;
|
||||||
|
if ( screen_get_window_property_iv(fgStructure.CurrentWindow->Window.Handle, SCREEN_PROPERTY_ROTATION, &orientation) != 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int orientationDif = abs(orientation - fgStructure.CurrentWindow->State.pWState.originalRotation);
|
||||||
|
if (orientationDif == 90 || orientationDif == 270) {
|
||||||
|
/* Swap dim. if screen is rotated */
|
||||||
|
int tmp = size[0];
|
||||||
|
size[0] = size[1];
|
||||||
|
size[1] = tmp;
|
||||||
|
}
|
||||||
|
switch ( eWhat )
|
||||||
|
{
|
||||||
|
case GLUT_WINDOW_WIDTH:
|
||||||
|
return size[0];
|
||||||
|
case GLUT_WINDOW_HEIGHT:
|
||||||
|
return size[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLUT_WINDOW_COLORMAP_SIZE:
|
||||||
|
/* 0 for RGBA/non-indexed mode */
|
||||||
|
/* Under BlackBerry and GLES more generally, no indexed-mode */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fghPlatformGlutGetEGL(eWhat);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* fg_structure_blackberry.c
|
||||||
|
*
|
||||||
|
* Windows and menus need tree structure
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
* Copyright (C) 2013 Vincent Simonetti
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "egl/fg_structure_egl.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize default platform-specific fields in SFG_Window
|
||||||
|
*/
|
||||||
|
void fgPlatformCreateWindow ( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fghPlatformCreateWindowEGL(window);
|
||||||
|
|
||||||
|
memset(&(window->State.pWState), 0, sizeof(SFG_PlatformWindowState));
|
||||||
|
window->State.pWState.windowCovered = GL_FALSE;
|
||||||
|
#ifdef __PLAYBOOK__
|
||||||
|
window->State.pWState.keyboardOpen = GL_FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,327 @@
|
||||||
|
/*
|
||||||
|
* fg_window_blackberry.c
|
||||||
|
*
|
||||||
|
* Window management methods for BlackBerry
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
|
||||||
|
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
|
||||||
|
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
* Copyright (C) 2013 Vincent Simonetti
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FREEGLUT_BUILDING_LIB
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
#include "egl/fg_window_egl.h"
|
||||||
|
#include <sys/pps.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opens a window. Requires a SFG_Window object created and attached
|
||||||
|
* to the freeglut structure. OpenGL context is created here.
|
||||||
|
*/
|
||||||
|
void fgPlatformOpenWindow( SFG_Window* window, const char* title,
|
||||||
|
GLboolean positionUse, int x, int y,
|
||||||
|
GLboolean sizeUse, int w, int h,
|
||||||
|
GLboolean gameMode, GLboolean isSubWindow )
|
||||||
|
{
|
||||||
|
/* TODO: only one full-screen window possible? */
|
||||||
|
if (fgDisplay.pDisplay.single_native_window != NULL) {
|
||||||
|
fgWarning("You can't have more than one window on BlackBerry");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create window */
|
||||||
|
screen_window_t sWindow;
|
||||||
|
if (screen_create_window(&sWindow, fgDisplay.pDisplay.screenContext)) {
|
||||||
|
fgError("Could not create window");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fgDisplay.pDisplay.single_native_window = sWindow;
|
||||||
|
|
||||||
|
/* Choose config and screen format */
|
||||||
|
fghChooseConfig(&window->Window.pContext.egl.Config);
|
||||||
|
int screenFormat = SCREEN_FORMAT_RGBA8888; //Only SCREEN_FORMAT_RGBA8888 and SCREEN_FORMAT_RGB565 are supported. See fg_window_egl for more info
|
||||||
|
int configAttri;
|
||||||
|
#define EGL_QUERY_COMP(att, comp) (eglGetConfigAttrib(fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Config, att, &configAttri) == GL_TRUE && (configAttri comp))
|
||||||
|
if (EGL_QUERY_COMP(EGL_ALPHA_SIZE, <= 0) && EGL_QUERY_COMP(EGL_RED_SIZE, <= 5) &&
|
||||||
|
EGL_QUERY_COMP(EGL_GREEN_SIZE, <= 6) && EGL_QUERY_COMP(EGL_BLUE_SIZE, <= 5)) {
|
||||||
|
screenFormat = SCREEN_FORMAT_RGB565;
|
||||||
|
}
|
||||||
|
#undef EGL_QUERY_COMP
|
||||||
|
|
||||||
|
/* Set window properties */
|
||||||
|
int orientation = atoi(getenv("ORIENTATION"));
|
||||||
|
int screenUsage = SCREEN_USAGE_ROTATION;
|
||||||
|
#ifdef SCREEN_USAGE_OPENGL_ES3
|
||||||
|
if (fgState.MajorVersion >= 3) {
|
||||||
|
screenUsage |= SCREEN_USAGE_OPENGL_ES3;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (fgState.MajorVersion >= 2) {
|
||||||
|
screenUsage |= SCREEN_USAGE_OPENGL_ES2;
|
||||||
|
} else {
|
||||||
|
screenUsage |= SCREEN_USAGE_OPENGL_ES1;
|
||||||
|
}
|
||||||
|
#if !defined(__X86__) && !defined(__PLAYBOOK__)
|
||||||
|
screenUsage |= SCREEN_USAGE_DISPLAY; // Physical device copy directly into physical display
|
||||||
|
#endif
|
||||||
|
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_FORMAT, &screenFormat)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not set window format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_USAGE, &screenUsage)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not set window usage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int value[2];
|
||||||
|
/* Uncomment when multiple windows are supported
|
||||||
|
if(positionUse) {
|
||||||
|
value[0] = x;
|
||||||
|
value[1] = y;
|
||||||
|
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_POSITION, value)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not set window position");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if(sizeUse) {
|
||||||
|
/* Uncomment when multiple windows are supported
|
||||||
|
value[0] = w;
|
||||||
|
value[1] = h;
|
||||||
|
*/
|
||||||
|
//TEMP until ^^ is uncommented
|
||||||
|
if (screen_get_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not get window mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* From PlatformBlackBerry in GamePlay3d */
|
||||||
|
screen_display_t display;
|
||||||
|
if (screen_get_window_property_pv(sWindow, SCREEN_PROPERTY_DISPLAY, (void**)&display)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not get window display");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_display_mode_t displayMode;
|
||||||
|
if (screen_get_display_property_pv(display, SCREEN_PROPERTY_MODE, (void**)&displayMode)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not get display mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screen_get_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not get window mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust buffer sizes based on rotation */
|
||||||
|
if ((orientation == 0) || (orientation == 180))
|
||||||
|
{
|
||||||
|
if (((displayMode.width > displayMode.height) && (value[0] < value[1])) ||
|
||||||
|
((displayMode.width < displayMode.height) && (value[0] > value[1])))
|
||||||
|
{
|
||||||
|
int tmp = value[1];
|
||||||
|
value[1] = value[0];
|
||||||
|
value[0] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((orientation == 90) || (orientation == 270))
|
||||||
|
{
|
||||||
|
if (((displayMode.width > displayMode.height) && (value[0] > value[1])) ||
|
||||||
|
((displayMode.width < displayMode.height) && (value[0] < value[1])))
|
||||||
|
{
|
||||||
|
int tmp = value[1];
|
||||||
|
value[1] = value[0];
|
||||||
|
value[0] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Unexpected rotation angle");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set rotation if usage allows it */
|
||||||
|
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_ROTATION, &orientation)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not set window rotation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window->State.pWState.originalRotation = orientation;
|
||||||
|
|
||||||
|
/* Set buffer sizes */
|
||||||
|
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not set window buffer size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create window buffers */
|
||||||
|
if (screen_create_window_buffers(sWindow, (fgState.DisplayMode & GLUT_DOUBLE) ? 2 : 1)) {
|
||||||
|
screen_destroy_window(sWindow);
|
||||||
|
fgError("Could not create window buffers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save window and set state */
|
||||||
|
window->Window.Handle = sWindow;
|
||||||
|
window->State.WorkMask |= GLUT_INIT_WORK;
|
||||||
|
window->State.IsFullscreen = GL_TRUE; //XXX Always fullscreen for now
|
||||||
|
|
||||||
|
/* Create context */
|
||||||
|
window->Window.Context = EGL_NO_CONTEXT;
|
||||||
|
if( fgState.UseCurrentContext == GL_TRUE )
|
||||||
|
window->Window.Context = eglGetCurrentContext();
|
||||||
|
if( window->Window.Context == EGL_NO_CONTEXT )
|
||||||
|
window->Window.Context = fghCreateNewContextEGL(window);
|
||||||
|
|
||||||
|
/* Create EGL window */
|
||||||
|
fghPlatformOpenWindowEGL(window);
|
||||||
|
|
||||||
|
window->State.Visible = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformFlushCommands()
|
||||||
|
{
|
||||||
|
if(screen_flush_context(fgDisplay.pDisplay.screenContext, 0)) {
|
||||||
|
fgWarning("Could not flush screen context");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fgPlatformRotateWindow(SFG_Window* window, int rotation)
|
||||||
|
{
|
||||||
|
if(screen_set_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_ROTATION, &rotation)) {
|
||||||
|
fgWarning("Could not set window rotation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request a window resize
|
||||||
|
*/
|
||||||
|
void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformReshapeWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Closes a window, destroying the frame and OpenGL context
|
||||||
|
*/
|
||||||
|
void fgPlatformCloseWindow( SFG_Window* window )
|
||||||
|
{
|
||||||
|
fghPlatformCloseWindowEGL(window);
|
||||||
|
|
||||||
|
screen_destroy_window((screen_window_t)window->Window.Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function makes the specified window visible
|
||||||
|
*/
|
||||||
|
void fgPlatformShowWindow( void )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformShowWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function hides the specified window
|
||||||
|
*/
|
||||||
|
void fgPlatformHideWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformHideWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iconify the specified window (top-level windows only)
|
||||||
|
*/
|
||||||
|
void fgPlatformIconifyWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
#ifndef __PLAYBOOK__
|
||||||
|
pps_encoder_t encoder;
|
||||||
|
|
||||||
|
pps_encoder_initialize(&encoder, false);
|
||||||
|
pps_encoder_add_string(&encoder, "msg", "minimizeWindow");
|
||||||
|
|
||||||
|
if (navigator_raw_write(pps_encoder_buffer(&encoder), pps_encoder_length(&encoder)) != BPS_SUCCESS) {
|
||||||
|
fgWarning("Could not iconify window on BlackBerry");
|
||||||
|
}
|
||||||
|
|
||||||
|
pps_encoder_cleanup(&encoder);
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "fgPlatformGlutIconifyWindow: STUB\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the current window's title
|
||||||
|
*/
|
||||||
|
void fgPlatformGlutSetWindowTitle( const char* title )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformGlutSetWindowTitle: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the current window's iconified title
|
||||||
|
*/
|
||||||
|
void fgPlatformGlutSetIconTitle( const char* title )
|
||||||
|
{
|
||||||
|
//XXX Possibly a window cover label?
|
||||||
|
fprintf(stderr, "fgPlatformGlutSetIconTitle: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change the specified window's position
|
||||||
|
*/
|
||||||
|
void fgPlatformPositionWindow( SFG_Window *window, int x, int y )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformPositionWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lowers the specified window (by Z order change)
|
||||||
|
*/
|
||||||
|
void fgPlatformPushWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformPushWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Raises the specified window (by Z order change)
|
||||||
|
*/
|
||||||
|
void fgPlatformPopWindow( SFG_Window *window )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformPopWindow: STUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle the window's full screen state.
|
||||||
|
*/
|
||||||
|
void fgPlatformFullScreenToggle( SFG_Window *win )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fgPlatformFullScreenToggle: STUB\n");
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* fg_display_android.c
|
||||||
|
*
|
||||||
|
* Display message posting, context buffer swapping.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "fg_internal.h"
|
||||||
|
|
||||||
|
void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow )
|
||||||
|
{
|
||||||
|
if (!eglSwapBuffers(pDisplayPtr->egl.Display, CurrentWindow->Window.pContext.egl.Surface))
|
||||||
|
fgError("eglSwapBuffers: error %x\n", eglGetError());
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* fg_ext_egl.c
|
||||||
|
*
|
||||||
|
* Functions related to OpenGL extensions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Sylvain Beucler
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include "../fg_internal.h"
|
||||||
|
|
||||||
|
SFG_Proc fgPlatformGetProcAddress( const char *procName )
|
||||||
|
{
|
||||||
|
return (SFG_Proc)eglGetProcAddress(procName);
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue