| // Copyright (C) 2012 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 "scenegraph_objects.rsh" |
| |
| static void getTransformedSphere(SgRenderable *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(SgRenderable *obj, SgCamera *cam) { |
| 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, |
| &cam->frustumPlanes[0], &cam->frustumPlanes[1], |
| &cam->frustumPlanes[2], &cam->frustumPlanes[3], |
| &cam->frustumPlanes[4], &cam->frustumPlanes[5]); |
| } |
| |
| |
| void root(rs_allocation *v_out, const void *usrData) { |
| |
| SgRenderable *drawable = (SgRenderable *)rsGetElementAt(*v_out, 0); |
| const SgCamera *camera = (const SgCamera*)usrData; |
| |
| drawable->isVisible = 0; |
| // Not loaded yet |
| if (!rsIsObject(drawable->mesh) || drawable->cullType == CULL_ALWAYS) { |
| return; |
| } |
| |
| // check to see if we are culling this object and if it's |
| // outside the frustum |
| if (drawable->cullType == CULL_FRUSTUM && frustumCulled(drawable, (SgCamera*)camera)) { |
| #ifdef DEBUG_RENDERABLES |
| rsDebug("Culled", drawable); |
| printName(drawable->name); |
| #endif // DEBUG_RENDERABLES |
| return; |
| } |
| drawable->isVisible = 1; |
| } |