Add lighting to animated water ripples.
diff --git a/libs/rs/java/Fall/res/raw/fall.c b/libs/rs/java/Fall/res/raw/fall.c
index 76847e0..267b3ea 100644
--- a/libs/rs/java/Fall/res/raw/fall.c
+++ b/libs/rs/java/Fall/res/raw/fall.c
@@ -1,10 +1,215 @@
+// Copyright (C) 2009 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 stateVertex(PVBackground)
 #pragma stateFragment(PFBackground)
-#pragma stateFragmentStore(PSBackground)
+#pragma stateFragmentStore(PFSBackground)
+
+#define RSID_STATE 0
+#define RSID_FRAME_COUNT 0
+#define RSID_WIDTH 1
+#define RSID_HEIGHT 2
+#define RSID_MESH_WIDTH 3
+#define RSID_MESH_HEIGHT 4
+#define RSID_RIPPLE_MAP_SIZE 5
+#define RSID_RIPPLE_INDEX 6
+#define RSID_DROP_X 7
+#define RSID_DROP_Y 8
+    
+#define RSID_TEXTURES 1
+
+#define RSID_RIPPLE_MAP 2
+
+#define RSID_REFRACTION_MAP 3
+
+#define REFRACTION 1.333f
+#define DAMP 4
+
+#define DROP_RADIUS 2
+// The higher, the smaller the ripple
+#define RIPPLE_HEIGHT 10.0f
+
+int offset(int x, int y, int width) {
+    return x + 1 + (y + 1) * (width + 2);
+}
+
+void drop(int x, int y, int r) {
+    int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
+    int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
+
+    if (x < r) x = r;
+    if (y < r) y = r;
+    if (x >= width - r) x = width - r - 1;
+    if (y >= height - r) x = height - r - 1;
+    
+    x = width - x;
+
+    int rippleMapSize = loadI32(RSID_STATE, RSID_RIPPLE_MAP_SIZE);
+    int index = loadI32(RSID_STATE, RSID_RIPPLE_INDEX);
+    int origin = offset(0, 0, width);
+
+    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
+    int sqr = r * r;
+
+    int h = 0;
+    for ( ; h < r; h++) {
+        int sqv = h * h;
+        int yn = origin + (y - h) * (width + 2);
+        int yp = origin + (y + h) * (width + 2);
+        int w = 0;
+        for ( ; w < r; w++) {
+            int squ = w * w;
+            if (squ + sqv < sqr) {
+                int v = -sqrtf((sqr - (squ + sqv)) << 16);
+                current[yn + x + w] = v;
+                current[yp + x + w] = v;
+                current[yn + x - w] = v;
+                current[yp + x - w] = v;
+            }
+        }
+    }
+}
+
+void updateRipples() {
+    int rippleMapSize = loadI32(RSID_STATE, RSID_RIPPLE_MAP_SIZE);
+    int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
+    int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
+    int index = loadI32(RSID_STATE, RSID_RIPPLE_INDEX);
+    int origin = offset(0, 0, width);
+
+    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
+    int* next = loadArrayI32(RSID_RIPPLE_MAP, (1 - index) * rippleMapSize + origin);
+
+    storeI32(RSID_STATE, RSID_RIPPLE_INDEX, 1 - index);
+
+    int a = 1;
+    int b = width + 2;
+    int h = height;
+    while (h) {
+        int w = width;
+        while (w) {
+            int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - next[0];
+            droplet -= (droplet >> DAMP);
+            next[0] = droplet;
+            current++;
+            next++;
+            w--;
+        }
+        current += 2;
+        next += 2;
+        h--;
+    }
+}
+
+void generateRipples() {
+    int rippleMapSize = loadI32(RSID_STATE, RSID_RIPPLE_MAP_SIZE);
+    int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
+    int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
+    int index = loadI32(RSID_STATE, RSID_RIPPLE_INDEX);
+    int origin = offset(0, 0, width);
+
+    int b = width + 2;
+
+    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
+    float *vertices = loadTriangleMeshVerticesF(NAMED_mesh);
+
+    int h = height - 1;
+    while (h >= 0) {
+        int w = width - 1;
+        int wave = current[0];
+        int offset = h * width;
+        while (w >= 0) {
+            int nextWave = current[1];
+            int dx = nextWave - wave;
+            int dy = current[b] - wave;
+
+            // Update Z coordinate of the vertex
+            vertices[(offset + w) * 8 + 7] = (dy / 512.0f) / RIPPLE_HEIGHT;
+            
+            w--;
+            current++;
+            wave = nextWave;
+        }
+        h--;
+        current += 2;
+    }
+
+    // Compute the normals for lighting
+    int y = 0;
+    for ( ; y < height; y++) {
+        int x = 0;
+        int yOffset = y * width;
+        for ( ; x < width; x++) {
+            // V1
+            float v1x = vertices[(yOffset + x) * 8 + 5];
+            float v1y = vertices[(yOffset + x) * 8 + 6];
+            float v1z = vertices[(yOffset + x) * 8 + 7];
+
+            // V2
+            float v2x = vertices[(yOffset + x + 1) * 8 + 5];
+            float v2y = vertices[(yOffset + x + 1) * 8 + 6];
+            float v2z = vertices[(yOffset + x + 1) * 8 + 7];
+            
+            // V3
+            float v3x = vertices[(yOffset + width + x) * 8 + 5];
+            float v3y = vertices[(yOffset + width + x) * 8 + 6];
+            float v3z = vertices[(yOffset + width + x) * 8 + 7];
+
+            // N1
+            float n1x = v2x - v1x;
+            float n1y = v2y - v1y;
+            float n1z = v2z - v1z;
+
+            // N2
+            float n2x = v3x - v1x;
+            float n2y = v3y - v1y;
+            float n2z = v3z - v1z;
+
+            // N1 x N2
+            float n3x = n1y * n2z - n1z * n2y;
+            float n3y = n1z * n2x - n1x * n2z;
+            float n3z = n1x * n2y - n1y * n2x;
+
+            // Normalize
+            float len = magf3(n3x, n3y, n3z);
+            n3x /= len;
+            n3y /= len;
+            n3z /= len;
+
+            vertices[(yOffset + x) * 8 + 0] = -n3x;
+            vertices[(yOffset + x) * 8 + 1] = -n3y;
+            vertices[(yOffset + x) * 8 + 2] = -n3z;
+        }
+    }
+}   
 
 int main(int index) {
-    color(1.0f, 0.0f, 0.0f, 1.0f);
+    int dropX = loadI32(RSID_STATE, RSID_DROP_X);
+    if (dropX != -1) {
+        int dropY = loadI32(RSID_STATE, RSID_DROP_Y);
+        drop(dropX, dropY, DROP_RADIUS);
+        storeI32(RSID_STATE, RSID_DROP_X, -1);
+        storeI32(RSID_STATE, RSID_DROP_Y, -1);
+    }
+
+    updateRipples();
+    generateRipples();
+    updateTriangleMesh(NAMED_mesh);
+
+    ambient(0.0f, 0.1f, 0.9f, 1.0f);
+    diffuse(0.0f, 0.1f, 0.9f, 1.0f);
     drawTriangleMesh(NAMED_mesh);    
 
     return 1;
diff --git a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
index 155bb6f..542f67c 100644
--- a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
+++ b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
@@ -25,6 +25,7 @@
 import android.renderscript.Allocation;
 import android.renderscript.Sampler;
 import android.renderscript.Element;
+import android.renderscript.Light;
 import static android.renderscript.Sampler.Value.LINEAR;
 import static android.renderscript.Sampler.Value.CLAMP;
 import static android.renderscript.ProgramStore.DepthFunc.*;
@@ -38,16 +39,26 @@
 import java.util.TimeZone;
 
 class FallRS {
-    private static final int MESH_RESOLUTION = 32;
+    private static final int MESH_RESOLUTION = 48;
 
     private static final int RSID_STATE = 0;
     private static final int RSID_STATE_FRAMECOUNT = 0;
     private static final int RSID_STATE_WIDTH = 1;
     private static final int RSID_STATE_HEIGHT = 2;
-
+    private static final int RSID_STATE_MESH_WIDTH = 3;
+    private static final int RSID_STATE_MESH_HEIGHT = 4;
+    private static final int RSID_STATE_RIPPLE_MAP_SIZE = 5;
+    private static final int RSID_STATE_RIPPLE_INDEX = 6;
+    private static final int RSID_STATE_DROP_X = 7;
+    private static final int RSID_STATE_DROP_Y = 8;
+    
     private static final int RSID_TEXTURES = 1;
     private static final int TEXTURES_COUNT = 0;
 
+    private static final int RSID_RIPPLE_MAP = 2;
+
+    private static final int RSID_REFRACTION_MAP = 3;
+
     private Resources mResources;
     private RenderScript mRS;
     private final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
@@ -61,6 +72,7 @@
     private ProgramStore mPfsBackground;
     private ProgramVertex mPvBackground;
     private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
+    private Light mLight;
 
     private Allocation mTexturesIDs;
     private Allocation[] mTextures;
@@ -68,6 +80,11 @@
 
     private Allocation mState;
     private RenderScript.TriangleMesh mMesh;
+    private int mMeshWidth;
+    private int mMeshHeight;
+
+    private Allocation mRippleMap;
+    private Allocation mRefractionMap;
 
     public FallRS(int width, int height) {
         mWidth = width;
@@ -96,6 +113,9 @@
         mState.destroy();
         mTextureBufferIDs = null;
         mMesh.destroy();
+        mLight.destroy();
+        mRippleMap.destroy();
+        mRefractionMap.destroy();
     }
 
     @Override
@@ -111,8 +131,9 @@
         createProgramVertex();
         createProgramFragmentStore();
         createProgramFragment();
-        createScriptStructures();
         createMesh();
+        createScriptStructures();
+        loadTextures();
 
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setScript(mResources, R.raw.fall);
@@ -121,16 +142,17 @@
         mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
         mScript.setTimeZone(TimeZone.getDefault().getID());
 
-        loadSkyTextures();
         mScript.bindAllocation(mState, RSID_STATE);
         mScript.bindAllocation(mTexturesIDs, RSID_TEXTURES);
+        mScript.bindAllocation(mRippleMap, RSID_RIPPLE_MAP);
+        mScript.bindAllocation(mRefractionMap, RSID_REFRACTION_MAP);
 
         mRS.contextBindRootScript(mScript);
     }
 
     private void createMesh() {
         final RenderScript rs = mRS;
-        rs.triangleMeshBegin(Element.XYZ_F32, Element.INDEX_16);
+        rs.triangleMeshBegin(Element.NORM_ST_XYZ_F32, Element.INDEX_16);
 
         int wResolution;
         int hResolution;
@@ -146,13 +168,20 @@
             hResolution = MESH_RESOLUTION;
         }
 
-        final float quadWidth = width / (float) wResolution;
-        final float quadHeight = height / (float) hResolution;
+        final float glHeight = 2.0f * height / (float) width;
+        final float quadWidth = 2.0f / (float) wResolution;
+        final float quadHeight = glHeight / (float) hResolution;
 
+        wResolution += 2;
+        hResolution += 2;        
+        
         for (int y = 0; y <= hResolution; y++) {
-            final float yOffset = y * quadHeight;
+            final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight;
             for (int x = 0; x <= wResolution; x++) {
-                rs.triangleMeshAddVertex_XYZ(x * quadWidth, yOffset, 0.0f);
+                rs.triangleMeshAddVertex_XYZ_ST_NORM(
+                        -1.0f + x * quadWidth - quadWidth, yOffset, 0.0f,
+                        x / (float) wResolution, y / (float) wResolution,
+                        0.0f, 0.0f, -1.0f);
             }
         }
 
@@ -167,18 +196,41 @@
 
         mMesh = rs.triangleMeshCreate();
         mMesh.setName("mesh");
+
+        mMeshWidth = wResolution + 1;
+        mMeshHeight = hResolution + 1;
     }
 
     private void createScriptStructures() {
-        final int[] data = new int[3];
+        final int rippleMapSize = (mMeshWidth + 2) * (mMeshHeight + 2);
+
+        final int[] data = new int[9];
         mState = Allocation.createSized(mRS, USER_I32, data.length);
         data[RSID_STATE_FRAMECOUNT] = 0;
         data[RSID_STATE_WIDTH] = mWidth;
         data[RSID_STATE_HEIGHT] = mHeight;
+        data[RSID_STATE_MESH_WIDTH] = mMeshWidth;
+        data[RSID_STATE_MESH_HEIGHT] = mMeshHeight;
+        data[RSID_STATE_RIPPLE_MAP_SIZE] = rippleMapSize;
+        data[RSID_STATE_RIPPLE_INDEX] = 0;
+        data[RSID_STATE_DROP_X] = mMeshWidth / 2;
+        data[RSID_STATE_DROP_Y] = mMeshHeight / 2;
         mState.data(data);
+
+        final int[] rippleMap = new int[rippleMapSize * 2];
+        mRippleMap = Allocation.createSized(mRS, USER_I32, rippleMap.length);
+
+        final int[] refractionMap = new int[513];
+        float ir = 1.0f / 1.333f;
+        for (int i = 0; i < refractionMap.length; i++) {
+            float d = (float) Math.tan(Math.asin(Math.sin(Math.atan(i * (1.0f / 256.0f))) * ir));
+            refractionMap[i] = (int) Math.floor(d * (1 << 16) + 0.5f);
+        }
+        mRefractionMap = Allocation.createSized(mRS, USER_I32, refractionMap.length);
+        mRefractionMap.data(refractionMap);
     }
 
-    private void loadSkyTextures() {
+    private void loadTextures() {
         mTextureBufferIDs = new int[TEXTURES_COUNT];
         mTextures = new Allocation[TEXTURES_COUNT];
         mTexturesIDs = Allocation.createSized(mRS, USER_FLOAT, TEXTURES_COUNT);
@@ -215,42 +267,49 @@
     }
 
     private void createProgramFragment() {
-        Sampler.Builder bs = new Sampler.Builder(mRS);
-        bs.setMin(LINEAR);
-        bs.setMag(LINEAR);
-        bs.setWrapS(CLAMP);
-        bs.setWrapT(CLAMP);
-        mSampler = bs.create();
+        Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
+        sampleBuilder.setMin(LINEAR);
+        sampleBuilder.setMag(LINEAR);
+        sampleBuilder.setWrapS(CLAMP);
+        sampleBuilder.setWrapT(CLAMP);
+        mSampler = sampleBuilder.create();
 
-        ProgramFragment.Builder b;
-        b = new ProgramFragment.Builder(mRS, null, null);
-        b.setTexEnable(true, 0);
-        b.setTexEnvMode(REPLACE, 0);
-        mPfBackground = b.create();
+        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
+        builder.setTexEnable(true, 0);
+        builder.setTexEnvMode(REPLACE, 0);
+        mPfBackground = builder.create();
         mPfBackground.setName("PFBackground");
         mPfBackground.bindSampler(mSampler, 0);
     }
 
     private void createProgramFragmentStore() {
-        ProgramStore.Builder b;
-        b = new ProgramStore.Builder(mRS, null, null);
-
-        b.setDepthFunc(ALWAYS);
-        b.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-        b.setDitherEnable(true);
-        b.setDepthMask(false);
-        mPfsBackground = b.create();
+        ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
+        builder.setDepthFunc(LESS);
+        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+        builder.setDitherEnable(true);
+        builder.setDepthMask(true);
+        mPfsBackground = builder.create();
         mPfsBackground.setName("PFSBackground");
     }
 
     private void createProgramVertex() {
         mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
-        mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
+        mPvOrthoAlloc.setupProjectionNormalized(mWidth, mHeight);
 
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
-        pvb.setTextureMatrixEnable(true);
-        mPvBackground = pvb.create();
+        mLight = new Light.Builder(mRS).create();
+        mLight.setPosition(0.0f, 0.0f, -1.0f);
+
+        ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
+        builder.setTextureMatrixEnable(true);
+        builder.addLight(mLight);
+        mPvBackground = builder.create();
         mPvBackground.bindAllocation(mPvOrthoAlloc);
         mPvBackground.setName("PVBackground");
     }
+
+    public void addDrop(float x, float y) {
+        mState.subData1D(RSID_STATE_DROP_X, 2, new int[] {
+                (int) ((x / mWidth) * mMeshWidth), (int) ((y / mHeight) * mMeshHeight)
+        });
+    }
 }
diff --git a/libs/rs/java/Fall/src/com/android/fall/rs/FallView.java b/libs/rs/java/Fall/src/com/android/fall/rs/FallView.java
index ebbdba5..bb793c8 100644
--- a/libs/rs/java/Fall/src/com/android/fall/rs/FallView.java
+++ b/libs/rs/java/Fall/src/com/android/fall/rs/FallView.java
@@ -19,6 +19,7 @@
 
 import android.content.Context;
 import android.view.SurfaceHolder;
+import android.view.MotionEvent;
 import android.renderscript.RenderScript;
 import android.renderscript.RSSurfaceView;
 
@@ -41,4 +42,20 @@
     public void surfaceDestroyed(SurfaceHolder holder) {
         if (mRender != null) mRender.destroy();
     }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+            case MotionEvent.ACTION_MOVE:
+                mRender.addDrop(event.getX(), event.getY());
+                try {
+                    Thread.sleep(16);
+                } catch (InterruptedException e) {
+                    // Ignore
+                }
+                break;
+        }
+        return true;
+    }
 }
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
index a32739c..6c17967 100644
--- a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
@@ -123,7 +123,7 @@
         createProgramFragmentStore();
         createProgramFragment();
         createScriptStructures();
-        loadSkyTextures();
+        loadTextures();
 
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setScript(mResources, R.raw.grass);
@@ -172,7 +172,7 @@
         blades[index + BLADE_STRUCT_B] = random(0.65f) + 0.35f;
     }
 
-    private void loadSkyTextures() {
+    private void loadTextures() {
         mTextureBufferIDs = new int[TEXTURES_COUNT];
         mTextures = new Allocation[TEXTURES_COUNT];
         mTexturesIDs = Allocation.createSized(mRS, USER_FLOAT, TEXTURES_COUNT);
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index c66e488..6ef5456 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -63,7 +63,7 @@
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     if (mLightCount) {
-        int v = 1;
+        int v = 0;
         glEnable(GL_LIGHTING);
         glLightModelxv(GL_LIGHT_MODEL_TWO_SIDE, &v);
         for (uint32_t ct = 0; ct < mLightCount; ct++) {
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index b7c66e2..b17121f 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -75,6 +75,25 @@
     return i + offset;
 }
 
+static float* SC_loadTriangleMeshVerticesF(RsTriangleMesh mesh)
+{
+    TriangleMesh *tm = static_cast<TriangleMesh *>(mesh);
+    void *vp = tm->mVertexData;
+    float *f = static_cast<float *>(vp);
+    return f;
+}
+
+static void SC_updateTriangleMesh(RsTriangleMesh mesh)
+{
+    TriangleMesh *tm = static_cast<TriangleMesh *>(mesh);
+    glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
+    glBufferData(GL_ARRAY_BUFFER, tm->mVertexDataSize, tm->mVertexData, GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, tm->mIndexDataSize, tm->mIndexData, GL_STATIC_DRAW);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);    
+}
 
 static uint32_t SC_loadU32(uint32_t bank, uint32_t offset)
 {
@@ -584,6 +603,36 @@
     glColor4f(r, g, b, a);
 }
 
+static void SC_ambient(float r, float g, float b, float a)
+{
+    GLfloat params[] = { r, g, b, a };
+    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, params);
+}
+
+static void SC_diffuse(float r, float g, float b, float a)
+{
+    GLfloat params[] = { r, g, b, a };
+    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, params);
+}
+
+static void SC_specular(float r, float g, float b, float a)
+{
+    GLfloat params[] = { r, g, b, a };
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, params);
+}
+
+static void SC_emission(float r, float g, float b, float a)
+{
+    GLfloat params[] = { r, g, b, a };
+    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, params);
+}
+
+static void SC_shininess(float r, float g, float b, float a)
+{
+    GLfloat params[] = { r, g, b, a };
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, params);
+}
+
 static void SC_hsb(float h, float s, float b, float a)
 {
     float red = 0.0f;
@@ -712,6 +761,10 @@
         "void", "(int, int, float *)" },
     { "storeMatrix", (void *)&SC_storeMatrix,
         "void", "(int, int, float *)" },
+    { "loadTriangleMeshVerticesF", (void *)&SC_loadTriangleMeshVerticesF,
+        "float*", "(int)" },
+    { "updateTriangleMesh", (void *)&SC_updateTriangleMesh,
+        "void", "(int)" },
 
     // math
     { "sinf", (void *)&sinf,
@@ -859,6 +912,16 @@
         "void", "(float, float, float, float)" },
     { "hsb", (void *)&SC_hsb,
         "void", "(float, float, float, float)" },
+    { "ambient", (void *)&SC_ambient,
+        "void", "(float, float, float, float)" },
+    { "diffuse", (void *)&SC_diffuse,
+        "void", "(float, float, float, float)" },
+    { "specular", (void *)&SC_specular,
+        "void", "(float, float, float, float)" },
+    { "emission", (void *)&SC_emission,
+        "void", "(float, float, float, float)" },
+    { "shininess", (void *)&SC_shininess,
+        "void", "(float, float, float, float)" },
 
     { "uploadToTexture", (void *)&SC_uploadToTexture,
         "void", "(int, int)" },