mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
Library: five more screensaver backgrounds, from ARMSX3
ARMSX2 had Flurry alone. This brings over the Really Slick Screensavers tree
ARMSX3 already runs -- Flux, Plasma, SolarWinds, Hyperspace, Lattice and
Skyrocket -- as one libsavers.so beside libflurry.so.
Terry Welsh's savers, GPL-2.0-OR-LATER, which this tree may take under the "or
later" clause. Nothing here comes from rss-glx: that Linux port is GPL-2.0-only
and cannot go into ARMSX2 at all, which is why Lattice and Skyrocket were
hand-ported from the Windows sources upstream rather than taken from the neutral
versions rss-glx already has. The per-file header is what decides this, not the
repository's LICENSE file; they disagree.
The saver sources build with RS_XSCREENSAVER, selecting their platform-neutral
path, against the GLES2 shim in savers/compat and savers/gl1.c rather than being
rewritten -- so they stay re-pullable and recognisably his code.
Four things the tree carries that are not obvious from the sources:
- The GL thread takes a 16MB stack. Skyrocket's World constructor declares a
1024x1024x3 starmap as a local, and a default stack is a SIGSEGV inside
memset before the first frame draws.
- Each saver is compiled through a *_unit.cpp that wraps it in a namespace.
They all declare draw/idleProc/cleanUp/readyToDraw, because each was built as
its own executable, and two in one .so collide at link. The shared libraries
must be pre-included OUTSIDE the namespace or the declarations never match
their definitions -- which compiles clean and fails at link.
- The lifecycle is serialised by a mutex and a generation token: gl1 keeps its
state in one global, so a view may only free the run it started. Without it
the first selection works and every later one is black.
- gl1_frame_begin() masks alpha off after the first frames. These savers fade
the previous frame rather than clearing, and that fade writes destination
alpha, dragging a composited surface transparent -- which reaches the screen
as full-screen TV static.
Hyperspace runs with dShaders = 0 (its ARB shader path needs objects GLES2 does
not have; upstream exposes this as -shaders 0 and falls back to it itself), and
Skyrocket with dSound = 0 (upstream drives OpenAL and bakes ~7MB of samples into
headers; soundEngine.h is a stub here). Hyperspace and Skyrocket ship no presets
upstream, so neither shows a preset picker -- invented ranges are what made
earlier ports fail to start.
SaverGlView replaces FlurryGlView, which it supersedes: it hosts Flurry and the
Really Slick savers behind one SaverSpec, and keeping both would have declared
FlurryNative twice in one package. Helios is deliberately absent -- it rendered
but animated wrongly and the cause was never found.
This commit is contained in:
@@ -102,6 +102,103 @@ target_compile_options(flurry PRIVATE -O2 -ffast-math -Wall -Wno-unused-paramete
|
||||
target_link_libraries(flurry log GLESv2 m)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Really Slick Screensavers -> libsavers.so
|
||||
#
|
||||
# Terry Welsh's savers (GPL-2.0-or-later), compiled against a GLES2 shim rather than rewritten.
|
||||
# The saver sources are BYTE-IDENTICAL to upstream: they are built with RS_XSCREENSAVER, which
|
||||
# selects their platform-neutral path, and everything that path expects is answered by
|
||||
# compat/. That keeps them re-pullable and keeps them recognisably his code.
|
||||
#
|
||||
# Separate from the flurry target because these are C++ and Flurry is C99, and because Flurry's
|
||||
# shim is a different, smaller one. If a saver ever needs Flurry's, the two can merge.
|
||||
|
||||
add_library(savers SHARED
|
||||
savers/savers_jni.cpp
|
||||
savers/savers_platform.cpp
|
||||
savers/gl1.c
|
||||
|
||||
# Each saver is compiled through a *_unit.cpp that wraps it in a namespace: they all
|
||||
# declare the same globals (draw, idleProc, cleanUp, readyToDraw) because each was built
|
||||
# as its own executable, and two in one .so collide at link time.
|
||||
savers/flux/flux_unit.cpp
|
||||
savers/flux/flux_port.cpp
|
||||
savers/plasma/plasma_unit.cpp
|
||||
savers/plasma/plasma_port.cpp
|
||||
savers/solarwinds/solarwinds_unit.cpp
|
||||
savers/solarwinds/solarwinds_port.cpp
|
||||
|
||||
# Hyperspace. extensions.cpp is deliberately NOT built: it is the WIN32/GLX loader for the
|
||||
# ARB shader path, and the port takes the non-shader path instead. The entry points it
|
||||
# would have resolved are declared in compat/arb_shaders.h and defined in savers_platform.
|
||||
savers/hyperspace/unit_causticTextures.cpp
|
||||
savers/hyperspace/unit_flare.cpp
|
||||
savers/hyperspace/unit_goo.cpp
|
||||
savers/hyperspace/unit_hyperspace.cpp
|
||||
savers/hyperspace/unit_splinePath.cpp
|
||||
savers/hyperspace/unit_starBurst.cpp
|
||||
savers/hyperspace/unit_stretchedParticle.cpp
|
||||
savers/hyperspace/unit_tunnel.cpp
|
||||
savers/hyperspace/unit_wavyNormalCubeMaps.cpp
|
||||
savers/hyperspace/hyperspace_port.cpp
|
||||
|
||||
savers/lattice/lattice_unit.cpp
|
||||
savers/lattice/lattice_port.cpp
|
||||
|
||||
# Skyrocket. soundEngine.cpp is NOT built and its ~7MB of samples are not shipped: upstream
|
||||
# drives OpenAL, the port runs with dSound = 0, and soundEngine.h is a stub.
|
||||
savers/skyrocket/unit_flare.cpp
|
||||
savers/skyrocket/unit_particle.cpp
|
||||
savers/skyrocket/unit_shockwave.cpp
|
||||
savers/skyrocket/unit_skyrocket.cpp
|
||||
savers/skyrocket/unit_smoke.cpp
|
||||
savers/skyrocket/unit_world.cpp
|
||||
savers/skyrocket/skyrocket_port.cpp
|
||||
|
||||
savers/rslibs/rsMath/rsVec.cpp
|
||||
savers/rslibs/rsMath/rsVec4.cpp
|
||||
savers/rslibs/rsMath/rsMatrix.cpp
|
||||
savers/rslibs/rsMath/rsQuat.cpp
|
||||
savers/rslibs/Rgbhsl/Rgbhsl.cpp
|
||||
|
||||
# Implicit surfaces: Hyperspace's "goo" is a marching-cubes isosurface.
|
||||
savers/rslibs/Implicit/impSurface.cpp
|
||||
savers/rslibs/Implicit/impCubeVolume.cpp
|
||||
savers/rslibs/Implicit/impCubeTables.cpp
|
||||
savers/rslibs/Implicit/impShape.cpp
|
||||
savers/rslibs/Implicit/impSphere.cpp
|
||||
savers/rslibs/Implicit/impCapsule.cpp
|
||||
savers/rslibs/Implicit/impEllipsoid.cpp
|
||||
savers/rslibs/Implicit/impHexahedron.cpp
|
||||
savers/rslibs/Implicit/impRoundedHexahedron.cpp
|
||||
savers/rslibs/Implicit/impKnot.cpp
|
||||
savers/rslibs/Implicit/impTorus.cpp
|
||||
|
||||
)
|
||||
|
||||
target_include_directories(savers PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers/compat
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers/rslibs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers/flux
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers/plasma
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers/solarwinds
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers/hyperspace
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers/lattice
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/savers/skyrocket
|
||||
)
|
||||
|
||||
# RS_XSCREENSAVER picks the savers' platform-neutral path. Without it they compile their Win32
|
||||
# shell and nothing links.
|
||||
target_compile_definitions(savers PRIVATE RS_XSCREENSAVER)
|
||||
set_target_properties(savers PROPERTIES C_STANDARD 99 CXX_STANDARD 17)
|
||||
|
||||
# -ffast-math for the same reason as Flurry: particle simulation judged entirely by eye.
|
||||
target_compile_options(savers PRIVATE -O2 -ffast-math -Wall -Wno-unused-parameter)
|
||||
target_link_libraries(savers log GLESv2 m)
|
||||
|
||||
|
||||
|
||||
add_subdirectory(3rdparty/adrenotools)
|
||||
|
||||
# librashader: RetroArch (.slangp) shader chains for the GS post-process path, for BOTH
|
||||
@@ -213,6 +310,7 @@ target_link_libraries(${ARMSX2_EMUCORE_LIBRARY_NAME} PRIVATE
|
||||
# this build would make it. A missing .so stays invisible until someone switches the background
|
||||
# on and the view throws UnsatisfiedLinkError.
|
||||
add_dependencies(${ARMSX2_EMUCORE_LIBRARY_NAME} flurry)
|
||||
add_dependencies(${ARMSX2_EMUCORE_LIBRARY_NAME} savers)
|
||||
|
||||
target_include_directories(${ARMSX2_EMUCORE_LIBRARY_NAME} PRIVATE
|
||||
"${ARMSX2_ROOT}"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Redirects the savers' <GL/gl.h> to the GLES2 shim. See ../../gl1.h. */
|
||||
#ifndef SAVERS_COMPAT_GL_H
|
||||
#define SAVERS_COMPAT_GL_H
|
||||
#include "gl1.h"
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
/* The Implicit library includes <GL/glext.h> for the multitexture entry points. GLES2 has
|
||||
* those in its core header, which gl1.h already pulls in. */
|
||||
#ifndef SAVERS_COMPAT_GLEXT_H
|
||||
#define SAVERS_COMPAT_GLEXT_H
|
||||
#include "gl1.h"
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
/* Redirects the savers' <GL/glu.h> to the GLES2 shim, which answers gluPerspective,
|
||||
* gluLookAt and the quadric spheres. See ../../gl1.h. */
|
||||
#ifndef SAVERS_COMPAT_GLU_H
|
||||
#define SAVERS_COMPAT_GLU_H
|
||||
#include "gl1.h"
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* The ARB_shader_objects surface Hyperspace expects.
|
||||
*
|
||||
* Hyperspace has two rendering paths and picks between them with dShaders. The shader path uses
|
||||
* ARB assembly-era shader objects, which GLES2 does not have at all. Rather than translate them,
|
||||
* the types are declared so the code compiles and the entry points are looked up at runtime --
|
||||
* on GLES2 they come back null, extensions.cpp reports the extension missing, and the saver
|
||||
* takes its own non-shader path, which is a supported upstream configuration rather than
|
||||
* something invented here.
|
||||
*/
|
||||
#ifndef SAVERS_COMPAT_ARB_SHADERS_H
|
||||
#define SAVERS_COMPAT_ARB_SHADERS_H
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include "gl1.h"
|
||||
|
||||
typedef unsigned int GLhandleARB;
|
||||
typedef char GLcharARB;
|
||||
|
||||
typedef void (*PFNGLACTIVETEXTUREARBPROC)(GLenum);
|
||||
typedef void (*PFNGLMULTITEXCOORD2FARBPROC)(GLenum, GLfloat, GLfloat);
|
||||
typedef GLhandleARB (*PFNGLCREATEPROGRAMOBJECTARBPROC)(void);
|
||||
typedef GLhandleARB (*PFNGLCREATESHADEROBJECTARBPROC)(GLenum);
|
||||
typedef void (*PFNGLSHADERSOURCEARBPROC)(GLhandleARB, GLsizei, const GLcharARB **, const GLint *);
|
||||
typedef void (*PFNGLCOMPILESHADERARBPROC)(GLhandleARB);
|
||||
typedef void (*PFNGLATTACHOBJECTARBPROC)(GLhandleARB, GLhandleARB);
|
||||
typedef void (*PFNGLLINKPROGRAMARBPROC)(GLhandleARB);
|
||||
typedef void (*PFNGLUSEPROGRAMOBJECTARBPROC)(GLhandleARB);
|
||||
typedef GLint (*PFNGLGETUNIFORMLOCATIONARBPROC)(GLhandleARB, const GLcharARB *);
|
||||
typedef void (*PFNGLUNIFORM1IARBPROC)(GLint, GLint);
|
||||
typedef void (*PFNGLUNIFORM1FARBPROC)(GLint, GLfloat);
|
||||
typedef void (*PFNGLUNIFORM4FARBPROC)(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
|
||||
typedef void (*PFNGLGETOBJECTPARAMETERIVARBPROC)(GLhandleARB, GLenum, GLint *);
|
||||
typedef void (*PFNGLGETINFOLOGARBPROC)(GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
|
||||
typedef void (*PFNGLDELETEOBJECTARBPROC)(GLhandleARB);
|
||||
|
||||
/* Multitexture unit names; core in GLES2 under the unsuffixed spelling. */
|
||||
#ifndef GL_TEXTURE0_ARB
|
||||
#define GL_TEXTURE0_ARB GL_TEXTURE0
|
||||
#define GL_TEXTURE1_ARB GL_TEXTURE1
|
||||
#define GL_TEXTURE2_ARB GL_TEXTURE2
|
||||
#define GL_TEXTURE3_ARB GL_TEXTURE3
|
||||
#endif
|
||||
|
||||
#ifndef GL_VERTEX_SHADER_ARB
|
||||
#define GL_VERTEX_SHADER_ARB 0x8B31
|
||||
#define GL_FRAGMENT_SHADER_ARB 0x8B30
|
||||
#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
|
||||
#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
|
||||
#endif
|
||||
|
||||
/* Upstream only includes its own extensions.h under WIN32 -- its X11 build relies on the system
|
||||
* GL exporting these symbols directly, which Mesa does and Android does not. So they are
|
||||
* declared here, at global scope, where the savers' namespaced code still finds them.
|
||||
*
|
||||
* Nothing calls them: every use sits behind dShaders, which the port forces off. glActiveTexture
|
||||
* is the one exception, being core in GLES2, so that one points at the real function. */
|
||||
extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
|
||||
extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
|
||||
extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
|
||||
extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
|
||||
extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
|
||||
extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
|
||||
extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
|
||||
extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
|
||||
extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
|
||||
extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
|
||||
|
||||
/* Upstream resolves entry points through the platform's GetProcAddress; on Android that is
|
||||
* EGL's. Anything ARB-only returns null here, which is the point. */
|
||||
#define glXGetProcAddressARB(name) ((void *) eglGetProcAddress((const char *) (name)))
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
/* Case alias: Helios includes <rgbhsl/rgbhsl.h>, Flux includes <Rgbhsl/Rgbhsl.h>. Windows did
|
||||
* not care and neither does macOS, but a case-sensitive build host would fail on one of them.
|
||||
*
|
||||
* The target is spelled as an explicit relative path, NOT as <Rgbhsl/Rgbhsl.h>. On a
|
||||
* case-insensitive filesystem the search path would match "compat/Rgbhsl" to this very
|
||||
* directory and the file would include itself -- the guard then silently swallows it and the
|
||||
* real declarations never arrive. */
|
||||
#ifndef SAVERS_RGBHSL_LOWER_ALIAS_H
|
||||
#define SAVERS_RGBHSL_LOWER_ALIAS_H
|
||||
#include "../../rslibs/Rgbhsl/Rgbhsl.h"
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Stands in for the X11 screensaver shell (upstream rsXScreenSaver, LGPL-2.1).
|
||||
*
|
||||
* The savers carry three platform paths: WIN32, RS_XSCREENSAVER, and nothing. The X11 one is
|
||||
* closest to what a background needs -- it exposes initSaver(), reshape(), draw(), idleProc()
|
||||
* and cleanUp() as plain functions and leaves the whole Win32 dialog shell out -- so we compile
|
||||
* with RS_XSCREENSAVER defined and answer what that path expects here.
|
||||
*
|
||||
* The point of doing it this way is that the saver sources stay BYTE-IDENTICAL to upstream.
|
||||
* Nothing is patched, so they can be re-pulled, and they stay recognisably Terry Welsh's code,
|
||||
* which their GPL headers ask us to keep intact.
|
||||
*
|
||||
* Declarations mirror upstream's types exactly -- note these flags are int, not bool.
|
||||
*/
|
||||
#ifndef SAVERS_COMPAT_RSXSCREENSAVER_H
|
||||
#define SAVERS_COMPAT_RSXSCREENSAVER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rsUtility/rsTimer.h"
|
||||
|
||||
/* The savers poll these before drawing. The host view stops calling us when it is not visible
|
||||
* rather than flagging suspension, so they stay 0. */
|
||||
extern int checkingPassword;
|
||||
extern int isSuspended;
|
||||
extern int doingPreview;
|
||||
|
||||
/* Pixel-format bits the X11 host reported; meaningless here and read only by savers deciding
|
||||
* whether they can rely on buffer preservation. */
|
||||
extern int pfd_swap_exchange;
|
||||
extern int pfd_swap_copy;
|
||||
|
||||
extern unsigned int dFrameRateLimit;
|
||||
|
||||
/* The on-screen frame-rate overlay. Left off -- it is debug furniture for a wallpaper. */
|
||||
extern int kStatistics;
|
||||
|
||||
/* GLX buffer swapping is the host view's job: it owns the EGL surface. */
|
||||
extern void *xdisplay;
|
||||
extern unsigned long xwindow;
|
||||
#define glXSwapBuffers(dpy, win) ((void) 0)
|
||||
|
||||
/* The savers build their frame-rate string with a bare to_string(); upstream picks it up from
|
||||
* this header's include chain. */
|
||||
using std::to_string;
|
||||
|
||||
/* Command-line parsing has no meaning here -- settings arrive through each saver's port API,
|
||||
* which calls setDefaults() and then assigns the globals directly. Accepting and ignoring the
|
||||
* call keeps handleCommandLine() compiling unmodified. */
|
||||
inline int getArgumentsValue(int, char **, std::string, std::string &) { return 0; }
|
||||
template <typename T>
|
||||
inline int getArgumentsValue(int, char **, std::string, T &) { return 0; }
|
||||
template <typename T>
|
||||
inline int getArgumentsValue(int, char **, std::string, T &, T, T) { return 0; }
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Android entry points for Flux.
|
||||
*
|
||||
* flux.cpp is upstream, byte-identical. flux_unit.cpp compiles it inside a namespace, with
|
||||
* RS_XSCREENSAVER defined so it takes its platform-neutral path -- initSaver(), reshape(),
|
||||
* idleProc(), cleanUp() as plain functions, and no Win32 shell. Everything that path expects
|
||||
* from an X11 host is answered by compat/rsXScreenSaver/rsXScreenSaver.h.
|
||||
*/
|
||||
|
||||
#include "gl1.h"
|
||||
|
||||
namespace saver_flux {
|
||||
void setDefaults(int which);
|
||||
void initSaver();
|
||||
void reshape(int width, int height);
|
||||
void idleProc();
|
||||
void cleanUp();
|
||||
extern int readyToDraw;
|
||||
extern int dGeometry;
|
||||
}
|
||||
|
||||
namespace { bool g_started = false; }
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* preset is 1..6, matching the saver's own DEFAULTS1..DEFAULTS6. */
|
||||
int flux_port_new(int preset)
|
||||
{
|
||||
if (g_started) return 1;
|
||||
if (!gl1_init()) return 0;
|
||||
|
||||
if (preset < 1 || preset > 6) preset = 1;
|
||||
saver_flux::setDefaults(preset);
|
||||
|
||||
/* Sphere geometry needs fixed-function lighting, which the shim does not emulate -- the
|
||||
* spheres would draw flat and unlit, which looks worse than the alternative rather than
|
||||
* merely different. Points and the textured "lights" need no lighting, so fall back to the
|
||||
* lights, which is the mode the effect is known for anyway. */
|
||||
if (saver_flux::dGeometry == 1) saver_flux::dGeometry = 2;
|
||||
|
||||
saver_flux::initSaver();
|
||||
g_started = saver_flux::readyToDraw != 0;
|
||||
return g_started ? 1 : 0;
|
||||
}
|
||||
|
||||
void flux_port_resize(int width, int height)
|
||||
{
|
||||
if (width > 0 && height > 0) saver_flux::reshape(width, height);
|
||||
}
|
||||
|
||||
/* idleProc() does the frame timing itself and calls draw(). */
|
||||
void flux_port_draw()
|
||||
{
|
||||
if (!g_started) return;
|
||||
gl1_frame_begin();
|
||||
saver_flux::idleProc();
|
||||
}
|
||||
|
||||
void flux_port_free()
|
||||
{
|
||||
if (!g_started) return;
|
||||
saver_flux::cleanUp();
|
||||
gl1_shutdown();
|
||||
saver_flux::readyToDraw = 0;
|
||||
g_started = false;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Compiles flux.cpp inside a namespace.
|
||||
*
|
||||
* Every Really Slick saver declares the same global names -- draw(), idleProc(), cleanUp(),
|
||||
* setDefaults(), readyToDraw, aspectRatio, dSize, dBlur -- because each was built as its own
|
||||
* executable. Two of them in one .so collide at link time.
|
||||
*
|
||||
* The headers are pulled in FIRST, at global scope, so that the copies inside the namespace hit
|
||||
* their include guards and expand to nothing. flux.cpp itself is then included unchanged, which
|
||||
* is the point: it stays byte-identical to upstream and can be re-pulled without re-patching.
|
||||
*/
|
||||
|
||||
#include <rsXScreenSaver/rsXScreenSaver.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include <rsText/rsText.h>
|
||||
#include <rsMath/rsMath.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <Rgbhsl/Rgbhsl.h>
|
||||
|
||||
namespace saver_flux {
|
||||
#include "flux.cpp"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Enough OpenGL 1.x for the Really Slick Screensavers, implemented on GLES2.
|
||||
*
|
||||
* Terry Welsh's screensavers are late-90s/2000s OpenGL: immediate mode (glBegin/glVertex3f),
|
||||
* the fixed-function matrix stack (glPushMatrix/glTranslatef/gluPerspective) and fixed-function
|
||||
* lighting. GLES2 has none of it. Rather than rewrite each renderer -- and lose the property
|
||||
* that these stay recognisably his code, which the GPL headers on them ask us to preserve --
|
||||
* the calls are redirected here and answered with one shader and a matrix stack.
|
||||
*
|
||||
* This is deliberately a SEPARATE shim from flurry/gl_compat.h. That one is Flurry-shaped:
|
||||
* client-side vertex arrays and a 2D ortho, with glMatrixMode a no-op. Making its matrices real
|
||||
* would risk a renderer that took a long time to get right. Once a couple of savers are running
|
||||
* on this file, Flurry can move over to it and the two can merge.
|
||||
*
|
||||
* NOT emulated yet, because no ported saver has needed it: fixed-function lighting. glLightfv
|
||||
* and friends are accepted and ignored, so anything relying on them draws unlit. Flux calls
|
||||
* them -- check what it actually looks like before deciding whether to implement per-vertex
|
||||
* lighting here or bake it into that saver.
|
||||
*/
|
||||
#ifndef SAVERS_GL1_H
|
||||
#define SAVERS_GL1_H
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* GL 1.x names GLES2 does not define. */
|
||||
#ifndef GL_QUADS
|
||||
#define GL_QUADS 0x0007
|
||||
#endif
|
||||
#ifndef GL_QUAD_STRIP
|
||||
#define GL_QUAD_STRIP 0x0008
|
||||
#endif
|
||||
#ifndef GL_POLYGON
|
||||
#define GL_POLYGON 0x0009
|
||||
#endif
|
||||
#ifndef GL_MODELVIEW
|
||||
#define GL_MODELVIEW 0x1700
|
||||
#endif
|
||||
#ifndef GL_PROJECTION
|
||||
#define GL_PROJECTION 0x1701
|
||||
#endif
|
||||
#ifndef GL_ALPHA_TEST
|
||||
#define GL_ALPHA_TEST 0x0BC0
|
||||
#endif
|
||||
#ifndef GL_LIGHTING
|
||||
#define GL_LIGHTING 0x0B50
|
||||
#endif
|
||||
#ifndef GL_LIGHT0
|
||||
#define GL_LIGHT0 0x4000
|
||||
#endif
|
||||
#ifndef GL_NORMALIZE
|
||||
#define GL_NORMALIZE 0x0BA1
|
||||
#endif
|
||||
#ifndef GL_COLOR_MATERIAL
|
||||
#define GL_COLOR_MATERIAL 0x0B57
|
||||
#endif
|
||||
#ifndef GL_POINT_SMOOTH
|
||||
#define GL_POINT_SMOOTH 0x0B10
|
||||
#endif
|
||||
#ifndef GL_LINE_SMOOTH
|
||||
#define GL_LINE_SMOOTH 0x0B20
|
||||
#endif
|
||||
#ifndef GL_COMPILE
|
||||
#define GL_COMPILE 0x1300
|
||||
#endif
|
||||
#ifndef GL_COMPILE_AND_EXECUTE
|
||||
#define GL_COMPILE_AND_EXECUTE 0x1301
|
||||
#endif
|
||||
#ifndef GL_TEXTURE_GEN_S
|
||||
#define GL_TEXTURE_GEN_S 0x0C60
|
||||
#endif
|
||||
#ifndef GL_TEXTURE_GEN_T
|
||||
#define GL_TEXTURE_GEN_T 0x0C61
|
||||
#endif
|
||||
/* Cube maps are core in GLES2; only the ARB spelling is missing. */
|
||||
#ifndef GL_TEXTURE_CUBE_MAP_ARB
|
||||
#define GL_TEXTURE_CUBE_MAP_ARB GL_TEXTURE_CUBE_MAP
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB GL_TEXTURE_CUBE_MAP_POSITIVE_X
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB GL_TEXTURE_CUBE_MAP_NEGATIVE_X
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB GL_TEXTURE_CUBE_MAP_POSITIVE_Y
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB GL_TEXTURE_CUBE_MAP_POSITIVE_Z
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
|
||||
#define GL_REFLECTION_MAP_ARB 0x8512
|
||||
#define GL_NORMAL_MAP_ARB 0x8511
|
||||
#endif
|
||||
#ifndef GL_FOG
|
||||
#define GL_FOG 0x0B60
|
||||
#endif
|
||||
#ifndef GL_MODELVIEW_MATRIX
|
||||
#define GL_MODELVIEW_MATRIX 0x0BA6
|
||||
#define GL_PROJECTION_MATRIX 0x0BA7
|
||||
#endif
|
||||
#ifndef GL_UNPACK_ROW_LENGTH
|
||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||
#endif
|
||||
/* GLES2 has only CLAMP_TO_EDGE. The savers use GL_CLAMP on textures they never sample outside
|
||||
* [0,1], so the border-vs-edge difference is not reachable. */
|
||||
#ifndef GL_CLAMP
|
||||
#define GL_CLAMP GL_CLAMP_TO_EDGE
|
||||
#endif
|
||||
#ifndef GL_DECAL
|
||||
#define GL_DECAL 0x2101
|
||||
#endif
|
||||
#ifndef GL_VERTEX_ARRAY
|
||||
#define GL_VERTEX_ARRAY 0x8074
|
||||
#endif
|
||||
#ifndef GL_NORMAL_ARRAY
|
||||
#define GL_NORMAL_ARRAY 0x8075
|
||||
#endif
|
||||
#ifndef GL_COLOR_ARRAY
|
||||
#define GL_COLOR_ARRAY 0x8076
|
||||
#endif
|
||||
#ifndef GL_TEXTURE_COORD_ARRAY
|
||||
#define GL_TEXTURE_COORD_ARRAY 0x8078
|
||||
#endif
|
||||
#ifndef GL_N3F_V3F
|
||||
#define GL_N3F_V3F 0x2A25
|
||||
#endif
|
||||
#ifndef GL_S
|
||||
#define GL_S 0x2000
|
||||
#endif
|
||||
#ifndef GL_T
|
||||
#define GL_T 0x2001
|
||||
#endif
|
||||
#ifndef GL_TEXTURE_GEN_MODE
|
||||
#define GL_TEXTURE_GEN_MODE 0x2500
|
||||
#endif
|
||||
#ifndef GL_SPHERE_MAP
|
||||
#define GL_SPHERE_MAP 0x2402
|
||||
#endif
|
||||
#ifndef GL_TEXTURE_2D_ENABLE_COMPAT
|
||||
#define GL_TEXTURE_2D_ENABLE_COMPAT 0x0DE1
|
||||
#endif
|
||||
|
||||
/* Lifetime. gl1_init needs a current context; gl1_lost forgets GL names without touching
|
||||
* them, for when the context has already gone away underneath us. */
|
||||
int gl1_init(void);
|
||||
void gl1_shutdown(void);
|
||||
void gl1_lost(void);
|
||||
|
||||
/* Matrix stack. */
|
||||
void gl1_matrix_mode(GLenum mode);
|
||||
void gl1_load_identity(void);
|
||||
void gl1_push_matrix(void);
|
||||
void gl1_pop_matrix(void);
|
||||
void gl1_load_matrixf(const float *m);
|
||||
void gl1_mult_matrixf(const float *m);
|
||||
void gl1_translatef(float x, float y, float z);
|
||||
void gl1_scalef(float x, float y, float z);
|
||||
void gl1_rotatef(float angle, float x, float y, float z);
|
||||
void gl1_ortho(double l, double r, double b, double t, double n, double f);
|
||||
void gl1_frustum(double l, double r, double b, double t, double n, double f);
|
||||
void gl1_perspective(double fovy, double aspect, double zn, double zf);
|
||||
void gl1_look_at(double ex, double ey, double ez, double cx, double cy, double cz,
|
||||
double ux, double uy, double uz);
|
||||
|
||||
/* Immediate mode. */
|
||||
void gl1_begin(GLenum mode);
|
||||
void gl1_end(void);
|
||||
void gl1_vertex2f(float x, float y);
|
||||
void gl1_vertex3f(float x, float y, float z);
|
||||
void gl1_vertex3fv(const float *v);
|
||||
void gl1_texcoord2f(float s, float t);
|
||||
void gl1_color3f(float r, float g, float b);
|
||||
void gl1_color4f(float r, float g, float b, float a);
|
||||
void gl1_color3fv(const float *c);
|
||||
void gl1_color4fv(const float *c);
|
||||
void gl1_normal3f(float x, float y, float z);
|
||||
void gl1_normal3fv(const float *n);
|
||||
void gl1_texcoord2fv(const float *t);
|
||||
|
||||
/* The savers read the matrices back to hand them to gluProject. GLES2 has no matrix state at
|
||||
* all, so these answer from the shim's own stack. GLdouble is likewise absent. */
|
||||
typedef double gl1_double;
|
||||
void gl1_get_floatv(GLenum pname, float *params);
|
||||
void gl1_get_doublev(GLenum pname, gl1_double *params);
|
||||
|
||||
/* Object space to window space, for savers that place 2D overlays over 3D positions. */
|
||||
int gl1_project(double ox, double oy, double oz, double *winx, double *winy, double *winz);
|
||||
|
||||
/* Display lists.
|
||||
*
|
||||
* The savers build a shape once (a sphere, or a textured quad) and replay it per particle with
|
||||
* a different matrix each time -- so this is not an optimisation to skip, it IS how they draw.
|
||||
* Recording captures the immediate-mode batches; replaying re-draws them under whatever the
|
||||
* matrices currently are. */
|
||||
GLuint gl1_gen_lists(GLsizei range);
|
||||
void gl1_new_list(GLuint list, GLenum mode);
|
||||
void gl1_end_list(void);
|
||||
void gl1_call_list(GLuint list);
|
||||
void gl1_delete_lists(GLuint list, GLsizei range);
|
||||
|
||||
/* GLU quadrics. Only spheres are used, and only as list content, so the quadric object is a
|
||||
* token and the sphere is emitted through the immediate-mode path above. */
|
||||
typedef struct gl1_quadric gl1_quadric;
|
||||
gl1_quadric *gl1_new_quadric(void);
|
||||
void gl1_delete_quadric(gl1_quadric *q);
|
||||
void gl1_sphere(gl1_quadric *q, double radius, int slices, int stacks);
|
||||
|
||||
/* Vertex arrays.
|
||||
*
|
||||
* The Implicit surface library draws through these, with real VBOs -- so unlike the immediate
|
||||
* mode above, the data is already in a form GLES2 accepts and only the fixed-function
|
||||
* plumbing (which attribute each pointer feeds, and the enable flags) has to be emulated. */
|
||||
void gl1_vertex_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr);
|
||||
void gl1_normal_pointer(GLenum type, GLsizei stride, const void *ptr);
|
||||
void gl1_color_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr);
|
||||
void gl1_texcoord_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr);
|
||||
void gl1_enable_client_state(GLenum cap);
|
||||
void gl1_disable_client_state(GLenum cap);
|
||||
void gl1_interleaved_arrays(GLenum format, GLsizei stride, const void *ptr);
|
||||
void gl1_draw_arrays(GLenum mode, GLint first, GLsizei count);
|
||||
void gl1_draw_elements(GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
void gl1_multi_draw_elements(GLenum mode, const GLsizei *count, GLenum type,
|
||||
const void *const *indices, GLsizei primcount);
|
||||
|
||||
/* State GLES2 rejects outright; an invalid enum would leave a sticky error for everything
|
||||
* after it, so these are filtered rather than passed through. */
|
||||
void gl1_enable(GLenum cap);
|
||||
void gl1_disable(GLenum cap);
|
||||
void gl1_point_size(float size);
|
||||
|
||||
/* Draw counters since the last call, for working out whether a black saver is drawing nothing
|
||||
* or drawing something invisible. Resets on read. */
|
||||
void gl1_stats_take(int *batches, long *vertices, unsigned *last_error);
|
||||
|
||||
/* Call at the top of every frame, before the saver draws.
|
||||
*
|
||||
* Handles the two things that make an accumulating saver show TV static on a composited
|
||||
* surface, both learned the hard way from Flurry:
|
||||
* - the buffer starts UNDEFINED, so the first few frames are cleared outright; a saver that
|
||||
* fades instead of clearing never establishes a known background on its own
|
||||
* - the fade writes destination ALPHA as well as colour, dragging the surface toward
|
||||
* transparent so the window compositor blends whatever is behind it. Alpha is set to 1 once
|
||||
* and then masked off, which leaves RGB and the trails untouched. */
|
||||
void gl1_frame_begin(void);
|
||||
|
||||
/* GL 1.x let internalformat be a component COUNT (1..4). GLES2 requires the actual enum and
|
||||
* rejects the number with GL_INVALID_ENUM -- which leaves a black texture and a sticky error
|
||||
* blamed on whatever runs next. Flux passes 1. */
|
||||
/* GLU built the mip chain on the CPU; GLES2 has glGenerateMipmap. Same component-count
|
||||
* translation as above applies to the internalformat argument. */
|
||||
void gl1_build_2d_mipmaps(GLenum target, GLint components, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type, const void *data);
|
||||
|
||||
/* GLES2 accepts neither GL_FLOAT pixel data nor GL_UNPACK_ROW_LENGTH. Plasma uses both: it
|
||||
* keeps a float RGB map and uploads a sub-rectangle of it. These repack into tight bytes. */
|
||||
void gl1_pixel_store_i(GLenum pname, GLint param);
|
||||
void gl1_tex_sub_image_2d(GLenum target, GLint level, GLint xoff, GLint yoff, GLsizei width,
|
||||
GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
|
||||
void gl1_tex_image_2d(GLenum target, GLint level, GLint internalformat, GLsizei width,
|
||||
GLsizei height, GLint border, GLenum format, GLenum type,
|
||||
const void *pixels);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The redirection. Included by each saver's sources ahead of any GL use.
|
||||
*
|
||||
* gl1.c MUST #undef every name below before defining the functions, or each implementation
|
||||
* calls itself -- and at -O2 that becomes a silent infinite loop rather than a crash. */
|
||||
#define glMatrixMode gl1_matrix_mode
|
||||
#define glLoadIdentity gl1_load_identity
|
||||
#define glPushMatrix gl1_push_matrix
|
||||
#define glPopMatrix gl1_pop_matrix
|
||||
#define glLoadMatrixf gl1_load_matrixf
|
||||
#define glMultMatrixf gl1_mult_matrixf
|
||||
#define glTranslatef gl1_translatef
|
||||
#define glScalef gl1_scalef
|
||||
#define glRotatef gl1_rotatef
|
||||
#define glOrtho gl1_ortho
|
||||
#define glFrustum gl1_frustum
|
||||
#define gluPerspective gl1_perspective
|
||||
#define gluLookAt gl1_look_at
|
||||
#define glBegin gl1_begin
|
||||
#define glEnd gl1_end
|
||||
#define glVertex2f gl1_vertex2f
|
||||
#define glVertex3f gl1_vertex3f
|
||||
#define glVertex3fv gl1_vertex3fv
|
||||
#define glTexCoord2f gl1_texcoord2f
|
||||
#define glColor3f gl1_color3f
|
||||
#define glColor4f gl1_color4f
|
||||
#define glColor3fv gl1_color3fv
|
||||
#define glColor4fv gl1_color4fv
|
||||
#define glNormal3f gl1_normal3f
|
||||
#define glNormal3fv gl1_normal3fv
|
||||
#define glTexCoord2fv gl1_texcoord2fv
|
||||
#define glEnable gl1_enable
|
||||
#define glDisable gl1_disable
|
||||
#define glPointSize gl1_point_size
|
||||
#define glGenLists gl1_gen_lists
|
||||
#define glNewList gl1_new_list
|
||||
#define glEndList gl1_end_list
|
||||
#define glCallList gl1_call_list
|
||||
#define glDeleteLists gl1_delete_lists
|
||||
#define GLUquadricObj gl1_quadric
|
||||
#define gluNewQuadric gl1_new_quadric
|
||||
#define gluDeleteQuadric gl1_delete_quadric
|
||||
#define gluSphere gl1_sphere
|
||||
#define glTexImage2D gl1_tex_image_2d
|
||||
#define gluBuild2DMipmaps gl1_build_2d_mipmaps
|
||||
#define glTexSubImage2D gl1_tex_sub_image_2d
|
||||
#define glPixelStorei gl1_pixel_store_i
|
||||
#define gluOrtho2D(l, r, b, t) gl1_ortho((l), (r), (b), (t), -1.0, 1.0)
|
||||
/* The savers pass the matrices and viewport they just queried; this shim keeps its own copies,
|
||||
* so those arguments are ignored and the live state is used instead. */
|
||||
#define gluProject(ox, oy, oz, mv, pj, vp, wx, wy, wz) \
|
||||
gl1_project((ox), (oy), (oz), (wx), (wy), (wz))
|
||||
|
||||
/* No analogue, and nothing ported so far depends on the effect. */
|
||||
#define glShadeModel(m) ((void) 0)
|
||||
#define glAlphaFunc(f, r) ((void) 0)
|
||||
#define glTexEnvf(t, p, v) ((void) 0)
|
||||
#define glTexEnvi(t, p, v) ((void) 0)
|
||||
#define glLightfv(l, p, v) ((void) 0)
|
||||
#define glLightf(l, p, v) ((void) 0)
|
||||
#define glMaterialfv(f, p, v) ((void) 0)
|
||||
#define glMaterialf(f, p, v) ((void) 0)
|
||||
#define glColorMaterial(f, m) ((void) 0)
|
||||
#define glFogfv(p, v) ((void) 0)
|
||||
#define glFogf(p, v) ((void) 0)
|
||||
#define glFogi(p, v) ((void) 0)
|
||||
#define glHint(t, m) ((void) 0)
|
||||
#define glDrawBuffer(m) ((void) 0)
|
||||
#define glReadBuffer(m) ((void) 0)
|
||||
#define glGetFloatv gl1_get_floatv
|
||||
#define glGetDoublev gl1_get_doublev
|
||||
#define GLdouble gl1_double
|
||||
#define glFinish() ((void) 0)
|
||||
#define glPolygonMode(f, m) ((void) 0)
|
||||
/* The generation MODE is not stored: GL_SPHERE_MAP is the only one the savers ask for, and
|
||||
* gl1_vertex3f implements exactly that. A saver wanting GL_OBJECT_LINEAR or GL_EYE_LINEAR
|
||||
* would silently get sphere mapping instead, so check this if one ever looks wrong. */
|
||||
#define glVertexPointer gl1_vertex_pointer
|
||||
#define glNormalPointer gl1_normal_pointer
|
||||
#define glColorPointer gl1_color_pointer
|
||||
#define glTexCoordPointer gl1_texcoord_pointer
|
||||
#define glEnableClientState gl1_enable_client_state
|
||||
#define glDisableClientState gl1_disable_client_state
|
||||
#define glInterleavedArrays gl1_interleaved_arrays
|
||||
#define glDrawArrays gl1_draw_arrays
|
||||
#define glDrawElements gl1_draw_elements
|
||||
#define glMultiDrawElements gl1_multi_draw_elements
|
||||
#define glTexGeni(coord, pname, param) ((void) 0)
|
||||
#define glTexGenfv(coord, pname, param) ((void) 0)
|
||||
#define glLightModeli(p, v) ((void) 0)
|
||||
#define glLightModelfv(p, v) ((void) 0)
|
||||
|
||||
#endif /* SAVERS_GL1_H */
|
||||
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Terence M. Welsh
|
||||
*
|
||||
* This file is part of Hyperspace.
|
||||
*
|
||||
* Hyperspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Hyperspace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
extern HDC hdc;
|
||||
#endif
|
||||
#ifdef RS_XSCREENSAVER
|
||||
#include <rsXScreenSaver/rsXScreenSaver.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <rsMath/rsMath.h>
|
||||
|
||||
#include "causticTextures.h"
|
||||
|
||||
causticTextures::causticTextures(int keys, int frames, int res, int size, float depth, float wa, float rm){
|
||||
int i, j, k;
|
||||
int xminus, xplus, zminus, zplus;
|
||||
int viewport[4];
|
||||
unsigned char* bitmap = new unsigned char[size * size * 3];
|
||||
|
||||
// initialize dimensions
|
||||
numKeys = keys;
|
||||
if(numKeys < 2)
|
||||
numKeys = 2;
|
||||
numFrames = frames;
|
||||
if(numFrames < numKeys * 2)
|
||||
numFrames = numKeys * 2;
|
||||
geoRes = res;
|
||||
if(geoRes < 8)
|
||||
geoRes = 8;
|
||||
texSize = size;
|
||||
if(texSize < 8)
|
||||
texSize = 8;
|
||||
waveAmp = wa;
|
||||
refractionMult = rm;
|
||||
|
||||
caustictex = new GLuint[numFrames];
|
||||
glGenTextures(numFrames, caustictex);
|
||||
|
||||
// allocate memory
|
||||
x = new float[geoRes + 1];
|
||||
z = new float[geoRes + 1];
|
||||
y = new float**[numFrames];
|
||||
for(k=0; k<numFrames; k++){
|
||||
y[k] = new float*[geoRes];
|
||||
for(i=0; i<geoRes; i++)
|
||||
y[k][i] = new float[geoRes];
|
||||
}
|
||||
xz = new float**[geoRes + 1];
|
||||
for(i=0; i<=geoRes; i++){
|
||||
xz[i] = new float*[geoRes + 1];
|
||||
for(j=0; j<=geoRes; j++)
|
||||
xz[i][j] = new float[2];
|
||||
}
|
||||
intensity = new float*[geoRes + 1];
|
||||
for(i=0; i<=geoRes; i++)
|
||||
intensity[i] = new float[geoRes + 1];
|
||||
|
||||
// set x and z geometry positions
|
||||
for(i=0; i<=geoRes; i++){
|
||||
x[i] = float(i) / float(geoRes);
|
||||
z[i] = float(i) / float(geoRes);
|
||||
}
|
||||
|
||||
// set y geometry positions (altitudes)
|
||||
// fractal altitudes is sort of ugly, so I don't use it
|
||||
//makeFractalAltitudes();
|
||||
makeTrigAltitudes();
|
||||
|
||||
// prepare to draw textures
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
glViewport(0, 0, texSize, texSize);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -0.5f, 0.5f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glRotatef(-90.0f, 1, 0, 0);
|
||||
glReadBuffer(GL_BACK);
|
||||
//glPixelStorei(GL_UNPACK_ROW_LENGTH, texSize);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
// project vertices and create textures
|
||||
float recvert = float(geoRes) * 0.5f; // reciprocal of vertical component of light ray
|
||||
for(k=0; k<numFrames; k++){
|
||||
// compute projected offsets
|
||||
// (this uses surface normals, not actual refractions, but it's faster this way)
|
||||
for(i=0; i<geoRes; i++){
|
||||
for(j=0; j<geoRes; j++){
|
||||
makeIndices(i, &xminus, &xplus);
|
||||
xz[i][j][0] = (y[k][xplus][j] - y[k][xminus][j]) * recvert * (depth + y[k][i][j]);
|
||||
makeIndices(j, &zminus, &zplus);
|
||||
xz[i][j][1] = (y[k][i][zplus] - y[k][i][zminus]) * recvert * (depth + y[k][i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
// copy offsets to edges of xz array
|
||||
for(i=0; i<geoRes; i++){
|
||||
xz[i][geoRes][0] = xz[i][0][0];
|
||||
xz[i][geoRes][1] = xz[i][0][1];
|
||||
}
|
||||
for(j=0; j<=geoRes; j++){
|
||||
xz[geoRes][j][0] = xz[0][j][0];
|
||||
xz[geoRes][j][1] = xz[0][j][1];
|
||||
}
|
||||
|
||||
// compute light intensities
|
||||
float space = 1.0f / float(geoRes);
|
||||
for(i=0; i<geoRes; i++){
|
||||
for(j=0; j<geoRes; j++){
|
||||
makeIndices(i, &xminus, &xplus);
|
||||
makeIndices(j, &zminus, &zplus);
|
||||
// this assumes nominal light intensity is 0.25
|
||||
intensity[i][j] = (1.0f / (float(geoRes) * float(geoRes)))
|
||||
/ ((myFabs(xz[xplus][j][0] - xz[i][j][0] + space)
|
||||
+ myFabs(xz[i][j][0] - xz[xminus][j][0] + space))
|
||||
* (myFabs(xz[i][zplus][1] - xz[i][j][1] + space)
|
||||
+ myFabs(xz[i][j][1] - xz[i][zminus][1] + space)))
|
||||
- 0.125f;
|
||||
if(intensity[i][j] > 1.0f)
|
||||
intensity[i][j] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// copy intensities to edges of intensity array
|
||||
for(i=0; i<geoRes; i++)
|
||||
intensity[i][geoRes] = intensity[i][0];
|
||||
for(j=0; j<=geoRes; j++)
|
||||
intensity[geoRes][j] = intensity[0][j];
|
||||
|
||||
// draw texture
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// draw most of texture
|
||||
draw(0, geoRes, 0, geoRes);
|
||||
// draw edges of texture that wrap around from opposite sides
|
||||
int numRows = geoRes / 10;
|
||||
glPushMatrix();
|
||||
glTranslatef(-1.0f, 0.0f, 0.0f);
|
||||
draw(geoRes - numRows, geoRes, 0, geoRes);
|
||||
glPopMatrix();
|
||||
glPushMatrix();
|
||||
glTranslatef(1.0f, 0.0f, 0.0f);
|
||||
draw(0, numRows, 0, geoRes);
|
||||
glPopMatrix();
|
||||
glPushMatrix();
|
||||
glTranslatef(0.0f, 0.0f, -1.0f);
|
||||
draw(0, geoRes, geoRes - numRows, geoRes);
|
||||
glPopMatrix();
|
||||
glPushMatrix();
|
||||
glTranslatef(0.0f, 0.0f, 1.0f);
|
||||
draw(0, geoRes, 0, numRows);
|
||||
glPopMatrix();
|
||||
// draw corners too
|
||||
glPushMatrix();
|
||||
glTranslatef(-1.0f, 0.0f, -1.0f);
|
||||
draw(geoRes - numRows, geoRes, geoRes - numRows, geoRes);
|
||||
glPopMatrix();
|
||||
glPushMatrix();
|
||||
glTranslatef(1.0f, 0.0f, -1.0f);
|
||||
draw(0, numRows, geoRes - numRows, geoRes);
|
||||
glPopMatrix();
|
||||
glPushMatrix();
|
||||
glTranslatef(-1.0f, 0.0f, 1.0f);
|
||||
draw(geoRes - numRows, geoRes, 0, numRows);
|
||||
glPopMatrix();
|
||||
glPushMatrix();
|
||||
glTranslatef(1.0f, 0.0f, 1.0f);
|
||||
draw(0, numRows, 0, numRows);
|
||||
glPopMatrix();
|
||||
|
||||
// read back texture
|
||||
glReadPixels(0, 0, texSize, texSize, GL_RGB, GL_UNSIGNED_BYTE, bitmap);
|
||||
|
||||
// create texture object
|
||||
glBindTexture(GL_TEXTURE_2D, caustictex[k]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texSize, texSize, GL_RGB,
|
||||
GL_UNSIGNED_BYTE, bitmap);
|
||||
|
||||
#ifdef WIN32
|
||||
wglSwapLayerBuffers(hdc, WGL_SWAP_MAIN_PLANE);
|
||||
#endif
|
||||
#ifdef RS_XSCREENSAVER
|
||||
glXSwapBuffers(xdisplay, xwindow);
|
||||
#endif
|
||||
}
|
||||
|
||||
// restore matrix stack
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
|
||||
delete[] x;
|
||||
delete[] y;
|
||||
delete[] z;
|
||||
delete[] xz;
|
||||
delete[] intensity;
|
||||
delete[] bitmap;
|
||||
}
|
||||
|
||||
|
||||
void causticTextures::makeFractalAltitudes(){
|
||||
int i, j, k, a;
|
||||
float keySeparation = float(numFrames) / float(numKeys);
|
||||
int* keyFrame = new int[numKeys+1];
|
||||
|
||||
// generate keyframes
|
||||
float phase = 0.0f;
|
||||
for(k=0; k<numKeys; k++){
|
||||
keyFrame[k] = int(float(k) * keySeparation);
|
||||
// set all keyframe altitudes to 0.0
|
||||
for(i=0; i<geoRes; i++){
|
||||
for(j=0; j<geoRes; j++)
|
||||
y[keyFrame[k]][i][j] = 0.0f;
|
||||
}
|
||||
// generate altitudes in first positions
|
||||
phase = float(k) * RS_PIx2 / float(numKeys);
|
||||
y[keyFrame[k]][0][0] = waveAmp * rsCosf(1.5707f + phase);
|
||||
y[keyFrame[k]][geoRes/2][0] = waveAmp * rsCosf(1.5707f + phase);
|
||||
y[keyFrame[k]][geoRes/2][geoRes/2] = waveAmp * rsCosf(3.1416f + phase);
|
||||
y[keyFrame[k]][0][geoRes/2] = waveAmp * rsCosf(4.7124f + phase);
|
||||
// recurse to find remaining altitudes
|
||||
altitudeSquare(0, geoRes/2, 0, geoRes/2, y[keyFrame[k]]);
|
||||
altitudeSquare(geoRes/2, geoRes, 0, geoRes/2, y[keyFrame[k]]);
|
||||
altitudeSquare(0, geoRes/2, geoRes/2, geoRes, y[keyFrame[k]]);
|
||||
altitudeSquare(geoRes/2, geoRes, geoRes/2, geoRes, y[keyFrame[k]]);
|
||||
}
|
||||
|
||||
// interpolate to find remaining frames
|
||||
int diff, kk;
|
||||
int kf0, kf1, kf2, kf3; // keyframe indices
|
||||
float where;
|
||||
keyFrame[numKeys] = numFrames;
|
||||
for(k=0; k<numKeys; k++){
|
||||
kf1 = keyFrame[k];
|
||||
kf2 = keyFrame[k+1];
|
||||
diff = kf2 - kf1;
|
||||
if(kf2 == numFrames)
|
||||
kf2 = 0;
|
||||
kk = k - 1;
|
||||
if(kk < 0)
|
||||
kk = numKeys - 1;
|
||||
kf0 = keyFrame[kk];
|
||||
kk = k + 2;
|
||||
if(kk >= numKeys)
|
||||
kk -= numKeys;
|
||||
kf3 = keyFrame[kk];
|
||||
if(diff > 1){
|
||||
for(a=kf1+1; a<kf1+diff; a++){
|
||||
where = float(a-kf1) / float(diff);
|
||||
for(i=0; i<geoRes; i++)
|
||||
for(j=0; j<geoRes; j++)
|
||||
y[a][i][j] = interpolate(y[kf0][i][j], y[kf1][i][j],
|
||||
y[kf2][i][j], y[kf3][i][j], where);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] keyFrame;
|
||||
}
|
||||
|
||||
|
||||
void causticTextures::altitudeSquare(int left, int right, int bottom, int top, float** alt){
|
||||
// find wrapped indices
|
||||
int rr = right;
|
||||
if(rr == geoRes)
|
||||
rr = 0;
|
||||
int tt = top;
|
||||
if(tt == geoRes)
|
||||
tt = 0;
|
||||
|
||||
// for determining if there is a gap to be filled
|
||||
int hor = right - left;
|
||||
int vert = top - bottom;
|
||||
|
||||
int centerHor = (left + right) / 2;
|
||||
int centerVert = (bottom + top) / 2;
|
||||
float offset;
|
||||
if(hor > 1){ // find bottom and top altitudes
|
||||
offset = myFabs(waveAmp * float(x[right] - x[left]));
|
||||
if(alt[centerHor][bottom] == 0.0f)
|
||||
alt[centerHor][bottom] = (alt[left][bottom] + alt[rr][bottom]) * 0.5f
|
||||
+ rsRandf(offset+offset) - offset;
|
||||
if(alt[centerHor][tt] == 0.0f)
|
||||
alt[centerHor][tt] = (alt[left][tt] + alt[rr][tt]) * 0.5f
|
||||
+ rsRandf(offset+offset) - offset;
|
||||
}
|
||||
if(vert > 1){ // find left and right altitudes
|
||||
offset = myFabs(waveAmp * float(z[top] - z[bottom]));
|
||||
if(alt[left][centerVert] == 0.0f)
|
||||
alt[left][centerVert] = (alt[left][bottom] + alt[left][tt]) * 0.5f
|
||||
+ rsRandf(offset+offset) - offset;
|
||||
if(alt[rr][centerVert] == 0.0f)
|
||||
alt[rr][centerVert] = (alt[rr][bottom] + alt[rr][tt]) * 0.5f
|
||||
+ rsRandf(offset+offset) - offset;
|
||||
}
|
||||
if(hor > 1 && vert > 1){ // find center altitude
|
||||
offset = waveAmp * 0.5f *
|
||||
(myFabs(float(x[right] - x[left]))
|
||||
+ myFabs(float(z[top] - z[bottom])));
|
||||
alt[centerHor][centerVert] = (alt[left][bottom] + alt[rr][bottom] + alt[left][tt]
|
||||
+ alt[rr][tt]) * 0.25f + rsRandf(offset+offset) - offset;
|
||||
}
|
||||
|
||||
// keep recursing if necessary
|
||||
int quadrant[4] = {0, 0, 0, 0};
|
||||
if(centerHor - left > 1){
|
||||
quadrant[0] ++;
|
||||
quadrant[2] ++;
|
||||
}
|
||||
if(right - centerHor > 1){
|
||||
quadrant[1] ++;
|
||||
quadrant[2] ++;
|
||||
}
|
||||
if(centerVert - bottom > 1){
|
||||
quadrant[0] ++;
|
||||
quadrant[1] ++;
|
||||
}
|
||||
if(top - centerVert > 1){
|
||||
quadrant[2] ++;
|
||||
quadrant[3] ++;
|
||||
}
|
||||
if(quadrant[0])
|
||||
altitudeSquare(left, centerHor, bottom, centerVert, alt);
|
||||
if(quadrant[1])
|
||||
altitudeSquare(centerHor, right, bottom, centerVert, alt);
|
||||
if(quadrant[2])
|
||||
altitudeSquare(left, centerHor, centerVert, top, alt);
|
||||
if(quadrant[3])
|
||||
altitudeSquare(centerHor, right, centerVert, top, alt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void causticTextures::makeTrigAltitudes(){
|
||||
int i, j, k;
|
||||
float xx, zz, offset;
|
||||
|
||||
for(k=0; k<numFrames; k++){
|
||||
offset = RS_PIx2 * float(k) / float(numFrames);
|
||||
for(i=0; i<geoRes; i++){
|
||||
xx = RS_PIx2 * float(i) / float(geoRes);
|
||||
for(j=0; j<geoRes; j++){
|
||||
zz = RS_PIx2 * float(j) / float(geoRes);
|
||||
/*y[k][i][j] = waveAmp
|
||||
* (0.12f * rsCosf(xx + 2.0f * offset)
|
||||
+ 0.08f * rsCosf(-1.0f * xx + 2.0f * zz + offset)
|
||||
+ 0.04f * rsCosf(-2.0f * xx - 4.0f * zz + offset)
|
||||
+ 0.014f * rsCosf(xx - 7.0f * zz - 2.0f * offset)
|
||||
+ 0.014f * rsCosf(3.0f * xx + 5.0f * zz + offset)
|
||||
+ 0.014f * rsCosf(9.0f * xx + zz - offset)
|
||||
+ 0.007f * rsCosf(11.0f * xx + 7.0f * zz - offset)
|
||||
+ 0.007f * rsCosf(4.0f * xx - 13.0f * zz + offset)
|
||||
+ 0.007f * rsCosf(19.0f * xx - 9.0f * zz - offset));*/
|
||||
y[k][i][j] = waveAmp
|
||||
* (0.08f * rsCosf(xx * 2.0f + offset)
|
||||
+ 0.06f * rsCosf(-1.0f * xx + 2.0f * zz + offset)
|
||||
+ 0.04f * rsCosf(-2.0f * xx - 3.0f * zz + offset)
|
||||
+ 0.01f * rsCosf(xx - 7.0f * zz - 2.0f * offset)
|
||||
+ 0.01f * rsCosf(3.0f * xx + 5.0f * zz + offset)
|
||||
+ 0.01f * rsCosf(9.0f * xx + zz - offset)
|
||||
+ 0.005f * rsCosf(11.0f * xx + 7.0f * zz - offset)
|
||||
+ 0.005f * rsCosf(4.0f * xx - 13.0f * zz + offset)
|
||||
+ 0.003f * rsCosf(19.0f * xx - 9.0f * zz - offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void causticTextures::draw(int xlo, int xhi, int zlo, int zhi){
|
||||
int i, j;
|
||||
float mult;
|
||||
|
||||
for(j=zlo; j<zhi; j++){
|
||||
// red
|
||||
mult = 1.0f - refractionMult / float(geoRes);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for(i=xlo; i<=xhi; i++){
|
||||
glColor3f(intensity[i][j+1], 0.0f, 0.0f);
|
||||
glVertex3f(x[i] + xz[i][j+1][0] * mult, 0.0f, z[j+1] + xz[i][j+1][1] * mult);
|
||||
glColor3f(intensity[i][j], 0.0f, 0.0f);
|
||||
glVertex3f(x[i] + xz[i][j][0] * mult, 0.0f, z[j] + xz[i][j][1] * mult);
|
||||
}
|
||||
glEnd();
|
||||
// green
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for(i=xlo; i<=xhi; i++){
|
||||
glColor3f(0.0f, intensity[i][j+1], 0.0f);
|
||||
glVertex3f(x[i] + xz[i][j+1][0], 0.0f, z[j+1] + xz[i][j+1][1]);
|
||||
glColor3f(0.0f, intensity[i][j], 0.0f);
|
||||
glVertex3f(x[i] + xz[i][j][0], 0.0f, z[j] + xz[i][j][1]);
|
||||
}
|
||||
glEnd();
|
||||
// blue
|
||||
mult = 1.0f + refractionMult / float(geoRes);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for(i=xlo; i<=xhi; i++){
|
||||
glColor3f(0.0f, 0.0f, intensity[i][j+1]);
|
||||
glVertex3f(x[i] + xz[i][j+1][0] * mult, 0.0f, z[j+1] + xz[i][j+1][1] * mult);
|
||||
glColor3f(0.0f, 0.0f, intensity[i][j]);
|
||||
glVertex3f(x[i] + xz[i][j][0] * mult, 0.0f, z[j] + xz[i][j][1] * mult);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void causticTextures::makeIndices(int index, int* minus, int* plus){
|
||||
*minus = index - 1;
|
||||
if(*minus < 0)
|
||||
*minus = geoRes - 1;
|
||||
*plus = index + 1;
|
||||
if(*plus >= geoRes)
|
||||
*plus = 0;
|
||||
}
|
||||
|
||||
|
||||
// Here's a little calculus that takes 4 points along a single
|
||||
// dimension and interpolates smoothly between the second and third
|
||||
// depending on the value of where which can be 0.0 to 1.0.
|
||||
// The slope at b is estimated using a and c. The slope at c
|
||||
// is estimated using b and d.
|
||||
float causticTextures::interpolate(float a, float b, float c, float d, float where){
|
||||
float q, r, s, t;
|
||||
|
||||
q = (((3.0f * b) + d - a - (3.0f * c)) * (where * where * where)) * 0.5f;
|
||||
r = (((2.0f * a) - (5.0f * b) + (4.0f * c) - d) * (where * where)) * 0.5f;
|
||||
s = ((c - a) * where) * 0.5f;
|
||||
t = b;
|
||||
return(q + r + s + t);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Terence M. Welsh
|
||||
*
|
||||
* This file is part of Hyperspace.
|
||||
*
|
||||
* Hyperspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Hyperspace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CAUSTICS_H
|
||||
#define CAUSTICS_H
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
|
||||
|
||||
class causticTextures{
|
||||
public:
|
||||
int numKeys;
|
||||
int numFrames;
|
||||
int geoRes;
|
||||
int texSize;
|
||||
float waveAmp;
|
||||
float refractionMult;
|
||||
|
||||
// textures indices for OpenGL texture objects
|
||||
GLuint* caustictex;
|
||||
|
||||
// space for storing geometry of water surface
|
||||
float* x; // x and z are the same for each frame
|
||||
float* z;
|
||||
float*** y; // y (altitude) is different
|
||||
|
||||
float*** xz; // projected vertex positions
|
||||
float** intensity; // projected light intensity
|
||||
|
||||
GLubyte** bitmap;
|
||||
|
||||
// constructor takes the following parameters:
|
||||
// num keyframes (only for fractal heightfield generation),
|
||||
// number of frames, geometry resolution, texture resolution, water depth, wave amplitude,
|
||||
// refraction multiplier (sort of like index of refraction)
|
||||
causticTextures(int keys, int frames, int res, int size, float depth, float wa, float rm);
|
||||
~causticTextures(){}
|
||||
|
||||
private:
|
||||
void makeFractalAltitudes();
|
||||
void makeTrigAltitudes();
|
||||
void altitudeSquare(int left, int right, int bottom, int top, float** alt);
|
||||
void draw(int xlo, int xhi, int zlo, int zhi);
|
||||
void makeIndices(int index, int* minus, int* plus);
|
||||
float myFabs(float x){if(x<0) return -x; return x;};
|
||||
float interpolate(float a, float b, float c, float d, float where);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Terence M. Welsh
|
||||
*
|
||||
* This file is part of Hyperspace.
|
||||
*
|
||||
* Hyperspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Hyperspace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "extensions.h"
|
||||
|
||||
|
||||
|
||||
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
|
||||
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
|
||||
PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
|
||||
PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
|
||||
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
|
||||
PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
|
||||
PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
|
||||
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
|
||||
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
|
||||
PFNGLUNIFORM1IARBPROC glUniform1iARB;
|
||||
|
||||
|
||||
|
||||
int queryExtension(char* name){
|
||||
char* extensions = (char *)glGetString(GL_EXTENSIONS);
|
||||
char* start = extensions;
|
||||
char* position;
|
||||
char* end;
|
||||
int quit = 0;
|
||||
|
||||
while(quit == 0){
|
||||
position = strstr(start, name);
|
||||
if(!position)
|
||||
quit = 1;
|
||||
else{
|
||||
// is name a substring of a larger name?
|
||||
end = position + strlen(name);
|
||||
if(position == start || *(position-1) == ' '){
|
||||
if(*end == ' ' || *end == '\0')
|
||||
return 1;
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void* getProcAddr(char* name){
|
||||
#ifdef WIN32
|
||||
void *addr = (void *)wglGetProcAddress(name);
|
||||
return addr;
|
||||
#else
|
||||
void *addr = (void *)glXGetProcAddressARB((char *)name);
|
||||
return addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int initExtensions(){
|
||||
if(queryExtension("GL_ARB_multitexture") && queryExtension("GL_ARB_texture_cube_map") && queryExtension("GL_ARB_shader_objects")){
|
||||
glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)getProcAddr("glActiveTextureARB");
|
||||
glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)getProcAddr("glCreateShaderObjectARB");
|
||||
glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)getProcAddr("glShaderSourceARB");
|
||||
glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)getProcAddr("glCompileShaderARB");
|
||||
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)getProcAddr("glCreateProgramObjectARB");
|
||||
glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)getProcAddr("glAttachObjectARB");
|
||||
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)getProcAddr("glLinkProgramARB");
|
||||
glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)getProcAddr("glUseProgramObjectARB");
|
||||
glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)getProcAddr("glGetUniformLocationARB");
|
||||
glUniform1iARB = (PFNGLUNIFORM1IARBPROC)getProcAddr("glUniform1iARB");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Terence M. Welsh
|
||||
*
|
||||
* This file is part of Hyperspace.
|
||||
*
|
||||
* Hyperspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Hyperspace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EXTENSIONS_H
|
||||
#define EXTENSIONS_H
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
|
||||
extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
|
||||
extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
|
||||
extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
|
||||
extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
|
||||
extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
|
||||
extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
|
||||
extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
|
||||
extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
|
||||
extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
|
||||
extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
|
||||
|
||||
|
||||
int initExtensions();
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Terence M. Welsh
|
||||
*
|
||||
* This file is part of Hyperspace.
|
||||
*
|
||||
* Hyperspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Hyperspace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "flare.h"
|
||||
|
||||
|
||||
|
||||
#define FLARESIZE 64
|
||||
|
||||
|
||||
unsigned char flare1[FLARESIZE][FLARESIZE][4];
|
||||
unsigned char flare2[FLARESIZE][FLARESIZE][4];
|
||||
unsigned char flare3[FLARESIZE][FLARESIZE][4];
|
||||
unsigned char flare4[FLARESIZE][FLARESIZE][4];
|
||||
unsigned int flarelist[4];
|
||||
unsigned int flaretex[4];
|
||||
|
||||
extern int xsize, ysize;
|
||||
extern float aspectRatio;
|
||||
extern float billboardMat[16];
|
||||
extern double modelMat[16];
|
||||
extern double projMat[16];
|
||||
extern int viewport[4];
|
||||
// Calculated in main draw routine each frame
|
||||
extern float frameTime;
|
||||
extern float camPos[3];
|
||||
|
||||
|
||||
|
||||
void initFlares(){
|
||||
int i, j;
|
||||
float x, y;
|
||||
float temp;
|
||||
|
||||
glGenTextures(4, flaretex);
|
||||
|
||||
// First flare: basic sphere
|
||||
for(i=0; i<FLARESIZE; i++){
|
||||
for(j=0; j<FLARESIZE; j++){
|
||||
flare1[i][j][0] = 255;
|
||||
flare1[i][j][1] = 255;
|
||||
flare1[i][j][2] = 255;
|
||||
x = float(i - FLARESIZE / 2) / float(FLARESIZE / 2);
|
||||
y = float(j - FLARESIZE / 2) / float(FLARESIZE / 2);
|
||||
temp = 1.0f - ((x * x) + (y * y));
|
||||
if(temp > 1.0f)
|
||||
temp = 1.0f;
|
||||
if(temp < 0.0f)
|
||||
temp = 0.0f;
|
||||
temp = temp * temp;
|
||||
flare1[i][j][3] = (unsigned char)(255.0f * temp);
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, flaretex[0]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, FLARESIZE, FLARESIZE, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, flare1);
|
||||
|
||||
// Second flare: flattened sphere
|
||||
for(i=0; i<FLARESIZE; i++){
|
||||
for(j=0; j<FLARESIZE; j++){
|
||||
flare2[i][j][0] = 255;
|
||||
flare2[i][j][1] = 255;
|
||||
flare2[i][j][2] = 255;
|
||||
x = float(i - FLARESIZE / 2) / float(FLARESIZE / 2);
|
||||
y = float(j - FLARESIZE / 2) / float(FLARESIZE / 2);
|
||||
temp = 2.5f * (1.0f - ((x * x) + (y * y)));
|
||||
if(temp > 1.0f)
|
||||
temp = 1.0f;
|
||||
if(temp < 0.0f)
|
||||
temp = 0.0f;
|
||||
//temp = temp * temp * temp * temp;
|
||||
flare2[i][j][3] = (unsigned char)(255.0f * temp);
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, flaretex[1]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, FLARESIZE, FLARESIZE, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, flare2);
|
||||
|
||||
// Third flare: torus
|
||||
for(i=0; i<FLARESIZE; i++){
|
||||
for(j=0; j<FLARESIZE; j++){
|
||||
flare3[i][j][0] = 255;
|
||||
flare3[i][j][1] = 255;
|
||||
flare3[i][j][2] = 255;
|
||||
x = float(i - FLARESIZE / 2) / float(FLARESIZE / 2);
|
||||
y = float(j - FLARESIZE / 2) / float(FLARESIZE / 2);
|
||||
temp = 4.0f * ((x * x) + (y * y)) * (1.0f - ((x * x) + (y * y)));
|
||||
if(temp > 1.0f)
|
||||
temp = 1.0f;
|
||||
if(temp < 0.0f)
|
||||
temp = 0.0f;
|
||||
temp = temp * temp * temp * temp;
|
||||
flare3[i][j][3] = (unsigned char)(255.0f * temp);
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, flaretex[2]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, FLARESIZE, FLARESIZE, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, flare3);
|
||||
|
||||
// Fourth flare: weird flare
|
||||
for(i=0; i<FLARESIZE; i++){
|
||||
for(j=0; j<FLARESIZE; j++){
|
||||
x = float(i - FLARESIZE / 2) / float(FLARESIZE / 2);
|
||||
if(x < 0.0f)
|
||||
x = -x;
|
||||
y = float(j - FLARESIZE / 2) / float(FLARESIZE / 2);
|
||||
if(y < 0.0f)
|
||||
y = -y;
|
||||
flare4[i][j][0] = 255;
|
||||
flare4[i][j][1] = 255;
|
||||
temp = 0.14f * (1.0f - max(x, y)) / max((x * y), 0.05f);
|
||||
if(temp > 1.0f)
|
||||
temp = 1.0f;
|
||||
if(temp < 0.0f)
|
||||
temp = 0.0f;
|
||||
flare4[i][j][2] = (unsigned char)(255.0f * temp);
|
||||
temp = 0.1f * (1.0f - max(x, y)) / max((x * y), 0.1f);
|
||||
if(temp > 1.0f)
|
||||
temp = 1.0f;
|
||||
if(temp < 0.0f)
|
||||
temp = 0.0f;
|
||||
flare4[i][j][3] = (unsigned char)(255.0f * temp);
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, flaretex[3]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, FLARESIZE, FLARESIZE, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, flare4);
|
||||
|
||||
// Build display lists
|
||||
flarelist[0] = glGenLists(4);
|
||||
flarelist[1] = flarelist[0] + 1;
|
||||
flarelist[2] = flarelist[0] + 2;
|
||||
flarelist[3] = flarelist[0] + 3;
|
||||
for(i=0; i<4; i++){
|
||||
glNewList(flarelist[i], GL_COMPILE);
|
||||
glBindTexture(GL_TEXTURE_2D, flaretex[i]);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glVertex3f(-0.5f, -0.5f, 0.0f);
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glVertex3f(0.5f, -0.5f, 0.0f);
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glVertex3f(-0.5f, 0.5f, 0.0f);
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glVertex3f(0.5f, 0.5f, 0.0f);
|
||||
glEnd();
|
||||
glEndList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Draw a flare at a specified (x,y) location on the screen
|
||||
// Screen corners are at (0,0) and (1,1)
|
||||
// alpha = 0.0 for lowest intensity; alpha = 1.0 for highest intensity
|
||||
void flare(double *pos, float red, float green, float blue, float alpha){
|
||||
double winx, winy, winz; // in screen coordinates
|
||||
float x, y, dx, dy;
|
||||
float fadewidth, temp;
|
||||
static float flicker = 0.95f;
|
||||
|
||||
gluProject(pos[0], pos[1], pos[2],
|
||||
modelMat, projMat, viewport,
|
||||
&winx, &winy, &winz);
|
||||
x = (float(winx) / float(xsize)) * aspectRatio;
|
||||
y = float(winy) / float(ysize);
|
||||
float diff[3] = {float(pos[0] - camPos[0]), float(pos[1] - camPos[1]), float(pos[2] - camPos[2])};
|
||||
if(diff[0] * billboardMat[8] + diff[1] * billboardMat[9] + diff[2] * billboardMat[10] > 0.0f)
|
||||
return;
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// Fade alpha if source is off edge of screen
|
||||
fadewidth = float(xsize) / 10.0f;
|
||||
if(y < 0){
|
||||
temp = fadewidth + y;
|
||||
if(temp < 0.0f)
|
||||
return;
|
||||
alpha *= temp / fadewidth;
|
||||
}
|
||||
if(y > ysize){
|
||||
temp = fadewidth - y + ysize;
|
||||
if(temp < 0.0f)
|
||||
return;
|
||||
alpha *= temp / fadewidth;
|
||||
}
|
||||
if(x < 0){
|
||||
temp = fadewidth + x;
|
||||
if(temp < 0.0f)
|
||||
return;
|
||||
alpha *= temp / fadewidth;
|
||||
}
|
||||
if(x > xsize){
|
||||
temp = fadewidth - x + xsize;
|
||||
if(temp < 0.0f)
|
||||
return;
|
||||
alpha *= temp / fadewidth;
|
||||
}
|
||||
|
||||
// Find lens flare vector
|
||||
// This vector runs from the light source through the screen's center
|
||||
dx = 0.5f * aspectRatio - x;
|
||||
dy = 0.5f - y;
|
||||
|
||||
// Setup projection matrix
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, aspectRatio, 0, 1.0f);
|
||||
|
||||
// Update fractal flickering
|
||||
flicker += frameTime * (rsRandf(2.0f) - 1.0f);
|
||||
if(flicker < 0.9f)
|
||||
flicker = 0.9f;
|
||||
if(flicker > 1.1f)
|
||||
flicker = 1.1f;
|
||||
alpha *= flicker;
|
||||
|
||||
// Draw stuff
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(x, y, 0.0f);
|
||||
glScalef(0.1f * flicker, 0.1f * flicker, 1.0f);
|
||||
glColor4f(red, green, blue * 0.8f, alpha);
|
||||
glCallList(flarelist[0]);
|
||||
|
||||
// wide flare
|
||||
glLoadIdentity();
|
||||
glTranslatef(x, y, 0.0f);
|
||||
glScalef(5.0f * alpha, 0.05f * alpha, 1.0f);
|
||||
glColor4f(red * 0.3f, green * 0.3f, blue, alpha);
|
||||
glCallList(flarelist[0]);
|
||||
|
||||
// torus
|
||||
glLoadIdentity();
|
||||
glTranslatef(x, y, 0.0f);
|
||||
glScalef(0.5f, 0.2f, 1.0f);
|
||||
glColor4f(red, green * 0.5f, blue * 0.5f, alpha * 0.4f);
|
||||
glCallList(flarelist[2]);
|
||||
|
||||
// 3 blueish dots
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 0.35f, y + dy * 0.35f, 0.0f);
|
||||
glScalef(0.06f, 0.06f, 1.0f);
|
||||
glColor4f(red * 0.85f, green * 0.85f, blue, alpha * 0.5f);
|
||||
glCallList(flarelist[1]);
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 0.45f, y + dy * 0.45f, 0.0f);
|
||||
glScalef(0.09f, 0.09f, 1.0f);
|
||||
glColor4f(red * 0.7f, green * 0.7f, blue, alpha * 0.4f);
|
||||
glCallList(flarelist[1]);
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 0.55f, y + dy * 0.55f, 0.0f);
|
||||
glScalef(0.12f, 0.12f, 1.0f);
|
||||
glColor4f(red * 0.55f, green * 0.55f, blue, alpha * 0.3f);
|
||||
glCallList(flarelist[1]);
|
||||
|
||||
// 4 more dots
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 0.75f, y + dy * 0.75f, 0.0f);
|
||||
glScalef(0.14f, 0.07f, 1.0f);
|
||||
glColor4f(red * 0.3f, green * 0.3f, blue * 0.3f, alpha);
|
||||
glCallList(flarelist[3]);
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 0.78f, y + dy * 0.78f, 0.0f);
|
||||
glScalef(0.06f, 0.06f, 1.0f);
|
||||
glColor4f(red * 0.3f, green * 0.4f, blue * 0.4f, alpha * 0.5f);
|
||||
glCallList(flarelist[1]);
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 1.25f, y + dy * 1.25f, 0.0f);
|
||||
glScalef(0.1f, 0.1f, 1.0f);
|
||||
glColor4f(red * 0.3f, green * 0.4f, blue * 0.3f, alpha * 0.5f);
|
||||
glCallList(flarelist[1]);
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 1.3f, y + dy * 1.3f, 0.0f);
|
||||
glScalef(0.07f, 0.07f, 1.0f);
|
||||
glColor4f(red * 0.6f, green * 0.45f, blue * 0.3f, alpha * 0.5f);
|
||||
glCallList(flarelist[1]);
|
||||
|
||||
// stretched weird flare
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 1.45f, y + dy * 1.45f, 0.0f);
|
||||
glScalef(0.8f, 0.2f, 1.0f);
|
||||
glRotatef(x * 70.0f, 0, 0, 1);
|
||||
glColor4f(red, green, blue, alpha * 0.4f);
|
||||
glCallList(flarelist[3]);
|
||||
|
||||
// circle
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 2.0f, y + dy * 2.0f, 0.0f);
|
||||
glScalef(0.3f, 0.3f, 1.0f);
|
||||
glColor4f(red, green, blue, alpha * 0.2f);
|
||||
glCallList(flarelist[1]);
|
||||
|
||||
// big weird flare
|
||||
glLoadIdentity();
|
||||
glTranslatef(x + dx * 2.4f, y + dy * 2.4f, 0.0f);
|
||||
glRotatef(y * 40.0f, 0, 0, 1);
|
||||
glScalef(0.7f, 0.7f, 1.0f);
|
||||
glColor4f(red, green, blue, alpha * 0.3f);
|
||||
glCallList(flarelist[3]);
|
||||
|
||||
// Unsetup projection matrix
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Terence M. Welsh
|
||||
*
|
||||
* This file is part of Hyperspace.
|
||||
*
|
||||
* Hyperspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Hyperspace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FLARE_H
|
||||
#define FLARE_H
|
||||
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <rsMath/rsMath.h>
|
||||
|
||||
|
||||
|
||||
// Externed so flares can be drawn elsewhere
|
||||
extern unsigned int flarelist[4];
|
||||
extern unsigned int flaretex[4];
|
||||
|
||||
|
||||
// Generate textures for lens flares
|
||||
// then applies textures to geometry in display lists
|
||||
void initFlares();
|
||||
|
||||
|
||||
// Draw a flare at a specified (x,y) location on the screen
|
||||
// Screen corners are at (0,0) and (1,1)
|
||||
// alpha = 0.0 for lowest intensity; alpha = 1.0 for highest intensity
|
||||
void flare(double *pos, float red, float green, float blue, float alpha);
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
inline const float max(const float& a, const float& b){ return (a > b) ? a : b; }
|
||||
#endif
|
||||
|
||||
|
||||
#endif // FLARE_H
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Terence M. Welsh
|
||||
*
|
||||
* This file is part of Hyperspace.
|
||||
*
|
||||
* Hyperspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Hyperspace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "goo.h"
|
||||
|
||||
|
||||
|
||||
extern float frameTime, simulationTime;
|
||||
|
||||
|
||||
|
||||
goo::goo(int res, float rad){
|
||||
int i, j;
|
||||
|
||||
for(i=0; i<4; ++i){
|
||||
cp[i] = float(i);
|
||||
cs[i] = 0.1f + rsRandf(0.4f);
|
||||
}
|
||||
|
||||
volumeSize = 2.0f;
|
||||
if(res < 5)
|
||||
res = 5;
|
||||
resolution = res;
|
||||
radius = rad;
|
||||
unitSize = volumeSize / float(res);
|
||||
arraySize = 2 * int(0.99f + radius / volumeSize);
|
||||
|
||||
// Init implicit surfaces
|
||||
volume = new impCubeVolume;
|
||||
volume->init(resolution, resolution, resolution, unitSize);
|
||||
// Using exact normals instead of fast normals. This should be slower, but it is faster
|
||||
// in this case because the surface function is so ridiculously fast.
|
||||
volume->useFastNormals(true);
|
||||
volume->setCrawlFromSides(true);
|
||||
volume->function = function;
|
||||
volume->setSurfaceValue(0.4f);
|
||||
surface = new impSurface**[arraySize];
|
||||
useSurface = new bool*[arraySize];
|
||||
for(i=0; i<arraySize; i++){
|
||||
surface[i] = new impSurface*[arraySize];
|
||||
useSurface[i] = new bool[arraySize];
|
||||
for(j=0; j<arraySize; j++){
|
||||
surface[i][j] = new impSurface;
|
||||
useSurface[i][j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
goo::~goo(){
|
||||
delete[] surface;
|
||||
delete[] useSurface;
|
||||
delete volume;
|
||||
}
|
||||
|
||||
|
||||
void goo::update(float x, float z, float heading, float fov){
|
||||
int i, j;
|
||||
|
||||
// update goo function constants
|
||||
for(i=0; i<4; i++){
|
||||
cp[i] += cs[i] * frameTime;
|
||||
if(cp[i] >= RS_PIx2)
|
||||
cp[i] -= RS_PIx2;
|
||||
c[i] = 0.25f * cosf(cp[i]);
|
||||
}
|
||||
|
||||
float halfFov = 0.5f * fov;
|
||||
|
||||
camx = x;
|
||||
camz = z;
|
||||
centerx = unitSize * float(int(0.5f + x / unitSize));
|
||||
centerz = unitSize * float(int(0.5f + z / unitSize));
|
||||
|
||||
clip[0][0] = cosf(heading + halfFov);
|
||||
clip[0][1] = -sinf(heading + halfFov);
|
||||
clip[1][0] = -cosf(heading - halfFov);
|
||||
clip[1][1] = sinf(heading - halfFov);
|
||||
clip[2][0] = sinf(heading);
|
||||
clip[2][1] = -cosf(heading);
|
||||
|
||||
// Empty crawl point vector.
|
||||
// This is only needed so that the right version of impCubeVolume::makeSurface() is called.
|
||||
impCrawlPointVector cpv;
|
||||
|
||||
for(i=0; i<arraySize; i++){
|
||||
for(j=0; j<arraySize; j++){
|
||||
shiftx = volumeSize * (0.5f + float(i - arraySize / 2));
|
||||
shiftz = volumeSize * (0.5f + float(j - arraySize / 2));
|
||||
if(shiftx * clip[0][0] + shiftz * clip[0][1] > volumeSize * -1.41421f){
|
||||
if(shiftx * clip[1][0] + shiftz * clip[1][1] > volumeSize * -1.41421f){
|
||||
if(shiftx * clip[2][0] + shiftz * clip[2][1] < radius + volumeSize * 1.41421f){
|
||||
shiftx += centerx;
|
||||
shiftz += centerz;
|
||||
volume->setSurface(surface[i][j]);
|
||||
surface[i][j]->reset();
|
||||
volume->makeSurface(cpv);
|
||||
useSurface[i][j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float goo::c[4];
|
||||
float goo::shiftx;
|
||||
float goo::shiftz;
|
||||
float goo::camx;
|
||||
float goo::camz;
|
||||
|
||||
float goo::function(float* position){
|
||||
const float px(position[0] + shiftx);
|
||||
const float pz(position[2] + shiftz);
|
||||
const float x(px - camx);
|
||||
const float z(pz - camz);
|
||||
|
||||
return
|
||||
// This first term defines upper and lower surfaces.
|
||||
position[1] * position[1] * 1.25f
|
||||
// These terms make the surfaces wavy.
|
||||
+ c[0] * rsCosf(px - 2.71f * position[1])
|
||||
+ c[1] * rsCosf(4.21f * position[1] + pz)
|
||||
+ c[2] * rsCosf(1.91f * px - 1.67f * pz)
|
||||
+ c[3] * rsCosf(1.53f * px + 1.11f * position[1] + 2.11f * pz)
|
||||
// The last term creates a bubble around the eyepoint so it doesn't
|
||||
// punch through the surface.
|
||||
- 0.1f / (x * x + position[1] * position[1] + z * z);
|
||||
}
|
||||
|
||||
|
||||
void goo::draw(){
|
||||
int i, j;
|
||||
|
||||
for(i=0; i<arraySize; i++){
|
||||
for(j=0; j<arraySize; j++){
|
||||
if(useSurface[i][j]){
|
||||
shiftx = centerx + volumeSize * (0.5f + float(i - arraySize / 2));
|
||||
shiftz = centerz + volumeSize * (0.5f + float(j - arraySize / 2));
|
||||
glPushMatrix();
|
||||
glTranslatef(shiftx, 0.0f, shiftz);
|
||||
surface[i][j]->draw();
|
||||
glPopMatrix();
|
||||
useSurface[i][j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Terence M. Welsh
|
||||
*
|
||||
* This file is part of Hyperspace.
|
||||
*
|
||||
* Hyperspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Hyperspace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GOO_H
|
||||
#define GOO_H
|
||||
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#include <rsMath/rsMath.h>
|
||||
#include <list>
|
||||
#include <Implicit/impCubeVolume.h>
|
||||
#include <Implicit/impCrawlPoint.h>
|
||||
|
||||
|
||||
|
||||
|
||||
class goo{
|
||||
public:
|
||||
int resolution;
|
||||
float radius;
|
||||
float unitSize;
|
||||
float volumeSize;
|
||||
|
||||
static float c[4]; // constants
|
||||
float cp[4]; // constants phase
|
||||
float cs[4]; // constants speed
|
||||
|
||||
static float camx, camz;
|
||||
float centerx, centerz;
|
||||
static float shiftx, shiftz;
|
||||
int arraySize;
|
||||
impCubeVolume* volume;
|
||||
impSurface*** surface;
|
||||
bool** useSurface;
|
||||
|
||||
// normals of planes for culling impSurfaces
|
||||
float clip[3][2];
|
||||
|
||||
goo(int res, float rad);
|
||||
~goo();
|
||||
void update(float x, float z, float heading, float fov);
|
||||
static float function(float* position);
|
||||
void draw();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user