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
21static 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
33static 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
65void 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