Merge "Added frustum plane extraction and sphere culling code."
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 60de04a..aee4133 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -318,6 +318,12 @@
     mDirty = true;
 }
 
+void ProgramVertex::getProjectionMatrix(rsc_Matrix *m) const
+{
+    float *f = static_cast<float *>(mConstants[0]->getPtr());
+    memcpy(m, &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], sizeof(rsc_Matrix));
+}
+
 void ProgramVertex::transformToScreen(const Context *rsc, float *v4out, const float *v3in) const
 {
     float *f = static_cast<float *>(mConstants[0]->getPtr());
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
index 1c8b9c8..a17c9ea 100644
--- a/libs/rs/rsProgramVertex.h
+++ b/libs/rs/rsProgramVertex.h
@@ -43,6 +43,7 @@
     void addLight(const Light *);
 
     void setProjectionMatrix(const rsc_Matrix *) const;
+    void getProjectionMatrix(rsc_Matrix *) const;
     void setModelviewMatrix(const rsc_Matrix *) const;
     void setTextureMatrix(const rsc_Matrix *) const;
 
diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp
index 4b8de76..a7877cdb 100644
--- a/libs/rs/rsScriptC_LibGL.cpp
+++ b/libs/rs/rsScriptC_LibGL.cpp
@@ -117,6 +117,12 @@
     pf->setConstantColor(r, g, b, a);
 }
 
+static void SC_vpGetProjectionMatrix(rsc_Matrix *m)
+{
+    GET_TLS();
+    rsc->getVertex()->getProjectionMatrix(m);
+}
+
 
 //////////////////////////////////////////////////////////////////////////////
 // Drawing
@@ -387,6 +393,8 @@
     { "_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4", (void *)&SC_vpLoadModelMatrix },
     { "_Z33rsgProgramVertexLoadTextureMatrixPK12rs_matrix4x4", (void *)&SC_vpLoadTextureMatrix },
 
+    { "_Z35rsgProgramVertexGetProjectionMatrixP12rs_matrix4x4", (void *)&SC_vpGetProjectionMatrix },
+
     { "_Z31rsgProgramFragmentConstantColor19rs_program_fragmentffff", (void *)&SC_pfConstantColor },
 
     { "_Z11rsgGetWidthv", (void *)&SC_getWidth },
diff --git a/libs/rs/scriptc/rs_core.rsh b/libs/rs/scriptc/rs_core.rsh
index aa9aebc..0bfb3b9 100644
--- a/libs/rs/scriptc/rs_core.rsh
+++ b/libs/rs/scriptc/rs_core.rsh
@@ -767,6 +767,92 @@
     m->m[15] = 1.0f;
 }
 
+/////////////////////////////////////////////////////
+// utility funcs
+/////////////////////////////////////////////////////
+void __attribute__((overloadable))
+rsExtractFrustumPlanes(const rs_matrix4x4 *modelViewProj,
+                         float4 *left, float4 *right,
+                         float4 *top, float4 *bottom,
+                         float4 *near, float4 *far) {
+    // x y z w = a b c d in the plane equation
+    left->x = modelViewProj->m[3] + modelViewProj->m[0];
+    left->y = modelViewProj->m[7] + modelViewProj->m[4];
+    left->z = modelViewProj->m[11] + modelViewProj->m[8];
+    left->w = modelViewProj->m[15] + modelViewProj->m[12];
+
+    right->x = modelViewProj->m[3] - modelViewProj->m[0];
+    right->y = modelViewProj->m[7] - modelViewProj->m[4];
+    right->z = modelViewProj->m[11] - modelViewProj->m[8];
+    right->w = modelViewProj->m[15] - modelViewProj->m[12];
+
+    top->x = modelViewProj->m[3] - modelViewProj->m[1];
+    top->y = modelViewProj->m[7] - modelViewProj->m[5];
+    top->z = modelViewProj->m[11] - modelViewProj->m[9];
+    top->w = modelViewProj->m[15] - modelViewProj->m[13];
+
+    bottom->x = modelViewProj->m[3] + modelViewProj->m[1];
+    bottom->y = modelViewProj->m[7] + modelViewProj->m[5];
+    bottom->z = modelViewProj->m[11] + modelViewProj->m[9];
+    bottom->w = modelViewProj->m[15] + modelViewProj->m[13];
+
+    near->x = modelViewProj->m[3] + modelViewProj->m[2];
+    near->y = modelViewProj->m[7] + modelViewProj->m[6];
+    near->z = modelViewProj->m[11] + modelViewProj->m[10];
+    near->w = modelViewProj->m[15] + modelViewProj->m[14];
+
+    far->x = modelViewProj->m[3] - modelViewProj->m[2];
+    far->y = modelViewProj->m[7] - modelViewProj->m[6];
+    far->z = modelViewProj->m[11] - modelViewProj->m[10];
+    far->w = modelViewProj->m[15] - modelViewProj->m[14];
+
+    float len = length(left->xyz);
+    *left /= len;
+    len = length(right->xyz);
+    *right /= len;
+    len = length(top->xyz);
+    *top /= len;
+    len = length(bottom->xyz);
+    *bottom /= len;
+    len = length(near->xyz);
+    *near /= len;
+    len = length(far->xyz);
+    *far /= len;
+}
+
+bool __attribute__((overloadable))
+rsIsSphereInFrustum(float4 *sphere,
+                      float4 *left, float4 *right,
+                      float4 *top, float4 *bottom,
+                      float4 *near, float4 *far) {
+
+    float distToCenter = dot(left->xyz, sphere->xyz) + left->w;
+    if(distToCenter < -sphere->w) {
+        return false;
+    }
+    distToCenter = dot(right->xyz, sphere->xyz) + right->w;
+    if(distToCenter < -sphere->w) {
+        return false;
+    }
+    distToCenter = dot(top->xyz, sphere->xyz) + top->w;
+    if(distToCenter < -sphere->w) {
+        return false;
+    }
+    distToCenter = dot(bottom->xyz, sphere->xyz) + bottom->w;
+    if(distToCenter < -sphere->w) {
+        return false;
+    }
+    distToCenter = dot(near->xyz, sphere->xyz) + near->w;
+    if(distToCenter < -sphere->w) {
+        return false;
+    }
+    distToCenter = dot(far->xyz, sphere->xyz) + far->w;
+    if(distToCenter < -sphere->w) {
+        return false;
+    }
+    return true;
+}
+
 
 /////////////////////////////////////////////////////
 // int ops
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index 63bd9d7..c0b2d2d 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -27,6 +27,9 @@
     rsgProgramVertexLoadTextureMatrix(const rs_matrix4x4 *);
 
 extern void __attribute__((overloadable))
+    rsgProgramVertexGetProjectionMatrix(rs_matrix4x4 *);
+
+extern void __attribute__((overloadable))
     rsgProgramFragmentConstantColor(rs_program_fragment, float, float, float, float);
 
 extern uint __attribute__((overloadable))
@@ -92,8 +95,6 @@
     bBoxMax->z = z2;
 }
 
-
-
 ///////////////////////////////////////////////////////
 // misc