com.barrybecker4.simulation.liquid.rendering.EnvironmentRenderer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bb4-liquid Show documentation
Show all versions of bb4-liquid Show documentation
bb4-simulations java code.
/** Copyright by Barry G. Becker, 2000-2011. Licensed under MIT License: http://www.opensource.org/licenses/MIT */
package com.barrybecker4.simulation.liquid.rendering;
import com.barrybecker4.ui.util.ColorMap;
import com.barrybecker4.simulation.liquid.Logger;
import com.barrybecker4.simulation.liquid.compute.VelocityInterpolator;
import com.barrybecker4.simulation.liquid.model.Cell;
import com.barrybecker4.simulation.liquid.model.Grid;
import com.barrybecker4.simulation.liquid.model.LiquidEnvironment;
import com.barrybecker4.simulation.liquid.model.Particle;
import com.barrybecker4.ui.util.GUIUtil;
import javax.vecmath.Vector2d;
import java.awt.*;
/**
* Renders a specified liquid environment.
*
* @author Barry Becker
*/
public final class EnvironmentRenderer {
// rendering style attributes
private static final Color GRID_COLOR = new Color( 20, 20, 20, 15 );
private static final Color PARTICLE_VELOCITY_COLOR = new Color( 225, 0, 35, 20 );
private static final Stroke PARTICLE_VELOCITY_STROKE = new BasicStroke(0.2f);
private static final Color FACE_VELOCITY_COLOR = new Color( 205, 90, 25, 110 );
private static final Stroke FACE_VELOCITY_STROKE = new BasicStroke(2.0f);
private static final double VELOCITY_SCALE = 8.0;
private static final Color WALL_COLOR = new Color( 100, 210, 170, 150 );
private static final Color TEXT_COLOR = new Color( 10, 10, 170, 200 );
/** scales the size of everything */
private static final double DEFAULT_SCALE = 30;
/* grid offset */
private static final int OFFSET = 10;
private static final ColorMap pressureColorMap_ = new PressureColorMap();
private static final Font BASE_FONT = new Font(GUIUtil.DEFAULT_FONT_FAMILY, Font.PLAIN, 12 );
private double scale_ = DEFAULT_SCALE;
private float wallLineWidth_;
private int particleSize_;
private RenderingOptions options = new RenderingOptions();
LiquidEnvironment env_;
public EnvironmentRenderer(LiquidEnvironment env) {
env_ = env;
}
public void setScale(double scale) {
scale_ = scale;
wallLineWidth_ = (float) (scale / 5.0) + 1;
particleSize_ = (int) (scale / 6.0) + 1;
}
/**
* figure out the biggest scale based in on which dimension is bumped up to first
*/
private void determinScaling(int width, int height) {
Grid grid = env_.getGrid();
double proposedXScale = width / grid.getXDimension();
double proposedYScale = height / grid.getYDimension();
setScale(Math.min(proposedXScale, proposedYScale));
}
public double getScale() {
return scale_;
}
public RenderingOptions getRenderingOptions() {
return options;
}
/**
* Render the Environment on the screen.
*/
public void render(Graphics2D g, int width, int height) {
double time = System.currentTimeMillis();
determinScaling(width, height);
// make sure all the cell statuses are in a consistent state
env_.getGrid().updateCellStatus();
drawGrid(g);
// draw the cells colored by ---pressure--- val
if (options.getShowPressures()) {
renderPressure(g);
}
// draw the ---walls---
drawWalls(g);
drawParticles(g);
if ( options.getShowCellStatus() ) {
drawCellSymbols(g);
}
// draw the ---velocity--- field (and status)
if (options.getShowVelocities()) {
drawCellFaceVelocities(g);
}
double duration = (System.currentTimeMillis() - time) / 100.0;
Logger.log( 1, "time to render: (" + duration + ") " );
}
private double getMaxY() {
return scale_ * env_.getGrid().getYDimension() + OFFSET;
}
/**
* draw the cells/grid_
*/
private void drawGrid(Graphics2D g) {
g.setColor( GRID_COLOR );
Grid grid = env_.getGrid();
int xDim = grid.getXDimension();
int yDim = grid.getYDimension();
int rightEdgePos = (int) (scale_ * xDim);
int bottomEdgePos = (int) (scale_ * yDim);
int maxY = (int)getMaxY();
for (int j = 0; j < yDim; j++ ) // -----
{
int ypos = (int) (j * scale_);
g.drawLine( OFFSET, maxY - ypos, rightEdgePos + OFFSET, maxY - ypos );
}
for (int i = 0; i < xDim; i++ ) // ||||
{
int xpos = (int) (i * scale_);
g.drawLine( xpos + OFFSET, maxY, xpos + OFFSET, maxY - bottomEdgePos );
}
}
/**
* Draw the particles in the liquid in the environment.
*/
private void drawParticles(Graphics2D g) {
// draw the ---particles--- of liquid
double[] a_ = new double[2];
double maxY = getMaxY();
for (Particle p : env_.getParticles()) {
p.get(a_);
g.setColor(getColorForParticle(p));
double offset = -particleSize_/2.0;
int y = (int) (maxY - (scale_ * a_[1] - offset));
g.fillOval((int) (scale_ * a_[0] + offset + OFFSET), y,
particleSize_, particleSize_);
}
if (options.getShowVelocities()) {
drawParticleVelocities(g);
}
}
private Color getColorForParticle(Particle part) {
int green = ((int)part.y % 2) == 0 ? 150 : 50;
int comp = (int) (256.0 * part.getAge() / 20.0);
comp = (comp > 255) ? 255 : comp;
return new Color(comp, green, 255 - comp, 80);
}
private void drawParticleVelocities(Graphics2D g) {
g.setStroke( PARTICLE_VELOCITY_STROKE);
g.setColor( PARTICLE_VELOCITY_COLOR );
double[] a_ = new double[2];
Grid grid = env_.getGrid();
VelocityInterpolator interpolator = new VelocityInterpolator(grid);
double maxY = getMaxY();
for (Particle p : env_.getParticles()) {
if (options.getShowVelocities()) {
Vector2d vel = interpolator.findVelocity(p);
p.get(a_);
double x = (scale_ * a_[0]) + OFFSET;
double xLen = x + VELOCITY_SCALE * vel.x;
double y = maxY - scale_ * a_[1];
double yLen = y - VELOCITY_SCALE * vel.y;
g.drawLine( (int)x, (int)y, (int)xLen, (int)yLen);
}
}
}
/**
* PathColor the squares according to the pressure in that discrete region.
*/
private void renderPressure(Graphics2D g) {
Grid grid = env_.getGrid();
double maxY = getMaxY();
for (int j = 0; j < grid.getYDimension(); j++ ) {
for (int i = 0; i < grid.getXDimension(); i++ ) {
g.setColor( pressureColorMap_.getColorForValue( grid.getCell(i, j).getPressure() ) );
g.fillRect( (int) (scale_ * (i)) + OFFSET, (int) (maxY - scale_ * (j)),
(int) scale_, (int) scale_ );
}
}
}
/**
* Draw walls and boundary.
*/
private void drawWalls(Graphics2D g) {
Stroke wallStroke = new BasicStroke( wallLineWidth_ );
g.setStroke( wallStroke );
int maxY = (int)getMaxY();
g.setColor(WALL_COLOR);
/*
//Stroke stroke = new BasicStroke(wall.getThickness(), BasicStroke.CAP_BUTT,
// BasicStroke.JOIN_ROUND, 10);
for (i=0; i 0 )
// strBuf.append( String.valueOf( nump ) );
g.drawString( strBuf.toString(), x + 6, y + 18 );
}
}
}
/**
* There is a velocity vector in the center of each cell face.
*/
private void drawCellFaceVelocities(Graphics2D g) {
g.setStroke( FACE_VELOCITY_STROKE);
g.setColor( FACE_VELOCITY_COLOR );
Grid grid = env_.getGrid();
double maxY = getMaxY();
for ( int j = 0; j < grid.getYDimension(); j++ ) {
for ( int i = 0; i < grid.getXDimension(); i++ ) {
Cell cell = grid.getCell(i, j);
double u = cell.getU();
double v = cell.getV();
int x = (int) (scale_ * i) + OFFSET;
int xMid = (int) (scale_ * (i + 0.5)) + OFFSET;
int xLen = (int) (scale_ * i + VELOCITY_SCALE * u) + OFFSET;
int y = (int)(maxY - scale_ * j);
int yMid = (int) (maxY - (scale_ * (j + 0.5)));
int yLen = (int) (maxY - (scale_ * j + VELOCITY_SCALE * v )) ;
g.drawLine( xMid, y, xMid, yLen);
g.drawLine( x, yMid, xLen, yMid );
}
}
}
}