Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2009 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.wallpaper.grass; |
| 18 | |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 19 | import android.renderscript.Sampler; |
| 20 | import static android.renderscript.ProgramFragment.EnvMode.*; |
| 21 | import static android.renderscript.ProgramStore.DepthFunc.*; |
| 22 | import static android.renderscript.ProgramStore.BlendSrcFunc; |
| 23 | import static android.renderscript.ProgramStore.BlendDstFunc; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 24 | import android.renderscript.ProgramFragment; |
| 25 | import android.renderscript.ProgramStore; |
| 26 | import android.renderscript.Allocation; |
| 27 | import android.renderscript.ProgramVertex; |
| 28 | import static android.renderscript.Element.*; |
| 29 | import static android.util.MathUtils.*; |
| 30 | import android.renderscript.ScriptC; |
| 31 | import android.renderscript.Type; |
| 32 | import android.renderscript.Dimension; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 33 | import android.renderscript.Element; |
| 34 | import android.renderscript.SimpleMesh; |
| 35 | import android.renderscript.Primitive; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 36 | import static android.renderscript.Sampler.Value.*; |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 37 | import android.content.Context; |
| 38 | import android.content.IntentFilter; |
| 39 | import android.content.Intent; |
| 40 | import android.content.BroadcastReceiver; |
| 41 | import android.location.LocationManager; |
| 42 | import android.location.LocationListener; |
| 43 | import android.location.Location; |
| 44 | import android.os.Bundle; |
| 45 | import android.text.format.Time; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 46 | import com.android.wallpaper.R; |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 47 | import com.android.wallpaper.RenderScriptScene; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 48 | |
| 49 | import java.util.TimeZone; |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 50 | import java.util.Calendar; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 51 | |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 52 | class GrassRS extends RenderScriptScene { |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 53 | private static final int LOCATION_UPDATE_MIN_TIME = 60 * 60 * 1000; // 1 hour |
| 54 | private static final int LOCATION_UPDATE_MIN_DISTANCE = 150 * 1000; // 150 km |
| 55 | |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 56 | private static final float TESSELATION = 0.5f; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 57 | private static final int TEXTURES_COUNT = 5; |
| 58 | |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 59 | private static final int RSID_STATE = 0; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 60 | private static final int RSID_BLADES = 1; |
| 61 | private static final int BLADES_COUNT = 200; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 62 | private static final int BLADE_STRUCT_FIELDS_COUNT = 13; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 63 | private static final int BLADE_STRUCT_ANGLE = 0; |
| 64 | private static final int BLADE_STRUCT_SIZE = 1; |
| 65 | private static final int BLADE_STRUCT_XPOS = 2; |
| 66 | private static final int BLADE_STRUCT_YPOS = 3; |
| 67 | private static final int BLADE_STRUCT_OFFSET = 4; |
| 68 | private static final int BLADE_STRUCT_SCALE = 5; |
| 69 | private static final int BLADE_STRUCT_LENGTHX = 6; |
| 70 | private static final int BLADE_STRUCT_LENGTHY = 7; |
| 71 | private static final int BLADE_STRUCT_HARDNESS = 8; |
| 72 | private static final int BLADE_STRUCT_H = 9; |
| 73 | private static final int BLADE_STRUCT_S = 10; |
| 74 | private static final int BLADE_STRUCT_B = 11; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 75 | private static final int BLADE_STRUCT_TURBULENCEX = 12; |
| 76 | |
| 77 | private static final int RSID_BLADES_BUFFER = 2; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 78 | |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 79 | @SuppressWarnings({ "FieldCanBeLocal" }) |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 80 | private ProgramFragment mPfBackground; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 81 | @SuppressWarnings({ "FieldCanBeLocal" }) |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 82 | private ProgramStore mPfsBackground; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 83 | @SuppressWarnings({ "FieldCanBeLocal" }) |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 84 | private ProgramVertex mPvBackground; |
Romain Guy | ff41eed | 2009-08-24 13:55:57 -0700 | [diff] [blame] | 85 | @SuppressWarnings({"FieldCanBeLocal"}) |
| 86 | private Sampler mSampler; |
| 87 | @SuppressWarnings({"FieldCanBeLocal"}) |
| 88 | private ProgramVertex.MatrixAllocation mPvOrthoAlloc; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 89 | |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 90 | @SuppressWarnings({ "FieldCanBeLocal" }) |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 91 | private Allocation[] mTextures; |
| 92 | |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 93 | private Type mStateType; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 94 | private Allocation mState; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 95 | |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 96 | private Allocation mBlades; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 97 | private Allocation mBladesBuffer; |
Romain Guy | ff41eed | 2009-08-24 13:55:57 -0700 | [diff] [blame] | 98 | @SuppressWarnings({"FieldCanBeLocal"}) |
| 99 | private SimpleMesh mBladesMesh; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 100 | |
| 101 | private int mTriangles; |
Romain Guy | f0bb956 | 2009-10-07 12:25:24 -0700 | [diff] [blame] | 102 | private float[] mBladesData; |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 103 | private final float[] mFloatData5 = new float[5]; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 104 | |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 105 | private WorldState mWorldState; |
| 106 | |
| 107 | private final Context mContext; |
| 108 | private final LocationManager mLocationManager; |
| 109 | |
| 110 | private LocationUpdater mLocationUpdater; |
| 111 | private GrassRS.TimezoneTracker mTimezoneTracker; |
| 112 | |
| 113 | GrassRS(Context context, int width, int height) { |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 114 | super(width, height); |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 115 | |
| 116 | mContext = context; |
| 117 | mLocationManager = (LocationManager) |
| 118 | context.getSystemService(Context.LOCATION_SERVICE); |
| 119 | } |
| 120 | |
| 121 | @Override |
| 122 | public void start() { |
| 123 | super.start(); |
| 124 | |
| 125 | if (mTimezoneTracker == null) { |
| 126 | mTimezoneTracker = new TimezoneTracker(); |
| 127 | IntentFilter filter = new IntentFilter(); |
| 128 | filter.addAction(Intent.ACTION_TIME_CHANGED); |
| 129 | filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); |
| 130 | |
| 131 | mContext.registerReceiver(mTimezoneTracker, filter); |
| 132 | } |
| 133 | |
| 134 | if (mLocationUpdater == null) { |
| 135 | mLocationUpdater = new LocationUpdater(); |
| 136 | mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, |
| 137 | LOCATION_UPDATE_MIN_TIME, LOCATION_UPDATE_MIN_DISTANCE, mLocationUpdater); |
| 138 | } |
| 139 | |
| 140 | updateLocation(); |
| 141 | } |
| 142 | |
| 143 | @Override |
| 144 | public void stop() { |
| 145 | super.stop(); |
| 146 | |
| 147 | if (mTimezoneTracker != null) { |
| 148 | mContext.unregisterReceiver(mTimezoneTracker); |
| 149 | mTimezoneTracker = null; |
| 150 | } |
| 151 | |
| 152 | if (mLocationUpdater != null) { |
| 153 | mLocationManager.removeUpdates(mLocationUpdater); |
| 154 | mLocationUpdater = null; |
| 155 | } |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 156 | } |
| 157 | |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 158 | @Override |
| 159 | public void resize(int width, int height) { |
| 160 | super.resize(width, height); |
Jason Sams | 575d514 | 2009-09-27 17:51:22 -0700 | [diff] [blame] | 161 | |
Romain Guy | 9e6f234 | 2009-08-24 18:40:21 -0700 | [diff] [blame] | 162 | mWorldState.width = width; |
| 163 | mWorldState.height = height; |
| 164 | mState.data(mWorldState); |
| 165 | |
Romain Guy | f0bb956 | 2009-10-07 12:25:24 -0700 | [diff] [blame] | 166 | final float[] blades = mBladesData; |
| 167 | for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) { |
| 168 | updateBlade(blades, i); |
| 169 | } |
| 170 | mBlades.data(blades); |
Romain Guy | 9e6f234 | 2009-08-24 18:40:21 -0700 | [diff] [blame] | 171 | |
Romain Guy | f0bb956 | 2009-10-07 12:25:24 -0700 | [diff] [blame] | 172 | mPvOrthoAlloc.setupOrthoWindow(width, height); |
Romain Guy | 9e6f234 | 2009-08-24 18:40:21 -0700 | [diff] [blame] | 173 | } |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 174 | |
| 175 | @Override |
| 176 | protected ScriptC createScript() { |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 177 | createProgramVertex(); |
| 178 | createProgramFragmentStore(); |
| 179 | createProgramFragment(); |
| 180 | createScriptStructures(); |
| 181 | loadTextures(); |
| 182 | |
| 183 | ScriptC.Builder sb = new ScriptC.Builder(mRS); |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 184 | sb.setType(mStateType, "State", RSID_STATE); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 185 | sb.setScript(mResources, R.raw.grass); |
| 186 | sb.setRoot(true); |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 187 | |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 188 | ScriptC script = sb.create(); |
| 189 | script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
| 190 | script.setTimeZone(TimeZone.getDefault().getID()); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 191 | |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 192 | script.bindAllocation(mState, RSID_STATE); |
| 193 | script.bindAllocation(mBlades, RSID_BLADES); |
| 194 | script.bindAllocation(mBladesBuffer, RSID_BLADES_BUFFER); |
Jason Sams | 575d514 | 2009-09-27 17:51:22 -0700 | [diff] [blame] | 195 | |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 196 | return script; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 197 | } |
| 198 | |
| 199 | private void createScriptStructures() { |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 200 | createBlades(); |
| 201 | createState(); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 202 | } |
| 203 | |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 204 | @Override |
| 205 | public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) { |
| 206 | mWorldState.xOffset = xOffset; |
| 207 | mState.data(mWorldState); |
| 208 | } |
| 209 | |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 210 | static class WorldState { |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 211 | public int bladesCount; |
| 212 | public int trianglesCount; |
| 213 | public int width; |
| 214 | public int height; |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 215 | public float xOffset; |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 216 | public float dawn; |
| 217 | public float morning; |
| 218 | public float afternoon; |
| 219 | public float dusk; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 220 | } |
| 221 | |
| 222 | private void createState() { |
Romain Guy | 9e6f234 | 2009-08-24 18:40:21 -0700 | [diff] [blame] | 223 | mWorldState = new WorldState(); |
| 224 | mWorldState.width = mWidth; |
| 225 | mWorldState.height = mHeight; |
| 226 | mWorldState.bladesCount = BLADES_COUNT; |
| 227 | mWorldState.trianglesCount = mTriangles; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 228 | |
| 229 | mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState"); |
| 230 | mState = Allocation.createTyped(mRS, mStateType); |
Romain Guy | 9e6f234 | 2009-08-24 18:40:21 -0700 | [diff] [blame] | 231 | mState.data(mWorldState); |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 232 | } |
| 233 | |
| 234 | private void createBlades() { |
| 235 | int triangles = 0; |
| 236 | |
Romain Guy | f0bb956 | 2009-10-07 12:25:24 -0700 | [diff] [blame] | 237 | mBladesData = new float[BLADES_COUNT * BLADE_STRUCT_FIELDS_COUNT]; |
| 238 | |
| 239 | final float[] blades = mBladesData; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 240 | for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) { |
| 241 | triangles += createBlade(blades, i); |
| 242 | } |
| 243 | |
Jason Sams | 575d514 | 2009-09-27 17:51:22 -0700 | [diff] [blame] | 244 | mBlades = Allocation.createSized(mRS, USER_F32(mRS), blades.length); |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 245 | mBlades.data(blades); |
| 246 | |
| 247 | mTriangles = triangles; |
| 248 | |
| 249 | createMesh(triangles); |
| 250 | } |
| 251 | |
| 252 | private void createMesh(int triangles) { |
| 253 | Builder elementBuilder = new Builder(mRS); |
| 254 | elementBuilder.addUNorm8RGBA(); |
| 255 | elementBuilder.addFloatXY(); |
| 256 | elementBuilder.addFloatST(); |
| 257 | final Element vertexElement = elementBuilder.create(); |
| 258 | |
| 259 | final SimpleMesh.Builder meshBuilder = new SimpleMesh.Builder(mRS); |
| 260 | final int vertexSlot = meshBuilder.addVertexType(vertexElement, triangles * 3); |
| 261 | meshBuilder.setPrimitive(Primitive.TRIANGLE); |
Romain Guy | e04d27e | 2009-08-21 16:30:52 -0700 | [diff] [blame] | 262 | mBladesMesh = meshBuilder.create(); |
| 263 | mBladesMesh.setName("BladesMesh"); |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 264 | |
Romain Guy | e04d27e | 2009-08-21 16:30:52 -0700 | [diff] [blame] | 265 | mBladesBuffer = mBladesMesh.createVertexAllocation(vertexSlot); |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 266 | mBladesBuffer.setName("BladesBuffer"); |
Romain Guy | e04d27e | 2009-08-21 16:30:52 -0700 | [diff] [blame] | 267 | mBladesMesh.bindVertexAllocation(mBladesBuffer, 0); |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 268 | |
| 269 | // Assign the texture coordinates of each triangle |
| 270 | final float[] floatData = mFloatData5; |
| 271 | final Allocation buffer = mBladesBuffer; |
| 272 | |
| 273 | int bufferIndex = 0; |
| 274 | for (int i = 0; i < triangles; i += 2) { |
| 275 | floatData[3] = 0.0f; |
| 276 | floatData[4] = 1.0f; |
| 277 | buffer.subData1D(bufferIndex, 1, floatData); |
| 278 | bufferIndex++; |
| 279 | |
| 280 | floatData[3] = 0.0f; |
| 281 | floatData[4] = 0.0f; |
| 282 | buffer.subData1D(bufferIndex, 1, floatData); |
| 283 | bufferIndex++; |
| 284 | |
| 285 | floatData[3] = 1.0f; |
| 286 | floatData[4] = 0.0f; |
| 287 | buffer.subData1D(bufferIndex, 1, floatData); |
| 288 | bufferIndex++; |
| 289 | |
| 290 | floatData[3] = 0.0f; |
| 291 | floatData[4] = 0.0f; |
| 292 | buffer.subData1D(bufferIndex, 1, floatData); |
| 293 | bufferIndex++; |
| 294 | |
| 295 | floatData[3] = 1.0f; |
| 296 | floatData[4] = 1.0f; |
| 297 | buffer.subData1D(bufferIndex, 1, floatData); |
| 298 | bufferIndex++; |
| 299 | |
| 300 | floatData[3] = 1.0f; |
| 301 | floatData[4] = 0.0f; |
| 302 | buffer.subData1D(bufferIndex, 1, floatData); |
| 303 | bufferIndex++; |
| 304 | } |
| 305 | } |
| 306 | |
Romain Guy | f0bb956 | 2009-10-07 12:25:24 -0700 | [diff] [blame] | 307 | private void updateBlade(float[] blades, int index) { |
| 308 | final int xpos = random(-mWidth, mWidth); |
| 309 | blades[index + BLADE_STRUCT_XPOS] = xpos; |
| 310 | blades[index + BLADE_STRUCT_TURBULENCEX] = xpos * 0.006f; |
| 311 | blades[index + BLADE_STRUCT_YPOS] = mHeight; |
| 312 | } |
| 313 | |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 314 | private int createBlade(float[] blades, int index) { |
| 315 | final float size = random(4.0f) + 4.0f; |
Romain Guy | 44da178 | 2009-08-28 11:03:21 -0700 | [diff] [blame] | 316 | final int xpos = random(-mWidth, mWidth); |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 317 | |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 318 | //noinspection PointlessArithmeticExpression |
| 319 | blades[index + BLADE_STRUCT_ANGLE] = 0.0f; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 320 | blades[index + BLADE_STRUCT_SIZE] = size / TESSELATION; |
| 321 | blades[index + BLADE_STRUCT_XPOS] = xpos; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 322 | blades[index + BLADE_STRUCT_YPOS] = mHeight; |
| 323 | blades[index + BLADE_STRUCT_OFFSET] = random(0.2f) - 0.1f; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 324 | blades[index + BLADE_STRUCT_SCALE] = 4.0f / (size / TESSELATION) + |
| 325 | (random(0.6f) + 0.2f) * TESSELATION; |
| 326 | blades[index + BLADE_STRUCT_LENGTHX] = (random(4.5f) + 3.0f) * TESSELATION * size; |
| 327 | blades[index + BLADE_STRUCT_LENGTHY] = (random(5.5f) + 2.0f) * TESSELATION * size; |
| 328 | blades[index + BLADE_STRUCT_HARDNESS] = (random(1.0f) + 0.2f) * TESSELATION; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 329 | blades[index + BLADE_STRUCT_H] = random(0.02f) + 0.2f; |
| 330 | blades[index + BLADE_STRUCT_S] = random(0.22f) + 0.78f; |
| 331 | blades[index + BLADE_STRUCT_B] = random(0.65f) + 0.35f; |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 332 | blades[index + BLADE_STRUCT_TURBULENCEX] = xpos * 0.006f; |
| 333 | |
| 334 | // Each blade is made of "size" quads, so we double to count the triangles |
| 335 | return (int) (blades[index + BLADE_STRUCT_SIZE]) * 2; |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 336 | } |
| 337 | |
| 338 | private void loadTextures() { |
| 339 | mTextures = new Allocation[TEXTURES_COUNT]; |
| 340 | |
| 341 | final Allocation[] textures = mTextures; |
| 342 | textures[0] = loadTexture(R.drawable.night, "TNight"); |
| 343 | textures[1] = loadTexture(R.drawable.sunrise, "TSunrise"); |
| 344 | textures[2] = loadTexture(R.drawable.sky, "TSky"); |
| 345 | textures[3] = loadTexture(R.drawable.sunset, "TSunset"); |
| 346 | textures[4] = generateTextureAlpha(4, 1, new int[] { 0x00FFFF00 }, "TAa"); |
| 347 | |
| 348 | final int count = textures.length; |
| 349 | for (int i = 0; i < count; i++) { |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 350 | textures[i].uploadToTexture(0); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 351 | } |
| 352 | } |
| 353 | |
| 354 | private Allocation generateTextureAlpha(int width, int height, int[] data, String name) { |
Jason Sams | 575d514 | 2009-09-27 17:51:22 -0700 | [diff] [blame] | 355 | final Type.Builder builder = new Type.Builder(mRS, A_8(mRS)); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 356 | builder.add(Dimension.X, width); |
| 357 | builder.add(Dimension.Y, height); |
Jason Sams | 575d514 | 2009-09-27 17:51:22 -0700 | [diff] [blame] | 358 | |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 359 | final Allocation allocation = Allocation.createTyped(mRS, builder.create()); |
| 360 | allocation.data(data); |
| 361 | allocation.setName(name); |
| 362 | return allocation; |
| 363 | } |
| 364 | |
| 365 | private Allocation loadTexture(int id, String name) { |
| 366 | final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources, |
Jason Sams | 575d514 | 2009-09-27 17:51:22 -0700 | [diff] [blame] | 367 | id, RGB_565(mRS), false); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 368 | allocation.setName(name); |
| 369 | return allocation; |
| 370 | } |
| 371 | |
| 372 | private void createProgramFragment() { |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 373 | Sampler.Builder samplerBuilder = new Sampler.Builder(mRS); |
| 374 | samplerBuilder.setMin(LINEAR); |
| 375 | samplerBuilder.setMag(LINEAR); |
| 376 | samplerBuilder.setWrapS(WRAP); |
| 377 | samplerBuilder.setWrapT(WRAP); |
Romain Guy | ff41eed | 2009-08-24 13:55:57 -0700 | [diff] [blame] | 378 | mSampler = samplerBuilder.create(); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 379 | |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 380 | ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null); |
| 381 | builder.setTexEnable(true, 0); |
| 382 | builder.setTexEnvMode(REPLACE, 0); |
| 383 | mPfBackground = builder.create(); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 384 | mPfBackground.setName("PFBackground"); |
Romain Guy | ff41eed | 2009-08-24 13:55:57 -0700 | [diff] [blame] | 385 | mPfBackground.bindSampler(mSampler, 0); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 386 | } |
| 387 | |
| 388 | private void createProgramFragmentStore() { |
Romain Guy | b7d2252 | 2009-08-20 12:08:50 -0700 | [diff] [blame] | 389 | ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null); |
| 390 | builder.setDepthFunc(ALWAYS); |
| 391 | builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA); |
| 392 | builder.setDitherEnable(false); |
| 393 | builder.setDepthMask(false); |
| 394 | mPfsBackground = builder.create(); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 395 | mPfsBackground.setName("PFSBackground"); |
| 396 | } |
| 397 | |
| 398 | private void createProgramVertex() { |
Romain Guy | ff41eed | 2009-08-24 13:55:57 -0700 | [diff] [blame] | 399 | mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS); |
| 400 | mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 401 | |
| 402 | ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null); |
| 403 | pvb.setTextureMatrixEnable(true); |
| 404 | mPvBackground = pvb.create(); |
Romain Guy | ff41eed | 2009-08-24 13:55:57 -0700 | [diff] [blame] | 405 | mPvBackground.bindAllocation(mPvOrthoAlloc); |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 406 | mPvBackground.setName("PVBackground"); |
| 407 | } |
Romain Guy | a56ce01 | 2009-10-13 17:05:45 -0700 | [diff] [blame^] | 408 | |
| 409 | private void updateLocation() { |
| 410 | updateLocation(mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)); |
| 411 | } |
| 412 | |
| 413 | private void updateLocation(Location location) { |
| 414 | if (location != null) { |
| 415 | final String timeZone = Time.getCurrentTimezone(); |
| 416 | final SunCalculator calculator = new SunCalculator(location, timeZone); |
| 417 | final Calendar now = Calendar.getInstance(); |
| 418 | |
| 419 | final double sunrise = calculator.computeSunriseTime(SunCalculator.ZENITH_CIVIL, now); |
| 420 | mWorldState.dawn = SunCalculator.timeToDayFraction(sunrise); |
| 421 | |
| 422 | final double sunset = calculator.computeSunsetTime(SunCalculator.ZENITH_CIVIL, now); |
| 423 | mWorldState.dusk = SunCalculator.timeToDayFraction(sunset); |
| 424 | } else { |
| 425 | mWorldState.dawn = 0.3f; |
| 426 | mWorldState.dusk = 0.75f; |
| 427 | } |
| 428 | |
| 429 | mWorldState.morning = mWorldState.dawn + 1.0f / 12.0f; // 2 hours for sunrise |
| 430 | mWorldState.afternoon = mWorldState.dusk - 1.0f / 12.0f; // 2 hours for sunset |
| 431 | |
| 432 | // Send the new data to RenderScript |
| 433 | mState.data(mWorldState); |
| 434 | } |
| 435 | |
| 436 | private class LocationUpdater implements LocationListener { |
| 437 | public void onLocationChanged(Location location) { |
| 438 | updateLocation(location); |
| 439 | } |
| 440 | |
| 441 | public void onStatusChanged(String provider, int status, Bundle extras) { |
| 442 | } |
| 443 | |
| 444 | public void onProviderEnabled(String provider) { |
| 445 | } |
| 446 | |
| 447 | public void onProviderDisabled(String provider) { |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | private class TimezoneTracker extends BroadcastReceiver { |
| 452 | public void onReceive(Context context, Intent intent) { |
| 453 | getScript().setTimeZone(Time.getCurrentTimezone()); |
| 454 | updateLocation(); |
| 455 | } |
| 456 | } |
Romain Guy | 55a384c | 2009-08-12 10:58:02 -0700 | [diff] [blame] | 457 | } |