Adding bounding box computation.

Change-Id: I682609312519d9474176556ade7a208c7d0a1323
diff --git a/rsMesh.cpp b/rsMesh.cpp
index 9026578..810e4ff 100644
--- a/rsMesh.cpp
+++ b/rsMesh.cpp
@@ -224,6 +224,49 @@
     return mesh;
 }
 
+void Mesh::computeBBox() {
+    float *posPtr = NULL;
+    uint32_t vectorSize = 0;
+    uint32_t stride = 0;
+    uint32_t numVerts = 0;
+    // First we need to find the position ptr and stride
+    for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
+        const Type *bufferType = mVertexBuffers[ct]->getType();
+        const Element *bufferElem = bufferType->getElement();
+
+        for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) {
+            if(strcmp(bufferElem->getFieldName(ct), "position") == 0) {
+                vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize();
+                stride = bufferElem->getSizeBytes() / sizeof(float);
+                uint32_t offset = bufferElem->getFieldOffsetBytes(ct);
+                posPtr = (float*)((uint8_t*)mVertexBuffers[ct]->getPtr() + offset);
+                numVerts = bufferType->getDimX();
+                break;
+            }
+        }
+        if(posPtr) {
+            break;
+        }
+    }
+
+    mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6;
+    mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6;
+    if(!posPtr) {
+        LOGE("Unable to compute bounding box");
+        mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f;
+        mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f;
+        return;
+    }
+
+    for(uint32_t i = 0; i < numVerts; i ++) {
+        for(uint32_t v = 0; v < vectorSize; v ++) {
+            mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]);
+            mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]);
+        }
+        posPtr += stride;
+    }
+}
+
 
 MeshContext::MeshContext()
 {
diff --git a/rsMesh.h b/rsMesh.h
index 765a971..ed01c38 100644
--- a/rsMesh.h
+++ b/rsMesh.h
@@ -61,6 +61,11 @@
     virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_MESH; }
     static Mesh *createFromStream(Context *rsc, IStream *stream);
 
+    // Bounding volumes
+    float mBBoxMin[3];
+    float mBBoxMax[3];
+    void computeBBox();
+
 protected:
 };
 
diff --git a/rsScriptC_LibGL.cpp b/rsScriptC_LibGL.cpp
index f5e5953..4b8de76 100644
--- a/rsScriptC_LibGL.cpp
+++ b/rsScriptC_LibGL.cpp
@@ -251,6 +251,20 @@
     sm->renderPrimitiveRange(rsc, primIndex, start, len);
 }
 
+static void SC_meshComputeBoundingBox(RsMesh vsm, float *minX, float *minY, float *minZ,
+                                                     float *maxX, float *maxY, float *maxZ)
+{
+    GET_TLS();
+    Mesh *sm = static_cast<Mesh *>(vsm);
+    sm->computeBBox();
+    *minX = sm->mBBoxMin[0];
+    *minY = sm->mBBoxMin[1];
+    *minZ = sm->mBBoxMin[2];
+    *maxX = sm->mBBoxMax[0];
+    *maxY = sm->mBBoxMax[1];
+    *maxZ = sm->mBBoxMax[2];
+}
+
 
 //////////////////////////////////////////////////////////////////////////////
 //
@@ -390,6 +404,7 @@
     { "_Z11rsgDrawMesh7rs_mesh", (void *)&SC_drawMesh },
     { "_Z11rsgDrawMesh7rs_meshj", (void *)&SC_drawMeshPrimitive },
     { "_Z11rsgDrawMesh7rs_meshjjj", (void *)&SC_drawMeshPrimitiveRange },
+    { "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_", (void *)&SC_meshComputeBoundingBox },
 
     { "_Z13rsgClearColorffff", (void *)&SC_ClearColor },
     { "_Z13rsgClearDepthf", (void *)&SC_ClearDepth },
diff --git a/scriptc/rs_graphics.rsh b/scriptc/rs_graphics.rsh
index fd0491c..63bd9d7 100644
--- a/scriptc/rs_graphics.rsh
+++ b/scriptc/rs_graphics.rsh
@@ -77,6 +77,23 @@
 extern void __attribute__((overloadable))
     rsgFontColor(float, float, float, float);
 
+extern void __attribute__((overloadable))
+    rsgMeshComputeBoundingBox(rs_mesh mesh, float *minX, float *minY, float *minZ,
+                                                float *maxX, float *maxY, float *maxZ);
+void __attribute__((overloadable))
+rsgMeshComputeBoundingBox(rs_mesh mesh, float3 *bBoxMin, float3 *bBoxMax) {
+    float x1, y1, z1, x2, y2, z2;
+    rsgMeshComputeBoundingBox(mesh, &x1, &y1, &z1, &x2, &y2, &z2);
+    bBoxMin->x = x1;
+    bBoxMin->y = y1;
+    bBoxMin->z = z1;
+    bBoxMax->x = x2;
+    bBoxMax->y = y2;
+    bBoxMax->z = z2;
+}
+
+
+
 ///////////////////////////////////////////////////////
 // misc