summaryrefslogtreecommitdiffstats
path: root/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs')
-rw-r--r--tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs296
1 files changed, 296 insertions, 0 deletions
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
new file mode 100644
index 0000000..2891657
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
@@ -0,0 +1,296 @@
+// Copyright (C) 2011 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.scenegraph)
+
+#include "rs_graphics.rsh"
+#include "transform_def.rsh"
+
+rs_script gTransformScript;
+rs_script gCameraScript;
+
+SgTransform *gRootNode;
+rs_allocation gCameras;
+rs_allocation gDrawableObjects;
+
+rs_allocation gRenderPasses;
+
+// Temporary shaders
+rs_allocation gTGrid;
+rs_program_store gPFSBackground;
+
+VShaderParams *vConst;
+FShaderParams *fConst;
+
+uint32_t *gFrontToBack;
+static uint32_t gFrontToBackCount = 0;
+uint32_t *gBackToFront;
+static uint32_t gBackToFrontCount = 0;
+
+static SgCamera *gActiveCamera = NULL;
+static float4 gFrustumPlanes[6];
+
+static rs_allocation nullAlloc;
+
+//#define DEBUG_RENDERABLES
+static void draw(SgDrawable *obj) {
+
+ const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0);
+ const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0);
+#ifdef DEBUG_RENDERABLES
+ rsDebug("**** Drawing object with transform", obj);
+ printName(objTransform->name);
+ rsDebug("Model matrix: ", &objTransform->globalMat);
+ printName(obj->name);
+#endif //DEBUG_RENDERABLES
+
+ SgCamera *cam = gActiveCamera;
+
+ rsMatrixLoad(&vConst->model, &objTransform->globalMat);
+ rsMatrixLoad(&vConst->viewProj, &cam->viewProj);
+ rsgAllocationSyncAll(rsGetAllocation(vConst));
+ fConst->cameraPos = cam->position;
+ rsgAllocationSyncAll(rsGetAllocation(fConst));
+
+ if (rsIsObject(renderState->ps)) {
+ rsgBindProgramStore(renderState->ps);
+ } else {
+ rsgBindProgramStore(gPFSBackground);
+ }
+
+ if (rsIsObject(renderState->pr)) {
+ rsgBindProgramRaster(renderState->pr);
+ } else {
+ rs_program_raster pr;
+ rsgBindProgramRaster(pr);
+ }
+
+ rsgBindProgramFragment(renderState->pf);
+ rsgBindProgramVertex(renderState->pv);
+
+ if (rsIsObject(obj->pf_textures[0])) {
+ rsgBindTexture(renderState->pf, 0, obj->pf_textures[0]);
+ } else {
+ rsgBindTexture(renderState->pf, 0, gTGrid);
+ }
+
+ rsgDrawMesh(obj->mesh, obj->meshIndex);
+}
+
+static void getTransformedSphere(SgDrawable *obj) {
+ obj->worldBoundingSphere = obj->boundingSphere;
+ obj->worldBoundingSphere.w = 1.0f;
+ const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0);
+ obj->worldBoundingSphere = rsMatrixMultiply(&objTransform->globalMat, obj->worldBoundingSphere);
+
+ const float4 unitVec = {0.57735f, 0.57735f, 0.57735f, 0.0f};
+ float4 scaledVec = rsMatrixMultiply(&objTransform->globalMat, unitVec);
+ scaledVec.w = 0.0f;
+ obj->worldBoundingSphere.w = obj->boundingSphere.w * length(scaledVec);
+}
+
+static bool frustumCulled(SgDrawable *obj) {
+ if (!obj->bVolInitialized) {
+ float minX, minY, minZ, maxX, maxY, maxZ;
+ rsgMeshComputeBoundingBox(obj->mesh,
+ &minX, &minY, &minZ,
+ &maxX, &maxY, &maxZ);
+ //rsDebug("min", minX, minY, minZ);
+ //rsDebug("max", maxX, maxY, maxZ);
+ float4 sphere;
+ sphere.x = (maxX + minX) * 0.5f;
+ sphere.y = (maxY + minY) * 0.5f;
+ sphere.z = (maxZ + minZ) * 0.5f;
+ float3 radius;
+ radius.x = (maxX - sphere.x);
+ radius.y = (maxY - sphere.y);
+ radius.z = (maxZ - sphere.z);
+
+ sphere.w = length(radius);
+ obj->boundingSphere = sphere;
+ obj->bVolInitialized = 1;
+ //rsDebug("Sphere", sphere);
+ }
+
+ getTransformedSphere(obj);
+
+ return !rsIsSphereInFrustum(&obj->worldBoundingSphere,
+ &gFrustumPlanes[0], &gFrustumPlanes[1],
+ &gFrustumPlanes[2], &gFrustumPlanes[3],
+ &gFrustumPlanes[3], &gFrustumPlanes[4]);
+}
+
+static void sortToBucket(SgDrawable *obj) {
+ // Not loaded yet
+ if (!rsIsObject(obj->mesh) || obj->cullType == 2) {
+ return;
+ }
+
+ // check to see if we are culling this object and if it's
+ // outside the frustum
+ if (obj->cullType == 0 && frustumCulled(obj)) {
+#ifdef DEBUG_RENDERABLES
+ rsDebug("Culled", obj);
+ printName(obj->name);
+#endif //DEBUG_RENDERABLES
+ return;
+ }
+ const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0);
+ if (rsIsObject(renderState->ps)) {
+ gBackToFront[gBackToFrontCount++] = (uint32_t)obj;
+ } else {
+ gFrontToBack[gFrontToBackCount++] = (uint32_t)obj;
+ }
+}
+
+static void updateActiveCamera(rs_allocation cam) {
+ gActiveCamera = (SgCamera *)rsGetElementAt(cam, 0);
+
+ rsExtractFrustumPlanes(&gActiveCamera->viewProj,
+ &gFrustumPlanes[0], &gFrustumPlanes[1],
+ &gFrustumPlanes[2], &gFrustumPlanes[3],
+ &gFrustumPlanes[3], &gFrustumPlanes[4]);
+}
+
+static void prepareCameras() {
+ // now compute all the camera matrices
+ float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ rsForEach(gCameraScript, gCameras, nullAlloc, &aspect, sizeof(aspect));
+}
+
+static void drawSorted() {
+ for (int i = 0; i < gFrontToBackCount; i ++) {
+ SgDrawable *current = (SgDrawable*)gFrontToBack[i];
+ draw(current);
+ }
+
+ for (int i = 0; i < gBackToFrontCount; i ++) {
+ SgDrawable *current = (SgDrawable*)gBackToFront[i];
+ draw(current);
+ }
+}
+
+static void drawAllObjects(rs_allocation allObj) {
+ if (!rsIsObject(allObj)) {
+ return;
+ }
+ int numDrawables = rsAllocationGetDimX(allObj);
+ for (int i = 0; i < numDrawables; i ++) {
+ rs_allocation *drawAlloc = (rs_allocation*)rsGetElementAt(allObj, i);
+ SgDrawable *current = (SgDrawable*)rsGetElementAt(*drawAlloc, 0);
+ sortToBucket(current);
+ }
+ drawSorted();
+}
+
+void root(const void *v_in, void *v_out) {
+
+ //rsDebug("=============================================================================", 0);
+ // first step is to update the transform hierachy
+ rsForEach(gTransformScript, gRootNode->children, nullAlloc, 0, 0);
+
+ prepareCameras();
+
+ rsgClearDepth(1.0f);
+
+ int numDrawables = rsAllocationGetDimX(gDrawableObjects);
+ if (rsIsObject(gRenderPasses)) {
+ int numPasses = rsAllocationGetDimX(gRenderPasses);
+ for (uint i = 0; i < numPasses; i ++) {
+ gFrontToBackCount = 0;
+ gBackToFrontCount = 0;
+ SgRenderPass *pass = (SgRenderPass*)rsGetElementAt(gRenderPasses, i);
+ if (rsIsObject(pass->color_target)) {
+ rsgBindColorTarget(pass->color_target, 0);
+ }
+ if (rsIsObject(pass->depth_target)) {
+ rsgBindDepthTarget(pass->depth_target);
+ }
+ if (!rsIsObject(pass->color_target) &&
+ !rsIsObject(pass->depth_target)) {
+ rsgClearAllRenderTargets();
+ }
+ updateActiveCamera(pass->camera);
+ if (pass->should_clear_color) {
+ rsgClearColor(pass->clear_color.x, pass->clear_color.y,
+ pass->clear_color.z, pass->clear_color.w);
+ }
+ if (pass->should_clear_depth) {
+ rsgClearDepth(pass->clear_depth);
+ }
+ drawAllObjects(pass->objects);
+ }
+ } else {
+ gFrontToBackCount = 0;
+ gBackToFrontCount = 0;
+ rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgClearDepth(1.0f);
+ rs_allocation *camAlloc = (rs_allocation*)rsGetElementAt(gCameras, 1);
+ updateActiveCamera(*camAlloc);
+ drawAllObjects(gDrawableObjects);
+ }
+}
+
+static bool intersect(const SgDrawable *obj, float3 pnt, float3 vec) {
+ // Solving for t^2 + Bt + C = 0
+ float3 originMinusCenter = pnt - obj->worldBoundingSphere.xyz;
+ float B = dot(originMinusCenter, vec) * 2.0f;
+ float C = dot(originMinusCenter, originMinusCenter) -
+ obj->worldBoundingSphere.w * obj->worldBoundingSphere.w;
+
+ float discriminant = B * B - 4.0f * C;
+ if (discriminant < 0.0f) {
+ return false;
+ }
+ discriminant = sqrt(discriminant);
+
+ float t0 = (-B - discriminant) * 0.5f;
+ float t1 = (-B + discriminant) * 0.5f;
+
+ if (t0 > t1) {
+ float temp = t0;
+ t0 = t1;
+ t1 = temp;
+ }
+
+ // The sphere is behind us
+ if (t1 < 0.0f) {
+ return false;
+ }
+ return true;
+}
+
+// Search through sorted and culled objects
+void pick(int screenX, int screenY) {
+ float3 pnt, vec;
+ getCameraRay(gActiveCamera, screenX, screenY, &pnt, &vec);
+
+ for (int i = 0; i < gFrontToBackCount; i ++) {
+ SgDrawable *current = (SgDrawable*)gFrontToBack[i];
+ bool isPicked = intersect(current, pnt, vec);
+ if (isPicked) {
+ current->cullType = 2;
+ }
+ }
+
+ for (int i = 0; i < gBackToFrontCount; i ++) {
+ SgDrawable *current = (SgDrawable*)gBackToFront[i];
+ bool isPicked = intersect(current, pnt, vec);
+ if (isPicked) {
+ current->cullType = 2;
+ }
+ }
+}