You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by de...@apache.org on 2005/11/07 21:34:10 UTC

svn commit: r331595 - in /xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image: SpotLight.java rendered/SpecularLightingRed.java

Author: deweese
Date: Mon Nov  7 12:34:04 2005
New Revision: 331595

URL: http://svn.apache.org/viewcvs?rev=331595&view=rev
Log:
Fixes a problem with feSpotLight and feSpecular lighting,
PR: 36745

Modified:
    xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/SpotLight.java
    xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/SpecularLightingRed.java

Modified: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/SpotLight.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/SpotLight.java?rev=331595&r1=331594&r2=331595&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/SpotLight.java (original)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/SpotLight.java Mon Nov  7 12:34:04 2005
@@ -107,10 +107,10 @@
         return limitingConeAngle;
     }
 
-    public SpotLight(final double lightX, final double lightY, final double lightZ,
-                     final double pointAtX, final double pointAtY, final double pointAtZ,
-                     final double specularExponent, final double limitingConeAngle,
-                     final Color lightColor){
+    public SpotLight(double lightX, double lightY, double lightZ,
+                     double pointAtX, double pointAtY, double pointAtZ,
+                     double specularExponent, double limitingConeAngle,
+                     Color lightColor){
         super(lightColor);
 
         this.lightX = lightX;
@@ -127,13 +127,11 @@
         S[1] = pointAtY - lightY;
         S[2] = pointAtZ - lightZ;
 
-        double norm = Math.sqrt(S[0]*S[0]
-                                + S[1]*S[1]
-                                + S[2]*S[2]);
-
-        S[0] /= norm;
-        S[1] /= norm;
-        S[2] /= norm;
+        double invNorm = 1/Math.sqrt(S[0]*S[0] + S[1]*S[1] + S[2]*S[2]);
+
+        S[0] *= invNorm;
+        S[1] *= invNorm;
+        S[2] *= invNorm;
     }
 
     /**
@@ -150,25 +148,29 @@
      * @param y y-axis coordinate where the light should be computed
      * @param z z-axis coordinate where the light should be computed
      * @param L array of length 3 where the result is stored
+     * @return the intensity factor for this light vector.
      */
-    public final void getLight(final double x, final double y, final double z,
-                               final double L[]){
+    public final double getLightBase(final double x, final double y, 
+                                     final double z,
+                                     final double L[]){
         // Light Vector, L
         L[0] = lightX - x;
         L[1] = lightY - y;
         L[2] = lightZ - z;
 
-        final double norm = Math.sqrt(L[0]*L[0] +
-                                      L[1]*L[1] +
-                                      L[2]*L[2]);
-
-        L[0] /= norm;
-        L[1] /= norm;
-        L[2] /= norm;
+        final double invNorm = 1/Math.sqrt(L[0]*L[0] +
+                                           L[1]*L[1] +
+                                           L[2]*L[2]);
+
+        L[0] *= invNorm;
+        L[1] *= invNorm;
+        L[2] *= invNorm;
         
         double LS = -(L[0]*S[0] + L[1]*S[1] + L[2]*S[2]);
         
-        if(LS > limitingCos){
+        if(LS <= limitingCos){
+            return 0;
+        } else {
             double Iatt = limitingCos/LS;
             Iatt *= Iatt;
             Iatt *= Iatt;
@@ -178,17 +180,58 @@
             Iatt *= Iatt; // akin Math.pow(Iatt, 64)
 
             Iatt = 1 - Iatt;
-            LS = Iatt*Math.pow(LS, specularExponent);
-            
-            L[0] *= LS;
-            L[1] *= LS;
-            L[2] *= LS;
+            return Iatt*Math.pow(LS, specularExponent);
         }
-        else{
-            L[0] = 0;
-            L[1] = 0;
-            L[2] = 0;
+    }
+
+    /**
+     * Computes the light vector in (x, y, z)
+     *
+     * @param x x-axis coordinate where the light should be computed
+     * @param y y-axis coordinate where the light should be computed
+     * @param z z-axis coordinate where the light should be computed
+     * @param L array of length 3 where the result is stored,
+     *          x,y,z are scaled by light intensity.
+     */
+    public final void getLight(final double x, final double y, 
+                               final double z,
+                               final double L[]){
+        final double s = getLightBase(x, y, z, L);
+        L[0] *= s;
+        L[1] *= s;
+        L[2] *= s;
+    }
+
+    /**
+     * computes light vector in (x, y, z).
+     *
+     * @param x x-axis coordinate where the light should be computed
+     * @param y y-axis coordinate where the light should be computed
+     * @param z z-axis coordinate where the light should be computed
+     * @param L array of length 4 where result is stored.
+     *          0,1,2 are x,y,z respectively of light vector (normalized).
+     *          3 is the intensity of the light at this point.
+     */
+    public final void getLight4(final double x, final double y, final double z,
+                               final double L[]){
+        L[3] = getLightBase(x, y, z, L);
+    }
+
+    public double[][] getLightRow4(double x, double y, 
+                                  final double dx, final int width,
+                                  final double[][] z,
+                                  final double[][] lightRow) {
+        double [][] ret = lightRow;
+        if (ret == null) 
+            ret = new double[width][4];
+
+        for(int i=0; i<width; i++){
+            getLight4(x, y, z[i][3], ret[i]);
+            x += dx;
         }
+
+        return ret;
     }
+
 }
 

Modified: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/SpecularLightingRed.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/SpecularLightingRed.java?rev=331595&r1=331594&r2=331595&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/SpecularLightingRed.java (original)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/SpecularLightingRed.java Mon Nov  7 12:34:04 2005
@@ -26,6 +26,7 @@
 
 import org.apache.batik.ext.awt.image.GraphicsUtil;
 import org.apache.batik.ext.awt.image.Light;
+import org.apache.batik.ext.awt.image.SpotLight;
 
 /**
  * 
@@ -160,32 +161,57 @@
         final double[][][] NA = bumpMap.getNormalArray(minX, minY, w, h);
 
         // System.out.println("Entering Specular Lighting");
-        if(!light.isConstant()){
-            final double[][] LA = new double[w][3];
+        if (light instanceof SpotLight) {
+            SpotLight slight = (SpotLight)light;
+            final double[][] LA = new double[w][4];
             for(i=0; i<h; i++){
                 // System.out.println("Row: " + i);
                 final double [][] NR = NA[i];
-                light.getLightRow(x, y+i*scaleY, scaleX, w, NR, LA);
+                slight.getLightRow4(x, y+i*scaleY, scaleX, w, NR, LA);
                 for (j=0; j<w; j++){
                     // Get Normal 
                     final double [] N = NR[j];
                     
                     // Get Light Vector
                     final double [] L = LA[j];
-
-                    // Compute Half-way vector
-                    L[2] += 1;
-                    norm = L[0]*L[0] + L[1]*L[1] + L[2]*L[2];
-                    if(norm == 0) 
-                        a = (int)(mult+0.5);
-                    else {
+                    double vs = L[3];
+                    if (vs == 0) {
+                        a = 0;
+                    } else {
+                        L[2] += 1;
+                        norm = L[0]*L[0] + L[1]*L[1] + L[2]*L[2];
                         norm = Math.sqrt(norm);
-                        a = (int)(mult*Math.pow((N[0]*L[0] + 
-                                                 N[1]*L[1] + N[2]*L[2])/norm, 
-                                                specularExponent) + 0.5);
+                        double dot = N[0]*L[0] + N[1]*L[1] + N[2]*L[2];
+                        vs = vs*Math.pow(dot/norm, specularExponent);
+                        a = (int)(mult*vs + 0.5);
                         if ((a & 0xFFFFFF00) != 0)
                             a = ((a & 0x80000000) != 0)?0:255;
                     }
+                    pixels[p++] = (a << 24 | pixel);
+                }
+                p += adjust;
+            }
+        } else if(!light.isConstant()){
+            final double[][] LA = new double[w][4];
+            for(i=0; i<h; i++){
+                // System.out.println("Row: " + i);
+                final double [][] NR = NA[i];
+                light.getLightRow(x, y+i*scaleY, scaleX, w, NR, LA);
+                for (j=0; j<w; j++){
+                    // Get Normal 
+                    final double [] N = NR[j];
+                    
+                    // Get Light Vector
+                    final double [] L = LA[j];
+                    L[2] += 1;
+                    norm = L[0]*L[0] + L[1]*L[1] + L[2]*L[2];
+                    norm = Math.sqrt(norm);
+                    double dot = N[0]*L[0] + N[1]*L[1] + N[2]*L[2];
+                    // vs = vs/norm;
+                    norm = Math.pow(dot/norm, specularExponent);
+                    a = (int)(mult*norm + 0.5);
+                    if ((a & 0xFFFFFF00) != 0)
+                        a = ((a & 0x80000000) != 0)?0:255;
                     pixels[p++] = (a << 24 | pixel);
                 }
                 p += adjust;