mirror of
https://github.com/ARMSX2/ARMSX3.git
synced 2026-08-24 16:58:52 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8a98305b8 | ||
|
|
2f0c63ac1b | ||
|
|
4b8ffa3702 | ||
|
|
c01f2e9ba8 | ||
|
|
71c694c9ab | ||
|
|
7673186c06 | ||
|
|
e9a21da302 | ||
|
|
5d5b8aa4c1 | ||
|
|
a46dae38bc | ||
|
|
b2caae9da2 | ||
|
|
0262053a91 | ||
|
|
b91c6551ed | ||
|
|
72410638ff | ||
|
|
0a3fcc622f | ||
|
|
43df8b0dc2 | ||
|
|
a14670c282 | ||
|
|
8c1952deae | ||
|
|
c6a0878a97 | ||
|
|
b9689d07fd |
@@ -34,8 +34,8 @@ android {
|
||||
// agree -- an APK that installs below its core's target is a dlopen failure at boot.
|
||||
minSdk = (project.findProperty("armsx3.minSdk") as String?)?.toInt() ?: 33
|
||||
targetSdk = 37
|
||||
versionCode = 20
|
||||
versionName = "0.9.4"
|
||||
versionCode = 21
|
||||
versionName = "0.9.4.1"
|
||||
|
||||
// ARMSX2's UI reads these. STORAGE_ALL_FILES gates the all-files storage path in
|
||||
// onboarding; IN_APP_UPDATER gates the in-app GitHub-release updater.
|
||||
|
||||
@@ -23,6 +23,131 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
adrenotools
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Flurry -> libflurry.so
|
||||
#
|
||||
# Calum Robinson's Flurry screensaver (2002), offered as a live library background. Its own
|
||||
# target rather than folded into the glue for two reasons: it is BSD-3-clause next to GPL code
|
||||
# and the boundary should be visible, and it is plain C from 2002 that wants none of the C++20
|
||||
# and adrenotools the glue is built with.
|
||||
#
|
||||
# gl_compat.c answers the GL 1.x calls the sources make -- client-side vertex arrays, a
|
||||
# fixed-function ortho and GL_QUADS -- with a GLES2 shader, so the renderer itself stays
|
||||
# unmodified. See its header for what is and is not emulated.
|
||||
# ---------------------------------------------------------------------------
|
||||
add_library(flurry SHARED
|
||||
flurry/flurry_jni.c
|
||||
flurry/gl_compat.c
|
||||
flurry/flurry.c
|
||||
flurry/flurry-smoke.c
|
||||
flurry/flurry-spark.c
|
||||
flurry/flurry-star.c
|
||||
flurry/flurry-texture.c
|
||||
)
|
||||
|
||||
target_include_directories(flurry PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/flurry)
|
||||
set_target_properties(flurry PROPERTIES C_STANDARD 99)
|
||||
|
||||
# -ffast-math: a particle simulation judged by eye, running thousands of sqrt per frame.
|
||||
# Upstream shipped hand-written frsqrte paths for exactly this reason.
|
||||
target_compile_options(flurry PRIVATE -O2 -ffast-math -Wall -Wno-unused-parameter)
|
||||
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)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Discord Social SDK bridge -> libarmsx2_discord.so
|
||||
#
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2002, Calum Robinson
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
/* Spark.cpp: implementation of the Spark class. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "flurry.h"
|
||||
|
||||
void InitSpark(Spark *s)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<3;i++)
|
||||
{
|
||||
s->position[i] = RandFlt(-100.0, 100.0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Immediate mode and the matrix stack, neither of which exists in GLES2.
|
||||
*
|
||||
* Left in place rather than deleted because it is Calum Robinson's code and the update half of
|
||||
* this file is very much live -- UpdateSpark and UpdateSparkColour drive the smoke. Upstream
|
||||
* never defines DRAW_SPARKS either, so this has not been compiled by xscreensaver in years;
|
||||
* the guard just makes that explicit instead of relying on the caller staying commented out. */
|
||||
#ifdef DRAW_SPARKS
|
||||
void DrawSpark(global_info_t *global, flurry_info_t *flurry, Spark *s)
|
||||
{
|
||||
const float black[4] = {0.0f,0.0f,0.0f,1.0f};
|
||||
float width,sx,sy;
|
||||
float a;
|
||||
float c = 0.0625f;
|
||||
float screenx;
|
||||
float screeny;
|
||||
float w,z, scale;
|
||||
int k;
|
||||
width = 60000.0f * global->sys_glWidth / 1024.0f;
|
||||
|
||||
z = s->position[2];
|
||||
sx = s->position[0] * global->sys_glWidth / z + global->sys_glWidth * 0.5f;
|
||||
sy = s->position[1] * global->sys_glWidth / z + global->sys_glHeight * 0.5f;
|
||||
w = width*4.0f / z;
|
||||
|
||||
screenx = sx;
|
||||
screeny = sy;
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(screenx,screeny,0.0f);
|
||||
scale = w/50.0f;
|
||||
glScalef(scale,scale,0.0f);
|
||||
for (k=0;k<12;k++)
|
||||
{
|
||||
a = ((float) (random() % 3600)) / 10.0f;
|
||||
glRotatef(a,0.0f,0.0f,1.0f);
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
glColor4fv(black);
|
||||
glVertex2f(-3.0f,0.0f);
|
||||
a = 2.0f + (float) (random() & 255) * c;
|
||||
glVertex2f(-3.0f,a);
|
||||
glColor4fv(s->color);
|
||||
glVertex2f(0.0f,0.0f);
|
||||
glColor4fv(black);
|
||||
glVertex2f(0.0f,a);
|
||||
glVertex2f(3.0f,0.0f);
|
||||
glVertex2f(3.0f,a);
|
||||
glEnd();
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
#endif /* DRAW_SPARKS */
|
||||
|
||||
#define BIGMYSTERY 1800.0
|
||||
#define MAXANGLES 16384
|
||||
|
||||
void UpdateSparkColour(global_info_t *global, flurry_info_t *flurry, Spark *s)
|
||||
{
|
||||
const float rotationsPerSecond = (float) (2.0*PI*fieldSpeed/MAXANGLES);
|
||||
double thisPointInRadians;
|
||||
double thisAngle = flurry->fTime*rotationsPerSecond;
|
||||
/*float cf;*/
|
||||
float cycleTime = 20.0f;
|
||||
float colorRot;
|
||||
float redPhaseShift;
|
||||
float greenPhaseShift;
|
||||
float bluePhaseShift;
|
||||
float baseRed;
|
||||
float baseGreen;
|
||||
float baseBlue;
|
||||
float colorTime;
|
||||
|
||||
if (flurry->currentColorMode == rainbowColorMode)
|
||||
{
|
||||
cycleTime = 1.5f;
|
||||
}
|
||||
else if (flurry->currentColorMode == tiedyeColorMode)
|
||||
{
|
||||
cycleTime = 4.5f;
|
||||
}
|
||||
else if (flurry->currentColorMode == cyclicColorMode)
|
||||
{
|
||||
cycleTime = 20.0f;
|
||||
}
|
||||
else if (flurry->currentColorMode == slowCyclicColorMode)
|
||||
{
|
||||
cycleTime = 120.0f;
|
||||
}
|
||||
colorRot = (float) (2.0*PI/cycleTime);
|
||||
redPhaseShift = 0.0f; /* cycleTime * 0.0f / 3.0f */
|
||||
greenPhaseShift = cycleTime / 3.0f;
|
||||
bluePhaseShift = cycleTime * 2.0f / 3.0f ;
|
||||
colorTime = flurry->fTime;
|
||||
if (flurry->currentColorMode == whiteColorMode)
|
||||
{
|
||||
baseRed = 0.1875f;
|
||||
baseGreen = 0.1875f;
|
||||
baseBlue = 0.1875f;
|
||||
}
|
||||
else if (flurry->currentColorMode == multiColorMode)
|
||||
{
|
||||
baseRed = 0.0625f;
|
||||
baseGreen = 0.0625f;
|
||||
baseBlue = 0.0625f;
|
||||
}
|
||||
else if (flurry->currentColorMode == darkColorMode)
|
||||
{
|
||||
baseRed = 0.0f;
|
||||
baseGreen = 0.0f;
|
||||
baseBlue = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flurry->currentColorMode < slowCyclicColorMode)
|
||||
{
|
||||
colorTime = (flurry->currentColorMode / 6.0f) * cycleTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
colorTime = flurry->fTime + flurry->flurryRandomSeed;
|
||||
}
|
||||
baseRed = 0.109375f * ((float) cos((colorTime+redPhaseShift)*colorRot)+1.0f);
|
||||
baseGreen = 0.109375f * ((float) cos((colorTime+greenPhaseShift)*colorRot)+1.0f);
|
||||
baseBlue = 0.109375f * ((float) cos((colorTime+bluePhaseShift)*colorRot)+1.0f);
|
||||
}
|
||||
|
||||
/*
|
||||
cf = ((float) (cos(7.0*((flurry->fTime)*rotationsPerSecond))+cos(3.0*((flurry->fTime)*rotationsPerSecond))+cos(13.0*((flurry->fTime)*rotationsPerSecond))));
|
||||
cf /= 6.0f;
|
||||
cf += 2.0f;
|
||||
*/
|
||||
thisPointInRadians = 2.0 * PI * (double) s->mystery / (double) BIGMYSTERY;
|
||||
|
||||
s->color[0] = baseRed + 0.0625f * (0.5f + (float) cos((15.0 * (thisPointInRadians + 3.0*thisAngle))) + (float) sin((7.0 * (thisPointInRadians + thisAngle))));
|
||||
s->color[1] = baseGreen + 0.0625f * (0.5f + (float) sin(((thisPointInRadians) + thisAngle)));
|
||||
s->color[2] = baseBlue + 0.0625f * (0.5f + (float) cos((37.0 * (thisPointInRadians + thisAngle))));
|
||||
}
|
||||
|
||||
void UpdateSpark(global_info_t *global, flurry_info_t *flurry, Spark *s)
|
||||
{
|
||||
const float rotationsPerSecond = (float) (2.0*PI*fieldSpeed/MAXANGLES);
|
||||
double thisPointInRadians;
|
||||
double thisAngle = flurry->fTime*rotationsPerSecond;
|
||||
float cf;
|
||||
int i;
|
||||
double tmpX1,tmpY1,tmpZ1;
|
||||
double tmpX2,tmpY2,tmpZ2;
|
||||
double tmpX3,tmpY3,tmpZ3;
|
||||
double tmpX4,tmpY4,tmpZ4;
|
||||
double rotation;
|
||||
double cr;
|
||||
double sr;
|
||||
float cycleTime = 20.0f;
|
||||
float colorRot;
|
||||
float redPhaseShift;
|
||||
float greenPhaseShift;
|
||||
float bluePhaseShift;
|
||||
float baseRed;
|
||||
float baseGreen;
|
||||
float baseBlue;
|
||||
float colorTime;
|
||||
|
||||
float old[3];
|
||||
|
||||
if (flurry->currentColorMode == rainbowColorMode) {
|
||||
cycleTime = 1.5f;
|
||||
} else if (flurry->currentColorMode == tiedyeColorMode) {
|
||||
cycleTime = 4.5f;
|
||||
} else if (flurry->currentColorMode == cyclicColorMode) {
|
||||
cycleTime = 20.0f;
|
||||
} else if (flurry->currentColorMode == slowCyclicColorMode) {
|
||||
cycleTime = 120.0f;
|
||||
}
|
||||
colorRot = (float) (2.0*PI/cycleTime);
|
||||
redPhaseShift = 0.0f; /* cycleTime * 0.0f / 3.0f */
|
||||
greenPhaseShift = cycleTime / 3.0f;
|
||||
bluePhaseShift = cycleTime * 2.0f / 3.0f ;
|
||||
colorTime = flurry->fTime;
|
||||
if (flurry->currentColorMode == whiteColorMode) {
|
||||
baseRed = 0.1875f;
|
||||
baseGreen = 0.1875f;
|
||||
baseBlue = 0.1875f;
|
||||
} else if (flurry->currentColorMode == multiColorMode) {
|
||||
baseRed = 0.0625f;
|
||||
baseGreen = 0.0625f;
|
||||
baseBlue = 0.0625f;
|
||||
} else if (flurry->currentColorMode == darkColorMode) {
|
||||
baseRed = 0.0f;
|
||||
baseGreen = 0.0f;
|
||||
baseBlue = 0.0f;
|
||||
} else {
|
||||
if(flurry->currentColorMode < slowCyclicColorMode) {
|
||||
colorTime = (flurry->currentColorMode / 6.0f) * cycleTime;
|
||||
} else {
|
||||
colorTime = flurry->fTime + flurry->flurryRandomSeed;
|
||||
}
|
||||
baseRed = 0.109375f * ((float) cos((colorTime+redPhaseShift)*colorRot)+1.0f);
|
||||
baseGreen = 0.109375f * ((float) cos((colorTime+greenPhaseShift)*colorRot)+1.0f);
|
||||
baseBlue = 0.109375f * ((float) cos((colorTime+bluePhaseShift)*colorRot)+1.0f);
|
||||
}
|
||||
|
||||
for (i=0;i<3;i++) {
|
||||
old[i] = s->position[i];
|
||||
}
|
||||
|
||||
cf = ((float) (cos(7.0*((flurry->fTime)*rotationsPerSecond))+cos(3.0*((flurry->fTime)*rotationsPerSecond))+cos(13.0*((flurry->fTime)*rotationsPerSecond))));
|
||||
cf /= 6.0f;
|
||||
cf += 2.0f;
|
||||
thisPointInRadians = 2.0 * PI * (double) s->mystery / (double) BIGMYSTERY;
|
||||
|
||||
s->color[0] = baseRed + 0.0625f * (0.5f + (float) cos((15.0 * (thisPointInRadians + 3.0*thisAngle))) + (float) sin((7.0 * (thisPointInRadians + thisAngle))));
|
||||
s->color[1] = baseGreen + 0.0625f * (0.5f + (float) sin(((thisPointInRadians) + thisAngle)));
|
||||
s->color[2] = baseBlue + 0.0625f * (0.5f + (float) cos((37.0 * (thisPointInRadians + thisAngle))));
|
||||
s->position[0] = fieldRange * cf * (float) cos(11.0 * (thisPointInRadians + (3.0*thisAngle)));
|
||||
s->position[1] = fieldRange * cf * (float) sin(12.0 * (thisPointInRadians + (4.0*thisAngle)));
|
||||
s->position[2] = fieldRange * (float) cos((23.0 * (thisPointInRadians + (12.0*thisAngle))));
|
||||
|
||||
rotation = thisAngle*0.501 + 5.01 * (double) s->mystery / (double) BIGMYSTERY;
|
||||
cr = cos(rotation);
|
||||
sr = sin(rotation);
|
||||
tmpX1 = s->position[0] * cr - s->position[1] * sr;
|
||||
tmpY1 = s->position[1] * cr + s->position[0] * sr;
|
||||
tmpZ1 = s->position[2];
|
||||
|
||||
tmpX2 = tmpX1 * cr - tmpZ1 * sr;
|
||||
tmpY2 = tmpY1;
|
||||
tmpZ2 = tmpZ1 * cr + tmpX1 * sr;
|
||||
|
||||
tmpX3 = tmpX2;
|
||||
tmpY3 = tmpY2 * cr - tmpZ2 * sr;
|
||||
tmpZ3 = tmpZ2 * cr + tmpY2 * sr + seraphDistance;
|
||||
|
||||
rotation = thisAngle*2.501 + 85.01 * (double) s->mystery / (double) BIGMYSTERY;
|
||||
cr = cos(rotation);
|
||||
sr = sin(rotation);
|
||||
tmpX4 = tmpX3 * cr - tmpY3 * sr;
|
||||
tmpY4 = tmpY3 * cr + tmpX3 * sr;
|
||||
tmpZ4 = tmpZ3;
|
||||
|
||||
s->position[0] = (float) tmpX4 + RandBell(5.0f*fieldCoherence);
|
||||
s->position[1] = (float) tmpY4 + RandBell(5.0f*fieldCoherence);
|
||||
s->position[2] = (float) tmpZ4 + RandBell(5.0f*fieldCoherence);
|
||||
|
||||
for (i=0;i<3;i++) {
|
||||
s->delta[i] = (s->position[i] - old[i])/flurry->fDeltaTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2002, Calum Robinson
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
/* Star.c: implementation of the Star class. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "flurry.h"
|
||||
|
||||
/* Construction/Destruction */
|
||||
|
||||
void InitStar(Star *s)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<3;i++) {
|
||||
s->position[i] = RandFlt(-10000.0, 10000.0);
|
||||
}
|
||||
s->rotSpeed = RandFlt(0.4, 0.9);
|
||||
s->mystery = RandFlt(0.0, 10.0);
|
||||
}
|
||||
|
||||
#define BIGMYSTERY 1800.0
|
||||
#define MAXANGLES 16384
|
||||
|
||||
void UpdateStar(global_info_t *global, flurry_info_t *flurry, Star *s)
|
||||
{
|
||||
float rotationsPerSecond = (float) (2.0*PI*12.0/MAXANGLES) * s->rotSpeed /* speed control */;
|
||||
double thisPointInRadians;
|
||||
double thisAngle = flurry->fTime*rotationsPerSecond;
|
||||
float cf;
|
||||
double tmpX1,tmpY1,tmpZ1;
|
||||
double tmpX2,tmpY2,tmpZ2;
|
||||
double tmpX3,tmpY3,tmpZ3;
|
||||
double tmpX4,tmpY4,tmpZ4;
|
||||
double rotation;
|
||||
double cr;
|
||||
double sr;
|
||||
|
||||
s->ate = 0;
|
||||
|
||||
cf = ((float) (cos(7.0*((flurry->fTime)*rotationsPerSecond))+cos(3.0*((flurry->fTime)*rotationsPerSecond))+cos(13.0*((flurry->fTime)*rotationsPerSecond))));
|
||||
cf /= 6.0f;
|
||||
cf += 0.75f;
|
||||
thisPointInRadians = 2.0 * PI * (double) s->mystery / (double) BIGMYSTERY;
|
||||
|
||||
s->position[0] = 250.0f * cf * (float) cos(11.0 * (thisPointInRadians + (3.0*thisAngle)));
|
||||
s->position[1] = 250.0f * cf * (float) sin(12.0 * (thisPointInRadians + (4.0*thisAngle)));
|
||||
s->position[2] = 250.0f * (float) cos((23.0 * (thisPointInRadians + (12.0*thisAngle))));
|
||||
|
||||
rotation = thisAngle*0.501 + 5.01 * (double) s->mystery / (double) BIGMYSTERY;
|
||||
cr = cos(rotation);
|
||||
sr = sin(rotation);
|
||||
tmpX1 = s->position[0] * cr - s->position[1] * sr;
|
||||
tmpY1 = s->position[1] * cr + s->position[0] * sr;
|
||||
tmpZ1 = s->position[2];
|
||||
|
||||
tmpX2 = tmpX1 * cr - tmpZ1 * sr;
|
||||
tmpY2 = tmpY1;
|
||||
tmpZ2 = tmpZ1 * cr + tmpX1 * sr;
|
||||
|
||||
tmpX3 = tmpX2;
|
||||
tmpY3 = tmpY2 * cr - tmpZ2 * sr;
|
||||
tmpZ3 = tmpZ2 * cr + tmpY2 * sr + seraphDistance;
|
||||
|
||||
rotation = thisAngle*2.501 + 85.01 * (double) s->mystery / (double) BIGMYSTERY;
|
||||
cr = cos(rotation);
|
||||
sr = sin(rotation);
|
||||
tmpX4 = tmpX3 * cr - tmpY3 * sr;
|
||||
tmpY4 = tmpY3 * cr + tmpX3 * sr;
|
||||
tmpZ4 = tmpZ3;
|
||||
|
||||
s->position[0] = (float) tmpX4;
|
||||
s->position[1] = (float) tmpY4;
|
||||
s->position[2] = (float) tmpZ4;
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2002, Calum Robinson
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* Texture.c
|
||||
* AppleFlurry
|
||||
*
|
||||
* Created by calumr on Sat Jul 07 2001.
|
||||
* Copyright (c) 2001 __CompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "flurry.h"
|
||||
|
||||
/* #include <GL/gl.h> */
|
||||
/* #include <GL/glu.h> */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
static GLubyte smallTextureArray[32][32];
|
||||
static GLubyte bigTextureArray[256][256][2];
|
||||
|
||||
/* simple smoothing routine */
|
||||
static void SmoothTexture(void)
|
||||
{
|
||||
GLubyte filter[32][32];
|
||||
int i,j;
|
||||
float t;
|
||||
for (i=1;i<31;i++)
|
||||
{
|
||||
for (j=1;j<31;j++)
|
||||
{
|
||||
t = (float) smallTextureArray[i][j]*4;
|
||||
t += (float) smallTextureArray[i-1][j];
|
||||
t += (float) smallTextureArray[i+1][j];
|
||||
t += (float) smallTextureArray[i][j-1];
|
||||
t += (float) smallTextureArray[i][j+1];
|
||||
t /= 8.0f;
|
||||
filter[i][j] = (GLubyte) t;
|
||||
}
|
||||
}
|
||||
for (i=1;i<31;i++)
|
||||
{
|
||||
for (j=1;j<31;j++)
|
||||
{
|
||||
smallTextureArray[i][j] = filter[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add some randomness to texture data */
|
||||
static void SpeckleTexture(void)
|
||||
{
|
||||
int i,j;
|
||||
int speck;
|
||||
float t;
|
||||
for (i=2;i<30;i++)
|
||||
{
|
||||
for (j=2;j<30;j++)
|
||||
{
|
||||
speck = 1;
|
||||
while (speck <= 32 && random() % 2)
|
||||
{
|
||||
t = (float) MIN_(255,smallTextureArray[i][j]+speck);
|
||||
smallTextureArray[i][j] = (GLubyte) t;
|
||||
speck+=speck;
|
||||
}
|
||||
speck = 1;
|
||||
while (speck <= 32 && random() % 2)
|
||||
{
|
||||
t = (float) MAX_(0,smallTextureArray[i][j]-speck);
|
||||
smallTextureArray[i][j] = (GLubyte) t;
|
||||
speck+=speck;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MakeSmallTexture(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
int i,j;
|
||||
float r,t;
|
||||
if (firstTime)
|
||||
{
|
||||
firstTime = 0;
|
||||
for (i=0;i<32;i++)
|
||||
{
|
||||
for (j=0;j<32;j++)
|
||||
{
|
||||
r = (float) sqrt((i-15.5)*(i-15.5)+(j-15.5)*(j-15.5));
|
||||
if (r > 15.0f)
|
||||
{
|
||||
smallTextureArray[i][j] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = 255.0f * (float) cos(r*M_PI/31.0);
|
||||
smallTextureArray[i][j] = (GLubyte) t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0;i<32;i++)
|
||||
{
|
||||
for (j=0;j<32;j++)
|
||||
{
|
||||
r = (float) sqrt((i-15.5)*(i-15.5)+(j-15.5)*(j-15.5));
|
||||
if (r > 15.0f)
|
||||
{
|
||||
t = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = 255.0f * (float) cos(r*M_PI/31.0);
|
||||
}
|
||||
smallTextureArray[i][j] = (GLubyte) MIN_(255,(t+smallTextureArray[i][j]+smallTextureArray[i][j])/3);
|
||||
}
|
||||
}
|
||||
}
|
||||
SpeckleTexture();
|
||||
SmoothTexture();
|
||||
SmoothTexture();
|
||||
}
|
||||
|
||||
static void CopySmallTextureToBigTexture(int k, int l)
|
||||
{
|
||||
int i,j;
|
||||
for (i=0;i<32;i++)
|
||||
{
|
||||
for (j=0;j<32;j++)
|
||||
{
|
||||
bigTextureArray[i+k][j+l][0] = smallTextureArray[i][j];
|
||||
bigTextureArray[i+k][j+l][1] = smallTextureArray[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AverageLastAndFirstTextures(void)
|
||||
{
|
||||
int i,j;
|
||||
int t;
|
||||
for (i=0;i<32;i++)
|
||||
{
|
||||
for (j=0;j<32;j++)
|
||||
{
|
||||
t = (smallTextureArray[i][j] + bigTextureArray[i][j][0]) / 2;
|
||||
smallTextureArray[i][j] = (GLubyte) MIN_(255,t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLuint MakeTexture(void)
|
||||
{
|
||||
GLuint theTexture = 0;
|
||||
int i,j;
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
for (j=0;j<8;j++)
|
||||
{
|
||||
if (i==7 && j==7)
|
||||
{
|
||||
AverageLastAndFirstTextures();
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeSmallTexture();
|
||||
}
|
||||
CopySmallTextureToBigTexture(i*32,j*32);
|
||||
}
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
||||
|
||||
glGenTextures(1, &theTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, theTexture);
|
||||
|
||||
/* Set the tiling mode (this is generally always GL_REPEAT). */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
/* Set the filtering. */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
/* GL_LINEAR, not LINEAR_MIPMAP_NEAREST.
|
||||
*
|
||||
* A mipmapped min filter makes the texture INCOMPLETE unless the whole chain exists, and an
|
||||
* incomplete texture samples as opaque black -- which, through this shader's c *= texture,
|
||||
* multiplies the entire particle to nothing. glGenerateMipmap is also not guaranteed for
|
||||
* GL_LUMINANCE_ALPHA, which is filterable but not colour-renderable, so the chain may never
|
||||
* have been built. The sprite is a 256x256 blob drawn at roughly its own size; the mip chain
|
||||
* was never doing much for it. */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
/* gluBuild2DMipmaps upstream. There is no GLU on Android, and GLES2 builds the chain
|
||||
* itself -- the internal format has to be spelled out rather than given as a component
|
||||
* count, which is what the 2 meant in GL 1.x. */
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 256, 256, 0,
|
||||
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, bigTextureArray);
|
||||
/* No glGenerateMipmap: see the min filter above. */
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
return theTexture;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2002, Calum Robinson
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
/* -*- Mode: C; tab-width: 4 c-basic-offset: 4 indent-tabs-mode: t -*- */
|
||||
/* flurry */
|
||||
#ifndef __GLCODE__
|
||||
#define __GLCODE__
|
||||
|
||||
/* Ported to Android/GLES2: see flurry_port.h for what these supplied. */
|
||||
#include "flurry_port.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef struct _global_info_t global_info_t;
|
||||
typedef struct _flurry_info_t flurry_info_t;
|
||||
|
||||
#define sqr(X) ((X) * (X))
|
||||
#define PI M_PI
|
||||
#define DEG2RAD(X) (PI*(X)/180.0)
|
||||
#define RAD2DEG(X) ((X)*180.0/PI)
|
||||
#define rnd() (frand(1.0))
|
||||
|
||||
/* fabs: Absolute function. */
|
||||
/* #undef abs */
|
||||
/* #define abs(a) ( (a) > 0 ? (a) : -(a) ) */
|
||||
|
||||
/* Force sign clamping to (-1;0;1) */
|
||||
#define sgn(a) ((a)<0?-1:((a)?1:0))
|
||||
|
||||
/* used to compute the min and max of two expresions */
|
||||
#define MIN_(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX_(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
typedef union {
|
||||
float f[4];
|
||||
#if 0
|
||||
#if __VEC__
|
||||
vector float v;
|
||||
#endif
|
||||
#endif /* 0 */
|
||||
} floatToVector;
|
||||
|
||||
typedef union {
|
||||
unsigned int i[4];
|
||||
#if 0
|
||||
#if __VEC__
|
||||
vector unsigned int v;
|
||||
#endif
|
||||
#endif /* 0 */
|
||||
} intToVector;
|
||||
|
||||
typedef struct SmokeParticleV
|
||||
{
|
||||
floatToVector color[4];
|
||||
floatToVector position[3];
|
||||
floatToVector oldposition[3];
|
||||
floatToVector delta[3];
|
||||
intToVector dead;
|
||||
floatToVector time;
|
||||
intToVector animFrame;
|
||||
} SmokeParticleV;
|
||||
|
||||
#define NUMSMOKEPARTICLES 3600
|
||||
|
||||
typedef struct SmokeV
|
||||
{
|
||||
SmokeParticleV p[NUMSMOKEPARTICLES/4];
|
||||
int nextParticle;
|
||||
int nextSubParticle;
|
||||
float lastParticleTime;
|
||||
int firstTime;
|
||||
long frame;
|
||||
float old[3];
|
||||
floatToVector seraphimVertices[NUMSMOKEPARTICLES*2+1];
|
||||
floatToVector seraphimColors[NUMSMOKEPARTICLES*4+1];
|
||||
float seraphimTextures[NUMSMOKEPARTICLES*2*4];
|
||||
} SmokeV;
|
||||
|
||||
void InitSmoke(SmokeV *s);
|
||||
|
||||
void UpdateSmoke_ScalarBase(global_info_t *global, flurry_info_t *flurry, SmokeV *s);
|
||||
#if 0
|
||||
#ifdef __ppc__
|
||||
void UpdateSmoke_ScalarFrsqrte(global_info_t *global, flurry_info_t *flurry, SmokeV *s);
|
||||
#endif
|
||||
#ifdef __VEC__
|
||||
void UpdateSmoke_VectorBase(global_info_t *global, flurry_info_t *flurry, SmokeV *s);
|
||||
void UpdateSmoke_VectorUnrolled(global_info_t *global, flurry_info_t *flurry, SmokeV *s);
|
||||
#endif
|
||||
#endif /* 0 */
|
||||
|
||||
void DrawSmoke_Scalar(global_info_t *global, flurry_info_t *flurry, SmokeV *s, float);
|
||||
void DrawSmoke_Vector(global_info_t *global, flurry_info_t *flurry, SmokeV *s, float);
|
||||
|
||||
typedef struct Star
|
||||
{
|
||||
float position[3];
|
||||
float mystery;
|
||||
float rotSpeed;
|
||||
int ate;
|
||||
} Star;
|
||||
|
||||
void UpdateStar(global_info_t *global, flurry_info_t *flurry, Star *s);
|
||||
void InitStar(Star *s);
|
||||
|
||||
typedef struct Spark
|
||||
{
|
||||
float position[3];
|
||||
int mystery;
|
||||
float delta[3];
|
||||
float color[4];
|
||||
} Spark;
|
||||
|
||||
void UpdateSparkColour(global_info_t *info, flurry_info_t *flurry, Spark *s);
|
||||
void InitSpark(Spark *s);
|
||||
void UpdateSpark(global_info_t *info, flurry_info_t *flurry, Spark *s);
|
||||
void DrawSpark(global_info_t *info, flurry_info_t *flurry, Spark *s);
|
||||
|
||||
/* #define FastDistance2D(x,y) hypot(x,y) */
|
||||
|
||||
/* UInt8 sys_glBPP=32; */
|
||||
/* int SSMODE = FALSE; */
|
||||
/* int currentVideoMode = 0; */
|
||||
/* int cohesiveness = 7; */
|
||||
/* int fieldStrength; */
|
||||
/* int colorCoherence = 7; */
|
||||
/* int fieldIncoherence = 0; */
|
||||
/* int ifieldSpeed = 120; */
|
||||
|
||||
static inline float FastDistance2D(float x, float y)
|
||||
{
|
||||
/* this function computes the distance from 0,0 to x,y with ~3.5% error */
|
||||
float mn;
|
||||
/* first compute the absolute value of x,y */
|
||||
x = (x < 0.0f) ? -x : x;
|
||||
y = (y < 0.0f) ? -y : y;
|
||||
|
||||
/* compute the minimum of x,y */
|
||||
mn = x<y?x:y;
|
||||
|
||||
/* return the distance */
|
||||
return(x+y-(mn*0.5f)-(mn*0.25f)+(mn*0.0625f));
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifdef __VEC__
|
||||
|
||||
static vector float FastDistance2DV(vector float x, vector float y) {
|
||||
vector float mn, temp;
|
||||
|
||||
x = vec_abs(x);
|
||||
y = vec_abs(y);
|
||||
mn = vec_min(x,y);
|
||||
temp = vec_add(x,y);
|
||||
temp = vec_madd(mn, (vector float)(-0.6875), temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* 0 */
|
||||
|
||||
#define RandFlt(min, max) ((min) + frand((max) - (min)))
|
||||
|
||||
#define RandBell(scale) ((scale) * (-(frand(.5) + frand(.5) + frand(.5))))
|
||||
|
||||
extern GLuint theTexture;
|
||||
|
||||
GLuint MakeTexture(void);
|
||||
|
||||
#define OPT_MODE_SCALAR_BASE 0x0
|
||||
|
||||
#if 0
|
||||
#ifdef __ppc__
|
||||
#define OPT_MODE_SCALAR_FRSQRTE 0x1
|
||||
#endif
|
||||
|
||||
#ifdef __VEC__
|
||||
#define OPT_MODE_VECTOR_SIMPLE 0x2
|
||||
#define OPT_MODE_VECTOR_UNROLLED 0x3
|
||||
#endif
|
||||
#endif /* 0 */
|
||||
|
||||
typedef enum _ColorModes
|
||||
{
|
||||
redColorMode = 0,
|
||||
magentaColorMode,
|
||||
blueColorMode,
|
||||
cyanColorMode,
|
||||
greenColorMode,
|
||||
yellowColorMode,
|
||||
slowCyclicColorMode,
|
||||
cyclicColorMode,
|
||||
tiedyeColorMode,
|
||||
rainbowColorMode,
|
||||
whiteColorMode,
|
||||
multiColorMode,
|
||||
darkColorMode
|
||||
} ColorModes;
|
||||
|
||||
#define gravity 1500000.0f
|
||||
|
||||
#define incohesion 0.07f
|
||||
#define colorIncoherence 0.15f
|
||||
#define streamSpeed 450.0
|
||||
#define fieldCoherence 0
|
||||
#define fieldSpeed 12.0f
|
||||
#define numParticles 250
|
||||
#define starSpeed 50
|
||||
#define seraphDistance 2000.0f
|
||||
#define streamSize 25000.0f
|
||||
#define fieldRange 1000.0f
|
||||
#define streamBias 7.0f
|
||||
|
||||
#define MAX_SPARKS 64
|
||||
|
||||
struct _flurry_info_t {
|
||||
flurry_info_t *next;
|
||||
ColorModes currentColorMode;
|
||||
SmokeV *s;
|
||||
Star *star;
|
||||
Spark *spark[MAX_SPARKS];
|
||||
float streamExpansion;
|
||||
int numStreams;
|
||||
double flurryRandomSeed;
|
||||
double fTime;
|
||||
double fOldTime;
|
||||
double fDeltaTime;
|
||||
double briteFactor;
|
||||
float drag;
|
||||
int dframe;
|
||||
};
|
||||
|
||||
struct _global_info_t {
|
||||
/* system values */
|
||||
int optMode;
|
||||
|
||||
/* Port-only. Flurry never clears: it fades the screen by a few percent each frame, which
|
||||
* is how the trails exist. That assumes it owns a buffer that started black. Here it gets
|
||||
* a rotating set of swapchain buffers full of uninitialised GPU memory, and an 8% fade
|
||||
* cannot win against that -- it shows as static the smoke sits behind. Clear each buffer
|
||||
* once, then hand over to the fade. */
|
||||
int port_clear_frames;
|
||||
|
||||
float sys_glWidth;
|
||||
float sys_glHeight;
|
||||
|
||||
double gTimeCounter;
|
||||
int first;
|
||||
double oldFrameTime;
|
||||
|
||||
flurry_info_t *flurry;
|
||||
GLuint texid;
|
||||
};
|
||||
|
||||
#define kNumSpectrumEntries 512
|
||||
|
||||
double TimeInSecondsSinceStart(const global_info_t *global);
|
||||
|
||||
#endif /* Include/Define */
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* JNI shim between the wallpaper's GL thread and Flurry.
|
||||
*
|
||||
* Every function here must be called with the EGL context current -- the Kotlin side owns the
|
||||
* context and guarantees that. Nothing is thread-safe beyond that assumption, which is fine
|
||||
* because a wallpaper engine has exactly one GL thread.
|
||||
*/
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "gl_compat.h"
|
||||
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "Flurry", __VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "Flurry", __VA_ARGS__)
|
||||
|
||||
typedef struct _global_info_t global_info_t;
|
||||
|
||||
global_info_t *flurry_port_new(int preset);
|
||||
global_info_t *flurry_port_new_custom(int streams, int colour, float thickness,
|
||||
float speed, float brightness);
|
||||
void flurry_port_resize(global_info_t *global, int width, int height);
|
||||
int flurry_port_draw(global_info_t *global);
|
||||
void flurry_port_free(global_info_t *global);
|
||||
|
||||
#define NS(name) Java_com_armsx2_ui_home_FlurryNative_##name
|
||||
|
||||
JNIEXPORT jlong JNICALL NS(nativeCreate)(JNIEnv *env, jclass clazz, jint preset)
|
||||
{
|
||||
(void) env; (void) clazz;
|
||||
|
||||
/* Flurry's entire look comes out of frand(); an unseeded run would be identical every
|
||||
* time the wallpaper restarts, which on a phone is many times a day. */
|
||||
srandom((unsigned) time(NULL) ^ (unsigned) clock());
|
||||
|
||||
if (!fx_init()) {
|
||||
LOGE("GL compatibility layer failed to initialise");
|
||||
return 0;
|
||||
}
|
||||
|
||||
global_info_t *g = flurry_port_new(preset);
|
||||
if (!g) {
|
||||
LOGE("flurry_port_new failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGI("Flurry started, preset %d", preset);
|
||||
return (jlong) (intptr_t) g;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL NS(nativeCreateCustom)(JNIEnv *env, jclass clazz, jint streams,
|
||||
jint colour, jfloat thickness, jfloat speed,
|
||||
jfloat brightness)
|
||||
{
|
||||
(void) env; (void) clazz;
|
||||
|
||||
srandom((unsigned) time(NULL) ^ (unsigned) clock());
|
||||
|
||||
if (!fx_init()) {
|
||||
LOGE("GL compatibility layer failed to initialise");
|
||||
return 0;
|
||||
}
|
||||
|
||||
global_info_t *g = flurry_port_new_custom(streams, colour, thickness, speed, brightness);
|
||||
if (!g) {
|
||||
LOGE("flurry_port_new_custom failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGI("Flurry started, custom: streams=%d colour=%d thickness=%.2f speed=%.2f brightness=%.2f",
|
||||
streams, colour, (double) thickness, (double) speed, (double) brightness);
|
||||
return (jlong) (intptr_t) g;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL NS(nativeResize)(JNIEnv *env, jclass clazz, jlong handle, jint w, jint h)
|
||||
{
|
||||
(void) env; (void) clazz;
|
||||
if (handle) flurry_port_resize((global_info_t *) (intptr_t) handle, w, h);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL NS(nativeDraw)(JNIEnv *env, jclass clazz, jlong handle)
|
||||
{
|
||||
(void) env; (void) clazz;
|
||||
if (!handle) return JNI_FALSE;
|
||||
return flurry_port_draw((global_info_t *) (intptr_t) handle) ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL NS(nativeDestroy)(JNIEnv *env, jclass clazz, jlong handle)
|
||||
{
|
||||
(void) env; (void) clazz;
|
||||
if (!handle) return;
|
||||
|
||||
flurry_port_free((global_info_t *) (intptr_t) handle);
|
||||
fx_shutdown();
|
||||
}
|
||||
|
||||
/*
|
||||
* The context went away without us being able to tidy up -- the usual case when a wallpaper is
|
||||
* torn down. Forget the GL names instead of deleting them: the objects are already gone with
|
||||
* the context, and deleting a name in a context that no longer exists is undefined.
|
||||
*/
|
||||
JNIEXPORT void JNICALL NS(nativeContextLost)(JNIEnv *env, jclass clazz, jlong handle)
|
||||
{
|
||||
(void) env; (void) clazz;
|
||||
if (handle) flurry_port_free((global_info_t *) (intptr_t) handle);
|
||||
fx_lost();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* The Android environment for Calum Robinson's Flurry.
|
||||
*
|
||||
* Upstream this comes from xscreensaver: xlockmoreI.h pulls in the GL headers and the ModeInfo
|
||||
* plumbing, yarandom.h supplies the RNG. Neither exists here, and the parts Flurry actually
|
||||
* uses are small enough to state directly.
|
||||
*/
|
||||
#ifndef FLURRY_PORT_H
|
||||
#define FLURRY_PORT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h> /* gettimeofday, via xlockmoreI.h upstream */
|
||||
|
||||
#include "gl_compat.h"
|
||||
|
||||
/* Normally set by xscreensaver's configure. Bionic's gettimeofday takes two arguments like
|
||||
* every other POSIX system, so the one-argument branch in currentTime() would not compile. */
|
||||
#define GETTIMEOFDAY_TWO_ARGS 1
|
||||
|
||||
/* xscreensaver's yarandom.h: a float in [0, f). random() is bionic's, seeded in flurry_jni.c
|
||||
* -- the smoke is driven entirely by it, so an unseeded run would look identical every time. */
|
||||
#ifndef frand
|
||||
#define frand(f) ((float) ((double) (f) * ((double) random() / ((double) RAND_MAX + 1.0))))
|
||||
#endif
|
||||
|
||||
#endif /* FLURRY_PORT_H */
|
||||
@@ -0,0 +1,329 @@
|
||||
#include "gl_compat.h"
|
||||
|
||||
/*
|
||||
* Undo the redirection for this file.
|
||||
*
|
||||
* gl_compat.h rewrites glEnable/glDisable/glDrawArrays and friends into the fx_* entry points
|
||||
* so the Flurry sources need no edits -- but this file IMPLEMENTS those entry points, and it
|
||||
* has to be able to call the real GL underneath them. Without these undefs, fx_enable's own
|
||||
* glEnable(cap) expands to fx_enable(cap) and recurses forever. At -O2 that is a tail call and
|
||||
* becomes an infinite LOOP rather than a stack overflow, so it does not crash: the thread just
|
||||
* spins at 100% and nothing after it ever runs. The first glDisable in GLSetupRC was enough to
|
||||
* hang the whole renderer with no error anywhere.
|
||||
*/
|
||||
#undef glEnable
|
||||
#undef glDisable
|
||||
#undef glDrawArrays
|
||||
#undef glVertexPointer
|
||||
#undef glColorPointer
|
||||
#undef glTexCoordPointer
|
||||
#undef glEnableClientState
|
||||
#undef glDisableClientState
|
||||
#undef glColor4f
|
||||
#undef glColor3f
|
||||
#undef glRectd
|
||||
#undef glMatrixMode
|
||||
#undef glLoadIdentity
|
||||
#undef glOrtho
|
||||
#undef glAlphaFunc
|
||||
#undef glShadeModel
|
||||
#undef glTexEnvf
|
||||
#undef glDrawBuffer
|
||||
#undef glFinish
|
||||
|
||||
#include <android/log.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "Flurry", __VA_ARGS__)
|
||||
|
||||
/* Flurry draws at most NUMSMOKEPARTICLES quads in one call. Kept here rather than including
|
||||
* flurry.h so this file stays independent of it; the assert in fx_draw_arrays catches it if
|
||||
* the particle count ever grows past what the index buffer covers. */
|
||||
#define FX_MAX_QUADS 4096
|
||||
|
||||
static const char *kVert =
|
||||
"attribute vec2 aPos;\n"
|
||||
"attribute vec4 aColor;\n"
|
||||
"attribute vec2 aTex;\n"
|
||||
"uniform mat4 uProj;\n"
|
||||
"varying vec4 vColor;\n"
|
||||
"varying vec2 vTex;\n"
|
||||
"void main() {\n"
|
||||
" vColor = aColor;\n"
|
||||
" vTex = aTex;\n"
|
||||
" gl_Position = uProj * vec4(aPos, 0.0, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
/* mediump is deliberate: the smoke is additive and low contrast, highp costs real time on
|
||||
* mobile fragment hardware, and this runs behind a home screen. */
|
||||
static const char *kFrag =
|
||||
"precision mediump float;\n"
|
||||
"uniform sampler2D uTex;\n"
|
||||
"uniform int uUseTex;\n"
|
||||
"varying vec4 vColor;\n"
|
||||
"varying vec2 vTex;\n"
|
||||
"void main() {\n"
|
||||
" vec4 c = vColor;\n"
|
||||
" if (uUseTex == 1) c *= texture2D(uTex, vTex);\n"
|
||||
" gl_FragColor = c;\n"
|
||||
"}\n";
|
||||
|
||||
typedef struct {
|
||||
GLint size;
|
||||
GLenum type;
|
||||
GLsizei stride;
|
||||
const void *ptr;
|
||||
int enabled;
|
||||
} fx_array;
|
||||
|
||||
static struct {
|
||||
GLuint program;
|
||||
GLuint ibo;
|
||||
GLint aPos, aColor, aTex;
|
||||
GLint uProj, uTex, uUseTex;
|
||||
GLfloat proj[16];
|
||||
fx_array vertex, color, texcoord;
|
||||
GLfloat current_color[4];
|
||||
int ready;
|
||||
} fx;
|
||||
|
||||
static GLuint compile(GLenum type, const char *src)
|
||||
{
|
||||
GLuint sh = glCreateShader(type);
|
||||
if (!sh) return 0;
|
||||
|
||||
glShaderSource(sh, 1, &src, NULL);
|
||||
glCompileShader(sh);
|
||||
|
||||
GLint ok = 0;
|
||||
glGetShaderiv(sh, GL_COMPILE_STATUS, &ok);
|
||||
if (!ok) {
|
||||
char log[512];
|
||||
glGetShaderInfoLog(sh, sizeof(log), NULL, log);
|
||||
LOGE("shader compile failed: %s", log);
|
||||
glDeleteShader(sh);
|
||||
return 0;
|
||||
}
|
||||
return sh;
|
||||
}
|
||||
|
||||
int fx_init(void)
|
||||
{
|
||||
if (fx.ready) return 1;
|
||||
|
||||
memset(&fx, 0, sizeof(fx));
|
||||
|
||||
GLuint vs = compile(GL_VERTEX_SHADER, kVert);
|
||||
GLuint fs = compile(GL_FRAGMENT_SHADER, kFrag);
|
||||
if (!vs || !fs) return 0;
|
||||
|
||||
fx.program = glCreateProgram();
|
||||
glAttachShader(fx.program, vs);
|
||||
glAttachShader(fx.program, fs);
|
||||
glLinkProgram(fx.program);
|
||||
|
||||
GLint ok = 0;
|
||||
glGetProgramiv(fx.program, GL_LINK_STATUS, &ok);
|
||||
if (!ok) {
|
||||
char log[512];
|
||||
glGetProgramInfoLog(fx.program, sizeof(log), NULL, log);
|
||||
LOGE("program link failed: %s", log);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attached shaders are refcounted by the program and can go now. */
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
|
||||
fx.aPos = glGetAttribLocation(fx.program, "aPos");
|
||||
fx.aColor = glGetAttribLocation(fx.program, "aColor");
|
||||
fx.aTex = glGetAttribLocation(fx.program, "aTex");
|
||||
fx.uProj = glGetUniformLocation(fx.program, "uProj");
|
||||
fx.uTex = glGetUniformLocation(fx.program, "uTex");
|
||||
fx.uUseTex = glGetUniformLocation(fx.program, "uUseTex");
|
||||
|
||||
/* One static index buffer for every quad draw. GL_QUADS is (0,1,2,3) per quad in draw
|
||||
* order, so each becomes two triangles sharing the 0-2 diagonal. Built once because the
|
||||
* pattern never depends on the data, only on how many quads are drawn. */
|
||||
GLushort *idx = (GLushort *) malloc(sizeof(GLushort) * FX_MAX_QUADS * 6);
|
||||
if (!idx) return 0;
|
||||
|
||||
for (int q = 0; q < FX_MAX_QUADS; q++) {
|
||||
const GLushort base = (GLushort) (q * 4);
|
||||
GLushort *o = idx + q * 6;
|
||||
o[0] = base; o[1] = (GLushort)(base + 1); o[2] = (GLushort)(base + 2);
|
||||
o[3] = base; o[4] = (GLushort)(base + 2); o[5] = (GLushort)(base + 3);
|
||||
}
|
||||
|
||||
glGenBuffers(1, &fx.ibo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fx.ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * FX_MAX_QUADS * 6, idx, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
free(idx);
|
||||
|
||||
fx.ready = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fx_shutdown(void)
|
||||
{
|
||||
if (fx.program) glDeleteProgram(fx.program);
|
||||
if (fx.ibo) glDeleteBuffers(1, &fx.ibo);
|
||||
memset(&fx, 0, sizeof(fx));
|
||||
}
|
||||
|
||||
void fx_lost(void)
|
||||
{
|
||||
/* The context is already gone; deleting these names would be undefined. */
|
||||
memset(&fx, 0, sizeof(fx));
|
||||
}
|
||||
|
||||
void fx_ortho(float left, float right, float bottom, float top)
|
||||
{
|
||||
/* Column-major, near/far fixed at -1/1: Flurry is entirely 2D. */
|
||||
const float rl = right - left, tb = top - bottom;
|
||||
memset(fx.proj, 0, sizeof(fx.proj));
|
||||
fx.proj[0] = 2.0f / rl;
|
||||
fx.proj[5] = 2.0f / tb;
|
||||
fx.proj[10] = -1.0f;
|
||||
fx.proj[12] = -(right + left) / rl;
|
||||
fx.proj[13] = -(top + bottom) / tb;
|
||||
fx.proj[15] = 1.0f;
|
||||
}
|
||||
|
||||
static void set_array(fx_array *a, GLint size, GLenum type, GLsizei stride, const void *ptr)
|
||||
{
|
||||
a->size = size;
|
||||
a->type = type;
|
||||
a->stride = stride;
|
||||
a->ptr = ptr;
|
||||
}
|
||||
|
||||
void fx_vertex_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr) { set_array(&fx.vertex, size, type, stride, ptr); }
|
||||
void fx_color_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr) { set_array(&fx.color, size, type, stride, ptr); }
|
||||
void fx_texcoord_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr) { set_array(&fx.texcoord, size, type, stride, ptr); }
|
||||
|
||||
void fx_enable_client_state(GLenum cap)
|
||||
{
|
||||
if (cap == GL_VERTEX_ARRAY) fx.vertex.enabled = 1;
|
||||
else if (cap == GL_COLOR_ARRAY) fx.color.enabled = 1;
|
||||
else if (cap == GL_TEXTURE_COORD_ARRAY) fx.texcoord.enabled = 1;
|
||||
}
|
||||
|
||||
void fx_disable_client_state(GLenum cap)
|
||||
{
|
||||
if (cap == GL_VERTEX_ARRAY) fx.vertex.enabled = 0;
|
||||
else if (cap == GL_COLOR_ARRAY) fx.color.enabled = 0;
|
||||
else if (cap == GL_TEXTURE_COORD_ARRAY) fx.texcoord.enabled = 0;
|
||||
}
|
||||
|
||||
void fx_enable(GLenum cap)
|
||||
{
|
||||
/* GLES2 has no alpha test or lighting; passing either would set GL_INVALID_ENUM and the
|
||||
* error would then be blamed on whatever ran next. */
|
||||
/* GL_TEXTURE_2D as a capability is gone in GLES2 -- whether a sampler is used is decided by
|
||||
* the shader. Passing it sets GL_INVALID_ENUM, and the sticky error then gets blamed on
|
||||
* whatever ran next. */
|
||||
if (cap == GL_ALPHA_TEST || cap == GL_LIGHTING || cap == GL_TEXTURE_2D_ENABLE_COMPAT) return;
|
||||
glEnable(cap);
|
||||
}
|
||||
|
||||
void fx_disable(GLenum cap)
|
||||
{
|
||||
if (cap == GL_ALPHA_TEST || cap == GL_LIGHTING || cap == GL_TEXTURE_2D_ENABLE_COMPAT) return;
|
||||
glDisable(cap);
|
||||
}
|
||||
|
||||
static void bind(GLint loc, const fx_array *a)
|
||||
{
|
||||
if (loc < 0) return;
|
||||
|
||||
if (!a->enabled || !a->ptr) {
|
||||
glDisableVertexAttribArray((GLuint) loc);
|
||||
return;
|
||||
}
|
||||
|
||||
glEnableVertexAttribArray((GLuint) loc);
|
||||
glVertexAttribPointer((GLuint) loc, a->size, a->type, GL_FALSE, a->stride, a->ptr);
|
||||
}
|
||||
|
||||
void fx_color4f(float r, float g, float b, float a)
|
||||
{
|
||||
fx.current_color[0] = r;
|
||||
fx.current_color[1] = g;
|
||||
fx.current_color[2] = b;
|
||||
fx.current_color[3] = a;
|
||||
}
|
||||
|
||||
void fx_rect(float x0, float y0, float x1, float y1)
|
||||
{
|
||||
if (!fx.ready) return;
|
||||
|
||||
const GLfloat verts[8] = { x0, y0, x1, y0, x1, y1, x0, y1 };
|
||||
|
||||
glUseProgram(fx.program);
|
||||
glUniformMatrix4fv(fx.uProj, 1, GL_FALSE, fx.proj);
|
||||
glUniform1i(fx.uUseTex, 0);
|
||||
|
||||
if (fx.aColor >= 0) {
|
||||
glDisableVertexAttribArray((GLuint) fx.aColor);
|
||||
glVertexAttrib4fv((GLuint) fx.aColor, fx.current_color);
|
||||
}
|
||||
if (fx.aTex >= 0) glDisableVertexAttribArray((GLuint) fx.aTex);
|
||||
|
||||
if (fx.aPos >= 0) {
|
||||
glEnableVertexAttribArray((GLuint) fx.aPos);
|
||||
glVertexAttribPointer((GLuint) fx.aPos, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fx.ibo);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
/* The arrays the smoke set up are still recorded; the next fx_draw_arrays rebinds them. */
|
||||
}
|
||||
|
||||
void fx_draw_arrays(GLenum mode, GLint first, GLsizei count)
|
||||
{
|
||||
|
||||
if (!fx.ready || count <= 0) return;
|
||||
|
||||
glUseProgram(fx.program);
|
||||
glUniformMatrix4fv(fx.uProj, 1, GL_FALSE, fx.proj);
|
||||
glUniform1i(fx.uTex, 0);
|
||||
glUniform1i(fx.uUseTex, fx.texcoord.enabled ? 1 : 0);
|
||||
|
||||
bind(fx.aPos, &fx.vertex);
|
||||
bind(fx.aColor, &fx.color);
|
||||
bind(fx.aTex, &fx.texcoord);
|
||||
|
||||
/* An attribute the shader declares but no array feeds still needs a value, or the draw
|
||||
* reads whatever the last one left behind. */
|
||||
if (fx.aColor >= 0 && (!fx.color.enabled || !fx.color.ptr))
|
||||
glVertexAttrib4f((GLuint) fx.aColor, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
if (mode != GL_QUADS) {
|
||||
glDrawArrays(mode, first, count);
|
||||
return;
|
||||
}
|
||||
|
||||
/* GL_QUADS, the only mode Flurry actually uses. `first` is always 0 upstream; honouring a
|
||||
* non-zero one would mean an index buffer per offset, so it is rejected loudly instead of
|
||||
* being silently drawn wrong. */
|
||||
if (first != 0) {
|
||||
LOGE("fx_draw_arrays: GL_QUADS with first=%d is not supported", first);
|
||||
return;
|
||||
}
|
||||
|
||||
GLsizei quads = count / 4;
|
||||
if (quads > FX_MAX_QUADS) {
|
||||
LOGE("fx_draw_arrays: %d quads exceeds the %d the index buffer covers; clamping",
|
||||
quads, FX_MAX_QUADS);
|
||||
quads = FX_MAX_QUADS;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fx.ibo);
|
||||
glDrawElements(GL_TRIANGLES, quads * 6, GL_UNSIGNED_SHORT, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Just enough OpenGL 1.x for Flurry, implemented on GLES2.
|
||||
*
|
||||
* Flurry is from 2002 and draws the only way that existed then: client-side vertex arrays
|
||||
* (glVertexPointer and friends), a fixed-function ortho projection, and GL_QUADS. GLES2 has
|
||||
* none of those. Rather than rewrite the renderer -- and lose the property that this is
|
||||
* recognisably Calum Robinson's code -- the calls are redirected here and answered with a
|
||||
* shader, an index buffer, and a matrix uniform.
|
||||
*
|
||||
* The surface is small because the smoke is the only thing drawn: DRAW_SPARKS is never
|
||||
* defined upstream, so the immediate-mode spark path (glBegin/glVertex2f, matrix stack) is
|
||||
* dead code and is not emulated. If sparks are ever switched on, this file needs a lot more
|
||||
* in it.
|
||||
*/
|
||||
#ifndef FLURRY_GL_COMPAT_H
|
||||
#define FLURRY_GL_COMPAT_H
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* GL 1.x names the sources use that GLES2 does not define. */
|
||||
#ifndef GL_QUADS
|
||||
#define GL_QUADS 0x0007
|
||||
#endif
|
||||
#ifndef GL_QUAD_STRIP
|
||||
#define GL_QUAD_STRIP 0x0008
|
||||
#endif
|
||||
#ifndef GL_ALPHA_TEST
|
||||
#define GL_ALPHA_TEST 0x0BC0
|
||||
#endif
|
||||
#ifndef GL_LIGHTING
|
||||
#define GL_LIGHTING 0x0B50
|
||||
#endif
|
||||
#ifndef GL_VERTEX_ARRAY
|
||||
#define GL_VERTEX_ARRAY 0x8074
|
||||
#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_LINEAR_MIPMAP_NEAREST
|
||||
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
|
||||
#endif
|
||||
#ifndef GL_TEXTURE_2D_ENABLE_COMPAT
|
||||
#define GL_TEXTURE_2D_ENABLE_COMPAT 0x0DE1
|
||||
#endif
|
||||
|
||||
/* Lifetime. fx_init needs a current context; fx_lost forgets GL names without touching them,
|
||||
* for when the context has already gone away underneath us. */
|
||||
int fx_init(void);
|
||||
void fx_shutdown(void);
|
||||
void fx_lost(void);
|
||||
|
||||
/* Replaces the projection matrix calls. */
|
||||
void fx_ortho(float left, float right, float bottom, float top);
|
||||
|
||||
/* Array + draw emulation. */
|
||||
void fx_vertex_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr);
|
||||
void fx_color_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr);
|
||||
void fx_texcoord_pointer(GLint size, GLenum type, GLsizei stride, const void *ptr);
|
||||
void fx_enable_client_state(GLenum cap);
|
||||
void fx_disable_client_state(GLenum cap);
|
||||
void fx_draw_arrays(GLenum mode, GLint first, GLsizei count);
|
||||
|
||||
/* glEnable/glDisable filtered: GLES2 rejects GL_ALPHA_TEST and GL_LIGHTING outright, and an
|
||||
* invalid enum here would leave a sticky GL error for everything after it. */
|
||||
void fx_enable(GLenum cap);
|
||||
void fx_disable(GLenum cap);
|
||||
|
||||
/* The per-frame fade. Flurry darkens the whole screen with a translucent black rect before
|
||||
* drawing, which is what gives the smoke its trails -- so this is not decoration, it is the
|
||||
* effect. glRectd and the current-colour state it reads are both gone in GLES2. */
|
||||
void fx_color4f(float r, float g, float b, float a);
|
||||
void fx_rect(float x0, float y0, float x1, float y1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The redirection itself. Included by the Flurry sources ahead of any GL use. */
|
||||
#define glVertexPointer fx_vertex_pointer
|
||||
#define glColorPointer fx_color_pointer
|
||||
#define glTexCoordPointer fx_texcoord_pointer
|
||||
#define glEnableClientState fx_enable_client_state
|
||||
#define glDisableClientState fx_disable_client_state
|
||||
#define glDrawArrays fx_draw_arrays
|
||||
#define glEnable fx_enable
|
||||
#define glDisable fx_disable
|
||||
|
||||
/* No analogue and nothing depends on the effect. */
|
||||
#define glAlphaFunc(func, ref) ((void) 0)
|
||||
#define glShadeModel(mode) ((void) 0)
|
||||
#define glMatrixMode(mode) ((void) 0)
|
||||
#define glLoadIdentity() ((void) 0)
|
||||
#define glTexEnvf(t, p, v) ((void) 0)
|
||||
#define glOrtho(l, r, b, t, n, f) fx_ortho((float) (l), (float) (r), (float) (b), (float) (t))
|
||||
#define glColor4f fx_color4f
|
||||
#define glColor3f(r, g, b) fx_color4f((r), (g), (b), 1.0f)
|
||||
#define glRectd(x0, y0, x1, y1) fx_rect((float) (x0), (float) (y0), (float) (x1), (float) (y1))
|
||||
#define glDrawBuffer(mode) ((void) 0)
|
||||
#define glFinish() ((void) 0)
|
||||
|
||||
#endif /* FLURRY_GL_COMPAT_H */
|
||||
@@ -93,6 +93,7 @@ struct RPCSXApi {
|
||||
bool (*saveStateToSlot)(unsigned int slot);
|
||||
bool (*loadStateFromSlot)(unsigned int slot);
|
||||
bool (*hasStateInSlot)(unsigned int slot);
|
||||
bool (*deleteStateFromSlot)(unsigned int slot);
|
||||
std::string (*patchEngineVersion)();
|
||||
int (*patchesImport)(std::string_view content);
|
||||
std::string (*patchesList)(std::string_view serial);
|
||||
@@ -204,6 +205,7 @@ struct RPCSXLibrary : RPCSXApi {
|
||||
result.saveStateToSlot = reinterpret_cast<decltype(saveStateToSlot)>(dlsym(handle, "_rpcsx_saveStateToSlot"));
|
||||
result.loadStateFromSlot = reinterpret_cast<decltype(loadStateFromSlot)>(dlsym(handle, "_rpcsx_loadStateFromSlot"));
|
||||
result.hasStateInSlot = reinterpret_cast<decltype(hasStateInSlot)>(dlsym(handle, "_rpcsx_hasStateInSlot"));
|
||||
result.deleteStateFromSlot = reinterpret_cast<decltype(deleteStateFromSlot)>(dlsym(handle, "_rpcsx_deleteStateFromSlot"));
|
||||
result.patchEngineVersion = reinterpret_cast<decltype(patchEngineVersion)>(dlsym(handle, "_rpcsx_patchEngineVersion"));
|
||||
result.patchesImport = reinterpret_cast<decltype(patchesImport)>(dlsym(handle, "_rpcsx_patchesImport"));
|
||||
result.patchesList = reinterpret_cast<decltype(patchesList)>(dlsym(handle, "_rpcsx_patchesList"));
|
||||
@@ -1007,6 +1009,15 @@ Java_net_rpcsx_RPCSX_hasStateInSlot(JNIEnv *, jobject, jint slot) {
|
||||
return rpcsxLib.hasStateInSlot(static_cast<unsigned int>(slot));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_net_rpcsx_RPCSX_deleteStateFromSlot(JNIEnv *, jobject, jint slot) {
|
||||
if (rpcsxLib.deleteStateFromSlot == nullptr || slot < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return rpcsxLib.deleteStateFromSlot(static_cast<unsigned int>(slot));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Patches
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user