1 // Copyright (C) 2012 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma version(1)
16 
17 #pragma rs java_package_name(com.android.scenegraph)
18 
19 #include "scenegraph_objects.rsh"
20 
21 static void getTransformedSphere(SgRenderable *obj) {
22     obj->worldBoundingSphere = obj->boundingSphere;
23     obj->worldBoundingSphere.w = 1.0f;
24     const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0);
25     obj->worldBoundingSphere = rsMatrixMultiply(&objTransform->globalMat, obj->worldBoundingSphere);
26 
27     const float4 unitVec = {0.57735f, 0.57735f, 0.57735f, 0.0f};
28     float4 scaledVec = rsMatrixMultiply(&objTransform->globalMat, unitVec);
29     scaledVec.w = 0.0f;
30     obj->worldBoundingSphere.w = obj->boundingSphere.w * length(scaledVec);
31 }
32 
33 static bool frustumCulled(SgRenderable *obj, SgCamera *cam) {
34     if (!obj->bVolInitialized) {
35         float minX, minY, minZ, maxX, maxY, maxZ;
36         rsgMeshComputeBoundingBox(obj->mesh,
37                                   &minX, &minY, &minZ,
38                                   &maxX, &maxY, &maxZ);
39         //rsDebug("min", minX, minY, minZ);
40         //rsDebug("max", maxX, maxY, maxZ);
41         float4 sphere;
42         sphere.x = (maxX + minX) * 0.5f;
43         sphere.y = (maxY + minY) * 0.5f;
44         sphere.z = (maxZ + minZ) * 0.5f;
45         float3 radius;
46         radius.x = (maxX - sphere.x);
47         radius.y = (maxY - sphere.y);
48         radius.z = (maxZ - sphere.z);
49 
50         sphere.w = length(radius);
51         obj->boundingSphere = sphere;
52         obj->bVolInitialized = 1;
53         //rsDebug("Sphere", sphere);
54     }
55 
56     getTransformedSphere(obj);
57 
58     return !rsIsSphereInFrustum(&obj->worldBoundingSphere,
59                                 &cam->frustumPlanes[0], &cam->frustumPlanes[1],
60                                 &cam->frustumPlanes[2], &cam->frustumPlanes[3],
61                                 &cam->frustumPlanes[4], &cam->frustumPlanes[5]);
62 }
63 
64 
65 void root(rs_allocation *v_out, const void *usrData) {
66 
67     SgRenderable *drawable = (SgRenderable *)rsGetElementAt(*v_out, 0);
68     const SgCamera *camera = (const SgCamera*)usrData;
69 
70     drawable->isVisible = 0;
71     // Not loaded yet
72     if (!rsIsObject(drawable->mesh) || drawable->cullType == CULL_ALWAYS) {
73         return;
74     }
75 
76     // check to see if we are culling this object and if it's
77     // outside the frustum
78     if (drawable->cullType == CULL_FRUSTUM && frustumCulled(drawable, (SgCamera*)camera)) {
79 #ifdef DEBUG_RENDERABLES
80         rsDebug("Culled", drawable);
81         printName(drawable->name);
82 #endif // DEBUG_RENDERABLES
83         return;
84     }
85     drawable->isVisible = 1;
86 }
87