root/graph/JavaPopWeb/src/jp/ac/nime/computer/grpsimulator/VecPr/AnalyzeReflectance.java

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. AnalyzeReflectance
  2. faceColor
  3. sphere
  4. colplus
  5. pointAmbient
  6. pointLambertReflectance
  7. pointLambertReflectance
  8. pointPhongReflectance
  9. pointPhongReflectance

package jp.ac.nime.computer.grpsimulator.VecPr;

import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.util.*;

/** 画像解析 リフレクタンス
 * @author Kikuchi
 * @version 1.0.0
 */
public class AnalyzeReflectance {
        // リソース
        ResourceBundle res_;
        /** コンストラクタ
         * @param res リソースハンドル
         */
        public AnalyzeReflectance(ResourceBundle res) {
                res_ = res;
        }
        
        /** 色をimgに表現する
         * @param ka 環境光(%)
         * @param kr 拡散反射率R(%)
         * @param kg 拡散反射率G(%)
         * @param kb 拡散反射率B(%)
         * @param ks 鏡面反射率(%)
         * @param nn ハイライト指数
         * @param ld 光源角度(度)(0-180)
         * @param cd カメラ角度(度)(0-180)
         * @return 最終的な色
         */
        public void faceColor(BufferedImage img, int ka, int kr, int kg, int kb, int ks, int nn, int ld, int cd) {
                Graphics2D g = img.createGraphics();
                // 黒でクリア
                g.setBackground(Color.black);
                g.clearRect(0, 0, img.getWidth(), img.getHeight());
                g.setStroke(new BasicStroke(0.0f)); // 一番細く 引数はfloat
                // 一つの幅
                int w = img.getWidth() / 4;
                int h = img.getHeight();
                // 色を置く
                // 環境光
                Color amb = pointAmbient(Color.white, ka, kr, kg, kb);
                g.setColor(amb);
                g.fill(new Rectangle2D.Double(0, 0, w, h));
                // 拡散反射
                Color lam = pointLambertReflectance(Color.white, kr, kg, kb, ld); 
                g.setColor(lam);
                g.fill(new Rectangle2D.Double(w, 0, w, h));
                // 鏡面反射
                Color phong = pointPhongReflectance(Color.white, ks, nn, ld, cd);
                g.setColor(phong);
                g.fill(new Rectangle2D.Double(w * 2, 0, w, h));
                // あわせた色
                Color all = colplus(amb, lam, phong);
                g.setColor(all);
                g.fill(new Rectangle2D.Double(w * 3, 0, w, h));
                // 白で枠を書く
                g.setColor(Color.white);
                g.draw(new Rectangle2D.Double(0, 0, w, h));
                g.draw(new Rectangle2D.Double(w, 0, w, h));
                g.draw(new Rectangle2D.Double(w * 2, 0, w, h));
                g.draw(new Rectangle2D.Double(w * 3, 0, w, h));
                // 説明文
                int xs = 10;
                int ys = 20;
                Font font = new Font( "SansSerif", Font.PLAIN, 10 ); 
                g.setFont( font ); 
                g.setColor(Color.white);
                FontMetrics fm = g.getFontMetrics();
                int w2 = fm.stringWidth(res_.getString("DlgAnalyzeReflectanceAmbient"));
                int h2 = fm.getHeight();
                g.fill(new Rectangle2D.Double(xs - 1, ys - h2 + 2, w2, h2));
                w2 = fm.stringWidth(res_.getString("DlgAnalyzeReflectanceLambert"));
                g.fill(new Rectangle2D.Double(xs - 1 + w, ys - h2 + 2, w2, h2));
                w2 = fm.stringWidth(res_.getString("DlgAnalyzeReflectancePhong"));
                g.fill(new Rectangle2D.Double(xs - 1 + w * 2, ys - h2 + 2, w2, h2));
                w2 = fm.stringWidth(res_.getString("DlgAnalyzeReflectanceAll"));
                g.fill(new Rectangle2D.Double(xs - 1 + w * 3, ys - h2 + 2, w2, h2));
                
                g.setColor(Color.black);
                g.drawString(res_.getString("DlgAnalyzeReflectanceAmbient"), xs, ys);
                g.drawString(res_.getString("DlgAnalyzeReflectanceLambert"), xs + w, ys);
                g.drawString(res_.getString("DlgAnalyzeReflectancePhong"), xs + w * 2, ys);
                g.drawString(res_.getString("DlgAnalyzeReflectanceAll"), xs + w * 3, ys);

                g.dispose();
        }
        
        /** 半球をimgに表現する
         * @param ka 環境光(%)
         * @param kr 拡散反射率R(%)
         * @param kg 拡散反射率G(%)
         * @param kb 拡散反射率B(%)
         * @param ks 鏡面反射率(%)
         * @param nn ハイライト指数(単位は10分の1)
         * @param ld 光源角度(度)(0-180)
         * @param cd カメラ角度(度)(0-180)
         * @return 最終的な色
         */
        public void sphere(BufferedImage img, int ka, int kr, int kg, int kb, int ks, int nn, int ld, int cd) {
                Graphics2D g = img.createGraphics();
                // 黒でクリア
                g.setBackground(Color.black);
                g.clearRect(0, 0, img.getWidth(), img.getHeight());
                g.setStroke(new BasicStroke(0.0f)); // 一番細く 引数はfloat
                // 高さ
                int he = img.getHeight();
                // 中心
                int cx = img.getWidth() / 2;
                int cy = img.getHeight() / 2;
                // 半径
                int r = cy * 2 / 3;
                int rr = r * r;
                // 環境光
                Color amb = pointAmbient(Color.white, ka, kr, kg, kb);
                // 光源へのベクトル
                double lx = Math.cos((double)ld * Math.PI / 180.0);
                Vertex L = new Vertex(lx, 1, -1);
                L.normal();
                // 視線へのベクトル
                Vertex V = new Vertex(0, 0, -1);
                V.normal();
                // 球の点のループ
                int y;
                int x;
                for (y = -r; y < r; y ++) {
                        for (x = - r; x < r; x ++) {
                                // 半径内かどうかチェック
                                int xxyy = (x * x + y * y);
                                if (xxyy <= rr) {
                                        // 色の決定
                                        // zを求める
                                        int zz = Math.abs(rr - xxyy);
                                        double z2 = - Math.sqrt((double)zz);
                                        double x2 = x;
                                        double y2 = y;
                                        // x, y , zから 法線ベクトルと光源へのベクトルを求める
                                        Vertex N = new Vertex(x2, y2, z2);
                                        N.normal();
                                        // 光源の正反射ベクトル
                                        Vertex R = Vertex.sub(Vertex.scale(N, 2.0 * Vertex.dot(N, L)), L);
                                        R.normal();
                                        // 拡散反射
                                        double cos = Vertex.dot(L, N);
//System.out.println("dot(L,N) = " + cos);
                                        Color lam = pointLambertReflectance(Color.white, kr, kg, kb, cos);
                                        // 鏡面反射
                                        cos = Vertex.dot(R, V);
                                        Color phong = new Color(0, 0, 0);
                                        if (cos > 0)
                                                phong = pointPhongReflectance(Color.white, ks, nn, cos);
                                        // 色
                                        Color all = colplus(amb, lam, phong);
                                        g.setColor(all);
                                        g.draw(new Line2D.Double(x + cx, he - (y + cy), x + cx + 1, he - (y + cy)));
                                }
                        }
                }
                g.dispose();
        }
        
        /** 色の足し算
         * @param amb 環境光
         * @param lam 反射光
         * @param phong 鏡面反射光
         */
        private Color colplus(Color amb, Color lam, Color phong) {
                int red = amb.getRed() + lam.getRed() + phong.getRed();
                int green = amb.getGreen() + lam.getGreen() + phong.getGreen();
                int blue = amb.getBlue() + lam.getBlue() + phong.getBlue();
                red = Math.max(0, Math.min(255, red));
                green = Math.max(0, Math.min(255, green));
                blue = Math.max(0, Math.min(255, blue));
                return new Color(red, green, blue);
        }
        
        /** 環境光
         * @param col 光源
         * @param ka 環境光(%)
         * @param kr 拡散反射率R(%)
         * @param kg 拡散反射率G(%)
         * @param kb 拡散反射率B(%)
         * @return 反射色
         */
        private Color pointAmbient(Color col, int ka, int kr, int kg, int kb) {
                return new Color((int)((col.getRed() * ka / 100.0 * kr / 100.0) + 0.5),
                                                 (int)((col.getGreen() * ka / 100.0 * kg / 100.0) + 0.5),
                                                 (int)((col.getBlue() * ka / 100.0 * kb / 100.0) + 0.5)
                                                 );
        }
        
        
        /** 点の拡散反射 Lambertの余弦則
         * @param col 光源
         * @param kr 拡散反射率R(%)
         * @param kg 拡散反射率G(%)
         * @param kb 拡散反射率B(%)
         * @param cos 光源と法線のcos
         * @return 反射色
         */
        private Color pointLambertReflectance(Color col, int kr, int kg, int kb, double cos) {
                int red = (int)((col.getRed() * kr * cos / 100.0) + 0.5) ;
                int green = (int)((col.getGreen() * kg * cos / 100.0) + 0.5);
                int blue = (int)((col.getBlue() * kb * cos / 100.0) + 0.5);
//System.out.println("Lam(r, g, b) = " + red + ", " + green + ", " + blue + ", " + cos);
                red = Math.max(0, Math.min(255, red));
                green = Math.max(0, Math.min(255, green));
                blue = Math.max(0, Math.min(255, blue));
                return new Color(red, green, blue);
        }

        /** 点の拡散反射 Lambertの余弦則
         * @param col 光源
         * @param kr 拡散反射率R(%)
         * @param kg 拡散反射率G(%)
         * @param kb 拡散反射率B(%)
         * @param ld 光源角度(度)(0-180)
         * @return 反射色
         */
        private Color pointLambertReflectance(Color col, int kr, int kg, int kb, int ld) {
                int sita = Math.abs(ld - 90);   // 法線となす角
                double rad = (double)sita * Math.PI/180.0;
                double cos = Math.cos(rad);
                return pointLambertReflectance(col, kr, kg, kb, cos);
        }
        
        
        /** 鏡面反射 Phong Reflectance
         * @param col 光源
         * @param ks 鏡面反射率(%)
         * @param nn 鏡面収束度
         * @param ld 光源角度(度)(0-180)
         * @param cd 視点角度(度)(0-180)
         * @return 反射色
         */
        private Color pointPhongReflectance(Color col, int ks, int nn, double cos) {
                double cosn = Math.pow(cos, nn);
                int red = (int)((col.getRed() * ks * cosn / 100.0) + 0.5) ;
                int green = (int)((col.getGreen() * ks * cosn / 100.0) + 0.5);
                int blue = (int)((col.getBlue() * ks * cosn / 100.0) + 0.5);
//System.out.println("Phong(r, g, b) = " + red + ", " + green + ", " + blue);
                red = Math.max(0, Math.min(255, red));
                green = Math.max(0, Math.min(255, green));
                blue = Math.max(0, Math.min(255, blue));
                return new Color(red, green, blue);
        }

        /** 鏡面反射 Phong Reflectance
         * @param col 光源
         * @param ks 鏡面反射率(%)
         * @param nn 鏡面収束度
         * @param ld 光源角度(度)(0-180)
         * @param cd 視点角度(度)(0-180)
         * @return 反射色
         */
        private Color pointPhongReflectance(Color col, int ks, int nn, int ld, int cd) {
                // ld, cd から 光源へのベクトルと視線へのベクトルとのなす角のcosを求める
                int revld = 180 - ld;   // 反射
                int ganma = Math.abs(revld - cd); // γ
                double rad = (double)ganma * Math.PI/180.0;
                double cos = Math.cos(rad);
                return pointPhongReflectance(col, ks, nn, cos);
        }
        
}

/* [<][>][^][v][top][bottom][index][help] */