/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- AnalyzeReflectance
- faceColor
- sphere
- colplus
- pointAmbient
- pointLambertReflectance
- pointLambertReflectance
- pointPhongReflectance
- 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);
}
}