diff options
author | Adam Lesinski <adamlesinski@google.com> | 2010-10-27 17:54:33 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2010-10-28 17:19:45 -0700 |
commit | 26122dc2e3971577fd8bbcfbac2140d73b817377 (patch) | |
tree | f98f502b19e13832335fb79a2be1b4bf62c80eb9 /src | |
parent | 2f2fedfca6446f2a407e2b84a4869282bba221e5 (diff) | |
download | android_packages_wallpapers_HoloSpiral-26122dc2e3971577fd8bbcfbac2140d73b817377.tar.gz android_packages_wallpapers_HoloSpiral-26122dc2e3971577fd8bbcfbac2140d73b817377.tar.bz2 android_packages_wallpapers_HoloSpiral-26122dc2e3971577fd8bbcfbac2140d73b817377.zip |
First version of Holo Spiral
Change-Id: Id298aa928e1590e8246f53526eb065956bbdc6f4
Diffstat (limited to 'src')
5 files changed, 729 insertions, 0 deletions
diff --git a/src/com/android/wallpaper/holospiral/HoloSpiralRS.java b/src/com/android/wallpaper/holospiral/HoloSpiralRS.java new file mode 100644 index 0000000..73677ff --- /dev/null +++ b/src/com/android/wallpaper/holospiral/HoloSpiralRS.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wallpaper.holospiral; + +import com.android.wallpaper.holospiral.ScriptC_holo_spiral; +import com.android.wallpaper.holospiral.ScriptField_VertexColor_s; +import com.android.wallpaper.holospiral.ScriptField_VertexShaderConstants_s; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.os.Bundle; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.Float3; +import android.renderscript.Float4; +import android.renderscript.Mesh; +import android.renderscript.Primitive; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.RenderScriptGL; +import android.renderscript.Sampler; + +public class HoloSpiralRS { + private static final String LOG_TAG = "HoloSpiralRS"; + private static final float MAX_POINT_SIZE = 75.0f; + private static final float NEAR_PLANE = 1.0f; + private static final float FAR_PLANE = 55.0f; + + private static final int NUM_INNER_POINTS = 100; + private static final float INNER_SPIRAL_DEPTH = 50.0f; + private static final float INNER_RADIUS = 5.0f; + private static final float INNER_SEPARATION_DEG = 23.0f; + + private static final int NUM_OUTER_POINTS = 50; + private static final float OUTER_SPIRAL_DEPTH = 30.0f; + private static final float OUTER_RADIUS = 10.0f; + private static final float OUTER_SEPARATION_DEG = 23.0f; + + /* Colors */ + private static final int POINTS_COLOR_BLUE = Color.argb(179, 0, 0, 255); + private static final int POINTS_COLOR_GREEN = Color.argb(179, 0, 255, 255); + private static final int POINTS_COLOR_AQUA = Color.argb(179, 38, 120, 148); + private static final int BG_COLOR_BLACK = Color.argb(255, 8, 19, 46); + private static final int BG_COLOR_BLUE = Color.argb(255, 26, 56, 99); + + private ScriptC_holo_spiral mScript; + private RenderScriptGL mRS = null; + private Resources mResources = null; + + public HoloSpiralRS(RenderScriptGL renderer, Resources resources) { + init(renderer, resources); + } + + public void init(RenderScriptGL renderer, Resources resources) { + mRS = renderer; + mResources = resources; + createScript(); + } + + public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) { + mScript.set_gXOffset(xOffset); + } + + public Bundle onCommand(String action, int x, int y, int z, Bundle extras, + boolean resultRequested) { + return null; + } + + public void start() { + mRS.contextBindRootScript(mScript); + } + + public void stop() { + mRS.contextBindRootScript(null); + } + + public void resize(int width, int height) { + mScript.invoke_resize(width, height); + } + + private void createScript() { + mScript = new ScriptC_holo_spiral(mRS, mResources, R.raw.holo_spiral, true); + mScript.set_gNearPlane(NEAR_PLANE); + mScript.set_gFarPlane(FAR_PLANE); + + createVertexPrograms(); + createFragmentPrograms(); + createStorePrograms(); + + createPointGeometry(); + createBackgroundMesh(); + createTextures(); + } + + private void createVertexPrograms() { + ScriptField_VertexShaderConstants_s vertexShaderConstants = + new ScriptField_VertexShaderConstants_s(mRS, 1); + mScript.bind_gVSConstants(vertexShaderConstants); + vertexShaderConstants.set_maxPointSize(0, MAX_POINT_SIZE, false); + vertexShaderConstants.copyAll(); + + ProgramVertex.ShaderBuilder backgroundBuilder = new ProgramVertex.ShaderBuilder(mRS); + backgroundBuilder.setShader(mResources, R.raw.vertex_background); + backgroundBuilder.addInput(ScriptField_VertexColor_s.createElement(mRS)); + ProgramVertex programVertexBackground = backgroundBuilder.create(); + mScript.set_gPVBackground(programVertexBackground); + + ProgramVertex.ShaderBuilder geometryBuilder = new ProgramVertex.ShaderBuilder(mRS); + geometryBuilder.setShader(mResources, R.raw.vertex_geometry); + geometryBuilder.addConstant(vertexShaderConstants.getAllocation().getType()); + geometryBuilder.addInput(ScriptField_VertexColor_s.createElement(mRS)); + ProgramVertex programVertexGeometry = geometryBuilder.create(); + programVertexGeometry.bindConstants(vertexShaderConstants.getAllocation(), 0); + mScript.set_gPVGeometry(programVertexGeometry); + } + + private void createFragmentPrograms() { + ProgramFragment.ShaderBuilder backgroundBuilder = new ProgramFragment.ShaderBuilder(mRS); + backgroundBuilder.setShader(mResources, R.raw.fragment_background); + ProgramFragment programFragmentBackground = backgroundBuilder.create(); + mScript.set_gPFBackground(programFragmentBackground); + + ProgramFragment.ShaderBuilder geometryBuilder = new ProgramFragment.ShaderBuilder(mRS); + geometryBuilder.setShader(mResources, R.raw.fragment_geometry); + geometryBuilder.setTextureCount(1); + ProgramFragment programFragmentGeometry = geometryBuilder.create(); + programFragmentGeometry.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); + mScript.set_gPFGeometry(programFragmentGeometry); + } + + private void createStorePrograms() { + ProgramStore.Builder builder = new ProgramStore.Builder(mRS); + builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA, + ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA); + mScript.set_gPSGeometry(builder.create()); + builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ZERO); + builder.setDitherEnable(true); + mScript.set_gPSBackground(builder.create()); + } + + private void createPointGeometry() { + ScriptField_VertexColor_s innerPoints = + new ScriptField_VertexColor_s(mRS, NUM_INNER_POINTS); + generateSpiral(innerPoints, INNER_SPIRAL_DEPTH, INNER_RADIUS, INNER_SEPARATION_DEG, + POINTS_COLOR_BLUE, POINTS_COLOR_GREEN); + + Mesh.AllocationBuilder innerPointBuilder = new Mesh.AllocationBuilder(mRS); + innerPointBuilder.addIndexType(Primitive.POINT); + innerPointBuilder.addVertexAllocation(innerPoints.getAllocation()); + mScript.set_gInnerGeometry(innerPointBuilder.create()); + + ScriptField_VertexColor_s outerPoints = + new ScriptField_VertexColor_s(mRS, NUM_OUTER_POINTS); + generateSpiral(outerPoints, OUTER_SPIRAL_DEPTH, OUTER_RADIUS, OUTER_SEPARATION_DEG, + POINTS_COLOR_AQUA, POINTS_COLOR_AQUA); + + Mesh.AllocationBuilder outerPointBuilder = new Mesh.AllocationBuilder(mRS); + outerPointBuilder.addIndexType(Primitive.POINT); + outerPointBuilder.addVertexAllocation(outerPoints.getAllocation()); + mScript.set_gOuterGeometry(outerPointBuilder.create()); + } + + private void createTextures() { + Bitmap bmp = BitmapFactory.decodeResource( + mResources, R.drawable.points_red_green, null); + Allocation pointTexture = Allocation.createFromBitmap( + mRS, bmp, Element.RGB_565(mRS), false); + pointTexture.uploadToTexture(0); + mScript.set_gPointTexture(pointTexture); + } + + private void createBackgroundMesh() { + ScriptField_VertexColor_s fullQuad = new ScriptField_VertexColor_s(mRS, 4); + + Float3 topLeft = new Float3(-1.0f, 1.0f, 0.0f); + Float3 bottomLeft = new Float3(-1.0f, -1.0f, 0.0f); + Float3 topRight = new Float3(1.0f, 1.0f, 0.0f); + Float3 bottomRight = new Float3(1.0f, -1.0f, 0.0f); + + fullQuad.set_position(0, topLeft, false); + fullQuad.set_color(0, convertColor(BG_COLOR_BLUE), false); + + fullQuad.set_position(1, bottomLeft, false); + fullQuad.set_color(1, convertColor(BG_COLOR_BLACK), false); + + fullQuad.set_position(2, topRight, false); + fullQuad.set_color(2, convertColor(BG_COLOR_BLUE), false); + + fullQuad.set_position(3, bottomRight, false); + fullQuad.set_color(3, convertColor(BG_COLOR_BLACK), false); + + fullQuad.copyAll(); + + Mesh.AllocationBuilder backgroundBuilder = new Mesh.AllocationBuilder(mRS); + backgroundBuilder.addIndexType(Primitive.TRIANGLE_STRIP); + backgroundBuilder.addVertexAllocation(fullQuad.getAllocation()); + mScript.set_gBackgroundMesh(backgroundBuilder.create()); + } + + private void generateSpiral(ScriptField_VertexColor_s points, float depth, float radius, + float separationDegrees, int primaryColor, int secondaryColor) { + + float separationRads = (separationDegrees / 360.0f) * 2 * (float) Math.PI; + int size = points.getAllocation().getType().getX(); + + float halfDepth = depth / 2.0f; + float radians = 0.0f; + + Float4 primary = convertColor(primaryColor); + Float4 secondary = convertColor(secondaryColor); + + for (int i = 0; i < size; i++) { + float percentage = (float) i / (float) size; + Float3 position = new Float3(radius * (float) Math.cos(radians), + radius * (float) Math.sin(radians), (percentage * depth) - halfDepth); + + float r = (float) Math.sin(radians / 2.0f); + + Float4 color = new Float4(); + color.x = primary.x + ((secondary.x - primary.x) * r); + color.y = primary.y + ((secondary.y - primary.y) * r); + color.z = primary.z + ((secondary.z - primary.z) * r); + color.w = primary.w + ((secondary.w - primary.w) * r); + + points.set_position(i, position, false); + points.set_color(i, color, false); + + radians += separationRads; + int multiplier = (int) (radians / (2.0f * (float) Math.PI)); + radians -= multiplier * 2.0f * (float) Math.PI; + } + + points.copyAll(); + } + + private static Float4 convertColor(int color) { + float red = Color.red(color) / 255.0f; + float green = Color.green(color) / 255.0f; + float blue = Color.blue(color) / 255.0f; + float alpha = Color.alpha(color) / 255.0f; + return new Float4(red, green, blue, alpha); + } +} diff --git a/src/com/android/wallpaper/holospiral/HoloSpiralTestActivity.java b/src/com/android/wallpaper/holospiral/HoloSpiralTestActivity.java new file mode 100644 index 0000000..e2bef47 --- /dev/null +++ b/src/com/android/wallpaper/holospiral/HoloSpiralTestActivity.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wallpaper.holospiral; + +import android.app.Activity; +import android.os.Bundle; + +public class HoloSpiralTestActivity extends Activity { + private HoloSpiralView mView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mView = new HoloSpiralView(this); + setContentView(mView); + } + + @Override + public void onResume() { + super.onResume(); + mView.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + mView.onPause(); + } +} diff --git a/src/com/android/wallpaper/holospiral/HoloSpiralView.java b/src/com/android/wallpaper/holospiral/HoloSpiralView.java new file mode 100644 index 0000000..2a8e305 --- /dev/null +++ b/src/com/android/wallpaper/holospiral/HoloSpiralView.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wallpaper.holospiral; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; +import android.view.MotionEvent; +import android.view.Surface; +import android.view.SurfaceHolder; + +public class HoloSpiralView extends RSSurfaceView { + private static final String LOG_TAG = "HoloRSView"; + private boolean mDragging = false; + private float mStartX = 0; + private float mCurrentPosition = 0; + private float mWallpaperWidth = 0; + + public HoloSpiralView(Context context) { + super(context); + } + + private RenderScriptGL mRenderScript = null; + private HoloSpiralRS mWallpaperRS = null; + + public void destroyRenderer() { + if (mWallpaperRS != null) { + mWallpaperRS.stop(); + mWallpaperRS = null; + } + + if (mRenderScript != null) { + mRenderScript.contextSetSurface(0, 0, null); + mRenderScript = null; + destroyRenderScript(); + } + } + + @Override + public void surfaceCreated(SurfaceHolder surfaceHolder) { + super.surfaceCreated(surfaceHolder); + + Surface surface = null; + while (surface == null) { + surface = surfaceHolder.getSurface(); + } + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + mRenderScript = createRenderScript(sc); + mRenderScript.contextSetPriority(RenderScript.Priority.LOW); + + surfaceHolder.setSizeFromLayout(); + surfaceHolder.setFormat(PixelFormat.RGBA_8888); + } + + @Override + public void surfaceDestroyed(SurfaceHolder surfaceHolder) { + super.surfaceDestroyed(surfaceHolder); + destroyRenderer(); + } + + @Override + public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) { + super.surfaceChanged(surfaceHolder, format, width, height); + if (mRenderScript != null) { + mRenderScript.contextSetSurface(width, height, surfaceHolder.getSurface()); + } + + if (mWallpaperRS == null) { + mWallpaperRS = new HoloSpiralRS(mRenderScript, getResources()); + mWallpaperRS.start(); + } + + mWallpaperRS.resize(width, height); + mWallpaperWidth = width; + } + + @Override + public void onResume() { + super.onResume(); + if (mWallpaperRS != null) { + mWallpaperRS.start(); + } + } + + @Override + public void onPause() { + super.onPause(); + if (mWallpaperRS != null) { + mWallpaperRS.stop(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + destroyRenderer(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getActionIndex() == 0) { + float realPosition = mCurrentPosition + (event.getX() - mStartX); + if (realPosition < 0.0f) { + realPosition = 0.0f; + } else if (realPosition > mWallpaperWidth * 4) { + realPosition = mWallpaperWidth * 4; + } + + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + mDragging = true; + mStartX = event.getX(0); + } else if (event.getActionMasked() == MotionEvent.ACTION_UP) { + mDragging = false; + mCurrentPosition = realPosition; + } else if (mDragging) { + float ratio = realPosition / (mWallpaperWidth * 4); + mWallpaperRS.setOffset(ratio, 0, 0, 0); + } + return true; + } + return false; + } +} diff --git a/src/com/android/wallpaper/holospiral/HoloSpiralWallpaper.java b/src/com/android/wallpaper/holospiral/HoloSpiralWallpaper.java new file mode 100644 index 0000000..90e4630 --- /dev/null +++ b/src/com/android/wallpaper/holospiral/HoloSpiralWallpaper.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wallpaper.holospiral; + +import android.graphics.PixelFormat; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; +import android.service.wallpaper.WallpaperService; +import android.view.Surface; +import android.view.SurfaceHolder; + +public class HoloSpiralWallpaper extends WallpaperService { + + @Override + public Engine onCreateEngine() { + return new RenderScriptEngine(); + } + + private class RenderScriptEngine extends Engine { + private RenderScriptGL mRenderScript = null; + private HoloSpiralRS mWallpaperRS = null; + + @Override + public void onCreate(SurfaceHolder surfaceHolder) { + super.onCreate(surfaceHolder); + setTouchEventsEnabled(true); + surfaceHolder.setSizeFromLayout(); + surfaceHolder.setFormat(PixelFormat.RGBA_8888); + } + + @Override + public void onDestroy() { + super.onDestroy(); + destroyRenderer(); + } + + public void destroyRenderer() { + if (mWallpaperRS != null) { + mWallpaperRS.stop(); + mWallpaperRS = null; + } + + if (mRenderScript != null) { + mRenderScript.contextSetSurface(0, 0, null); + mRenderScript.destroy(); + mRenderScript = null; + } + } + + @Override + public void onSurfaceCreated(SurfaceHolder surfaceHolder) { + super.onSurfaceCreated(surfaceHolder); + Surface surface = null; + while (surface == null) { + surface = surfaceHolder.getSurface(); + } + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + mRenderScript = new RenderScriptGL(sc); + mRenderScript.contextSetPriority(RenderScript.Priority.LOW); + } + + @Override + public void onSurfaceDestroyed(SurfaceHolder surfaceHolder) { + super.onSurfaceDestroyed(surfaceHolder); + destroyRenderer(); + } + + @Override + public void onSurfaceChanged(SurfaceHolder surfaceHolder, int format, + int width, int height) { + super.onSurfaceChanged(surfaceHolder, format, width, height); + + if (mRenderScript != null) { + mRenderScript.contextSetSurface(width, height, surfaceHolder.getSurface()); + } + + if (mWallpaperRS == null) { + mWallpaperRS = new HoloSpiralRS(mRenderScript, getResources()); + mWallpaperRS.start(); + } + + mWallpaperRS.resize(width, height); + } + + @Override + public Bundle onCommand(String action, int x, int y, int z, Bundle extras, + boolean resultRequested) { + if (mWallpaperRS != null) { + return mWallpaperRS.onCommand(action, x, y, z, extras, resultRequested); + } + return null; + } + + @Override + public void onVisibilityChanged(boolean visible) { + super.onVisibilityChanged(visible); + if (mWallpaperRS != null) { + if (visible) { + mWallpaperRS.start(); + } else { + mWallpaperRS.stop(); + } + } + } + + @Override + public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, + float yOffsetStep, int xPixelOffset, int yPixelOffset) { + mWallpaperRS.setOffset(xOffset, yOffset, xPixelOffset, yPixelOffset); + } + } +} diff --git a/src/com/android/wallpaper/holospiral/holo_spiral.rs b/src/com/android/wallpaper/holospiral/holo_spiral.rs new file mode 100644 index 0000000..d0c77b0 --- /dev/null +++ b/src/com/android/wallpaper/holospiral/holo_spiral.rs @@ -0,0 +1,158 @@ +// Copyright (C) 2010 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma version(1) + +#pragma rs java_package_name(com.android.wallpaper.holospiral) + +#include "rs_graphics.rsh" + +#pragma rs export_func(resize) + +#define FOV 60.0f +#define SPIRAL_ROTATE_SPEED 15.0f +#define INNER_ROTATE_SPEED 1.5f +#define OUTER_ROTATE_SPEED 0.5f + +// Vertex Shaders +rs_program_vertex gPVBackground; +rs_program_vertex gPVGeometry; + +// Fragment Shaders +rs_program_fragment gPFBackground; +rs_program_fragment gPFGeometry; + +// Blending and Depth testing +rs_program_store gPSBackground; +rs_program_store gPSGeometry; + +// Meshes +rs_mesh gInnerGeometry; +rs_mesh gOuterGeometry; +rs_mesh gBackgroundMesh; + +// Matrices +static rs_matrix4x4 gProjectionMatrix; +static rs_matrix4x4 gTransformedModelView; + +// Textures +rs_allocation gPointTexture; + +// Misc fields +float gXOffset; +float gNearPlane; +float gFarPlane; + +// User defined data types +typedef struct VertexShaderConstants_s { + rs_matrix4x4 modelViewProj; + float maxPointSize; + float farPlane; +} VertexShaderConstants; +VertexShaderConstants* gVSConstants; + +typedef struct VertexColor_s { + float3 position; + float4 color; +} VertexColor; +VertexColor* VertexColor_s_dummy; + +static float lastTime; +static float gInnerRotateAngle; +static float gOuterRotateAngle; +static float gWidth; +static float gHeight; + +static float modulo360(float val) { + static const INVERSE_360 = 1.0f / 360.0f; + int multiplier = (int)(val * INVERSE_360); + return val - (multiplier * 360.0f); +} + +static void drawBackground() { + rsgBindProgramVertex(gPVBackground); + rsgBindProgramFragment(gPFBackground); + rsgBindProgramStore(gPSBackground); + + rsgDrawMesh(gBackgroundMesh); +} + +static void drawGeometry(float dt) { + rsgBindProgramVertex(gPVGeometry); + rsgBindProgramFragment(gPFGeometry); + rsgBindProgramStore(gPSGeometry); + + rsgBindTexture(gPFGeometry, 0, gPointTexture); + + rs_matrix4x4 modelView; + rs_matrix4x4 rotateModelView; + + rsMatrixLoad(&modelView, &gTransformedModelView); + rsMatrixRotate(&modelView, gXOffset * -SPIRAL_ROTATE_SPEED, 0.0f, 1.0f, 0.0f); + + rsMatrixLoad(&rotateModelView, &modelView); + { + rsMatrixRotate(&rotateModelView, -gOuterRotateAngle, 0.0f, 0.0f, 1.0f); + rsMatrixLoadMultiply(&gVSConstants->modelViewProj, &gProjectionMatrix, &rotateModelView); + + // Wrap the rotation so we don't go past 360 + gOuterRotateAngle = modulo360(gOuterRotateAngle + (dt * OUTER_ROTATE_SPEED)); + + rsgDrawMesh(gOuterGeometry); + } + + rsMatrixLoad(&rotateModelView, &modelView); + { + rsMatrixRotate(&rotateModelView, gInnerRotateAngle, 0.0f, 0.0f, 1.0f); + rsMatrixLoadMultiply(&gVSConstants->modelViewProj, &gProjectionMatrix, &rotateModelView); + + // Wrap the rotation so we don't go past 360 + gInnerRotateAngle = modulo360(gInnerRotateAngle + (dt * INNER_ROTATE_SPEED)); + + rsgDrawMesh(gInnerGeometry); + } +} + +void resize(float width, float height) { + gWidth = width; + gHeight = height; + gVSConstants->farPlane = gFarPlane; + rsMatrixLoadPerspective(&gProjectionMatrix, FOV, gWidth / gHeight, gNearPlane, gFarPlane); +} + +void init() { + gInnerRotateAngle = 0.0f; + gOuterRotateAngle = 0.0f; + + gXOffset = 0.0f; + lastTime = rsUptimeMillis(); + + // Pre-calculate some fixed transformations + rsMatrixLoadIdentity(&gTransformedModelView); + rsMatrixTranslate(&gTransformedModelView, -3.0f, -5.0f, -18.0f); + rsMatrixRotate(&gTransformedModelView, 20.0f, 0.0f, 1.0f, 0.0f); + rsMatrixRotate(&gTransformedModelView, -10.0f, 1.0f, 0.0f, 0.0f); +} + +int root(int launchID) { + float now = rsUptimeMillis(); + float elapsed = (now - lastTime) * 0.001f; + lastTime = now; + + drawBackground(); + drawGeometry(elapsed); + + // Around 14 FPS + return 70; +} |