Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package model;
- import java.awt.Dimension;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileReader;
- import java.io.IOException;
- import java.io.StreamTokenizer;
- import java.util.ArrayList;
- import java.util.LinkedList;
- import java.util.List;
- import model.objects.ObjectCharacteristic;
- import model.objects.Shape;
- import model.objects.Sphere;
- import model.objects.Triangle;
- import model.raytracer.Intersection;
- import model.raytracer.Ray;
- import model.raytracer.RenderParameters;
- import model.raytracer.ResultImage;
- import model.transform.base.AffineTransform;
- import model.transform.transform.Movement;
- import model.transform.transform.Proection;
- import model.transform.transform.RotateX;
- import model.transform.transform.RotateY;
- import settings.ModelDefault;
- import state.SceneState;
- import utilites.FileUtils;
- public class Model {
- // ��������� �����������
- private RenderParameters renderParameters;
- // ���� �� ��������� ����� (�� �����)
- private boolean isreadScene = false;
- // ��������� ����������
- private BufferedImage renderImage;
- public BufferedImage getRenderImage()
- {
- return renderImage;
- }
- // ��������� �� ����������� ����������� � ���������� ���������
- private boolean isRender;
- public boolean isRender()
- {
- return isRender;
- }
- private double zoom = ModelDefault.ZOOM_COFEEICIENT;
- private double rotate = ModelDefault.ROTATE_COEFFICIENT;
- /**
- * �������� �����. �������� ���� ���, � ����� ����� �� ��������.
- */
- private Scene3D sourceScene;
- /**
- * ������� ����� (� ������ �������� � ������)
- */
- private Scene3D currentScene;
- /**
- * ����������� �����
- */
- private Scene3D renderScene;
- private Camera camera;
- /**
- * ��������� ����� (����� � �������)
- */
- private SceneState sceneState = new SceneState();
- public SceneState getSceneState()
- {
- return sceneState;
- }
- /**
- * �������������� ��� �������� �������� ������ ������ � ������������ �����
- */
- AffineTransform perspectiveTransform;
- // ���������� �� ������ ���������
- double far;
- // ���������� �� �������� ���������
- double near;
- public Model() {
- }
- /**
- * ������ ����� ����� � ��������� ����������� ��������������
- *
- * @param objects
- * ��������� ��������, ����������� �� �����
- * @param lights
- * ��������� ���������� �����
- */
- private void initScene(Shape[] objects, List<Light> lights)
- {
- sourceScene = new Scene3D(objects, lights);
- calculateCurrentScene();
- camera = new Camera(calculateCameraOrigin());
- calculateDistance();
- calculatePerspectiveTransform();
- }
- private void calculatePerspectiveTransform()
- {
- GabariteBox box = sourceScene.getGabariteBox().clone();
- // ��������� �������������� � �� ������, ����� �����������
- // ���� �������
- box.applyTransform(camera.getWorldTransform());
- Point3D boxSize = box.getSize();
- perspectiveTransform = new Proection(boxSize.getX(), boxSize.getY(),
- -1.0 * near, -1.0 * far);
- }
- /**
- * ����������� ���������� �� �������� � ������ ����������
- */
- private void calculateDistance()
- {
- GabariteBox box = sourceScene.getGabariteBox();
- Point3D boxSize = box.getSize();
- // ���������� �� ������ �� �������� ������ �����
- near = sourceScene.calculateShift(ModelDefault.angle) - boxSize.getZ();
- far = near + 1.5 * boxSize.getX();
- }
- /**
- * ��������� ����� ������ (�� ��� X)
- *
- * @return
- */
- private Point3D calculateCameraOrigin()
- {
- double shift = sourceScene.calculateShift(ModelDefault.angle);
- Point3D origin = new Point3D(.0, .0, shift);
- return origin;
- }
- /**
- * ��������� ����������� �������������� ��� ������, ����� �������� ��
- * �������� � ���� ������
- *
- */
- public void process(Dimension viewPortDimension)
- {
- if (null == renderScene) {
- renderScene = currentScene;
- AffineTransform worldToCameraTransform = camera.getWorldTransform();
- renderScene.applyTransform(worldToCameraTransform);
- renderScene.applyTransform(perspectiveTransform);
- renderScene.perspectiveDivide();
- // renderScene.clipInCanocicalVolume(CanonicalVolume.canonicalOneCube);
- renderScene.transformToViewPort(viewPortDimension);
- }
- }
- public Scene3D getResult()
- {
- return renderScene;
- }
- /**
- * �������� �����
- *
- * @param notches
- * ���������� ������� (�������� ������� ����), �� ������� �����
- * �������� �����. � ������ �������������� �������� �����
- * ������������, � ������ �������������� - ����������
- */
- public void shiftScene(int notches)
- {
- double calculatedShift = ((double) notches) * zoom;
- AffineTransform shiftTransform = new Movement(.0, .0, calculatedShift);
- sceneState.applyShift(shiftTransform);
- calculateCurrentScene();
- }
- public void calculateCurrentScene()
- {
- if (isreadScene) {
- currentScene = sourceScene.clone();
- AffineTransform resultTransform = sceneState.getRotate().addLeft(
- sceneState.getShift());
- currentScene.applyTransform(resultTransform);
- // ��������� ������� ����� ����������, �� �����
- // ������ �� �����������
- renderScene = null;
- }
- }
- public void rotateScene(double x, double y)
- {
- double rotateY = rotate * x;
- double rotateX = rotate * y;
- AffineTransform rotateTransform = new RotateY(rotateY)
- .addLeft(new RotateX(rotateX));
- sceneState.applyRotate(rotateTransform);
- calculateCurrentScene();
- }
- public void readFromFile(File inputFile) throws IOException
- {
- assert (null != inputFile);
- FileReader fileReader = null;
- try {
- fileReader = new FileReader(inputFile);
- StreamTokenizer tokenizer = new StreamTokenizer(fileReader);
- assert (null != tokenizer);
- tokenizer.slashSlashComments(true);
- renderParameters = new RenderParameters();
- readBackgroundColor(tokenizer);
- readGamma(tokenizer);
- // ������� �����������. � ������ ��������� - ������ 1
- readInt(tokenizer);
- readScatterColor(tokenizer);
- List<Light> lights = readLights(tokenizer);
- Shape[] objects = readObjects(tokenizer);
- clear();
- initScene(objects, lights);
- isreadScene = true;
- calculateCurrentScene();
- } catch (FileNotFoundException e) {
- throw new IOException(e);
- } catch (NumberFormatException e) {
- throw new IOException(e);
- } finally {
- FileUtils.closeQuietly(fileReader);
- }
- }
- private void clear()
- {
- sourceScene = null;
- currentScene = null;
- renderImage = null;
- camera = null;
- isreadScene = false;
- isRender = false;
- sceneState.reset();
- }
- public boolean isIsreadScene()
- {
- return isreadScene;
- }
- private Shape[] readObjects(StreamTokenizer tokenizer)
- {
- List<Shape> objectList = new ArrayList<>();
- try{
- while (true){
- Shape shape = readShape(tokenizer);
- if (null != shape) {
- objectList.add(shape);
- }
- }
- } catch (Exception e){
- }
- Shape[] objects = new Shape[objectList.size()];
- objectList.toArray(objects);
- return objects;
- }
- /**
- * ������ ������ (��������)
- *
- * @param tokenizer
- * @return
- */
- private Shape readShape(StreamTokenizer tokenizer)
- {
- String primitiveName = readString(tokenizer).toUpperCase();
- // ������ ��������� ����� �������� ������ �
- // �������������� � �������
- if (primitiveName.equals("TRIANGLE")) {
- return readTriagnle(tokenizer);
- } else
- if (primitiveName.equals("SPHERE")) {
- return readSphere(tokenizer);
- } else
- if (primitiveName.equals("BOX")) {
- return readQuadric(tokenizer);
- } else {
- throw new NumberFormatException("Unknown type of primitive");
- }
- }
- /**
- * ������ �������. �� ��������� ������ ��������� �� �������� � ����������,
- * �� ���������� null
- *
- * @param tokenizer
- * @return
- */
- private Shape readQuadric(StreamTokenizer tokenizer)
- {
- // � �������� 16 ����������
- for (int i = 0; i < 16; i++) {
- readDouble(tokenizer);
- }
- // � 2 ��������������
- readObjectCharacteristic(tokenizer);
- readObjectCharacteristic(tokenizer);
- return null;
- }
- private Shape readSphere(StreamTokenizer tokenizer)
- {
- Point3D center = readPoint3D(tokenizer);
- double radius = readDouble(tokenizer);
- ObjectCharacteristic charact = readObjectCharacteristic(tokenizer);
- Sphere sphere = new Sphere(center, radius, charact);
- return sphere;
- }
- private Shape readTriagnle(StreamTokenizer tokenizer)
- {
- Point3D first = readPoint3D(tokenizer);
- Point3D second = readPoint3D(tokenizer);
- Point3D third = readPoint3D(tokenizer);
- ObjectCharacteristic charact = readObjectCharacteristic(tokenizer);
- Triangle triangle = new Triangle(first, second, third, charact);
- return triangle;
- }
- private Point3D readPoint3D(StreamTokenizer tokenizer)
- {
- return new Point3D(readDouble(tokenizer), readDouble(tokenizer),
- readDouble(tokenizer));
- }
- private ObjectCharacteristic readObjectCharacteristic(
- StreamTokenizer tokenizer)
- {
- ObjectCharacteristic objHCharacteristic = new ObjectCharacteristic();
- objHCharacteristic
- .setAmbientDiffuseCoefficient(readNormalizedPoint(tokenizer));
- objHCharacteristic
- .setSpecularCoefficient(readNormalizedPoint(tokenizer));
- objHCharacteristic.setPower(readDouble(tokenizer));
- // objHCharacteristic.setKt(readDouble(tokenizer));
- // objHCharacteristic.setN1(readDouble(tokenizer));
- // objHCharacteristic.setN2(readDouble(tokenizer));
- return objHCharacteristic;
- }
- private NormalizedPoint readNormalizedPoint(StreamTokenizer tokenizer)
- {
- double values[] = new double[3];
- for (int i = 0; i < 3; i++) {
- values[i] = readDouble(tokenizer);
- }
- return new NormalizedPoint(values);
- }
- /**
- * ��������� ��������� �����
- *
- * @param tokenizer
- */
- private List<Light> readLights(StreamTokenizer tokenizer)
- {
- int lightsNumber = readInt(tokenizer);
- if (lightsNumber < 1) {
- throw new NumberFormatException("Lights number must be more 0");
- }
- List<Light> lights = new LinkedList<Light>();
- for (int i = 0; i < lightsNumber; i++) {
- Light light = readLight(tokenizer);
- if (null != light) {
- lights.add(light);
- }
- }
- return lights;
- }
- private Light readLight(StreamTokenizer tokenizer)
- {
- Light light = new Light(readPoint3D(tokenizer),
- readNormalizedPoint(tokenizer));
- return light;
- }
- /**
- * ������ �������� ��������� ������������� ��� ����������� �����
- *
- * @param tokenizer
- */
- private void readScatterColor(StreamTokenizer tokenizer)
- {
- renderParameters.setScatterColor(readNormalizedPoint(tokenizer));
- }
- private void readGamma(StreamTokenizer tokenizer)
- {
- double gamma = readDouble(tokenizer);
- renderParameters.setGamma(gamma);
- }
- private void readBackgroundColor(StreamTokenizer tokenizer)
- {
- int red = readInt(tokenizer);
- int green = readInt(tokenizer);
- int blue = readInt(tokenizer);
- renderParameters.setBackgroundColor(ColorUtils.colorToIntencivity(red,
- green, blue));
- }
- private static double readDouble(StreamTokenizer tokenizer)
- throws NumberFormatException
- {
- try {
- switch (tokenizer.nextToken()) {
- case StreamTokenizer.TT_EOF:
- throw new NumberFormatException();
- case StreamTokenizer.TT_WORD:
- throw new NumberFormatException();
- case StreamTokenizer.TT_NUMBER:
- return (double) tokenizer.nval;
- default:
- throw new NumberFormatException();
- }
- } catch (IOException e) {
- throw new NumberFormatException();
- }
- }
- private static int readInt(StreamTokenizer tokenizer)
- throws NumberFormatException
- {
- try {
- switch (tokenizer.nextToken()) {
- case StreamTokenizer.TT_EOF:
- throw new NumberFormatException();
- case StreamTokenizer.TT_WORD:
- throw new NumberFormatException();
- case StreamTokenizer.TT_NUMBER:
- return (int) (tokenizer.nval);
- default:
- throw new NumberFormatException();
- }
- } catch (IOException e) {
- throw new NumberFormatException();
- }
- }
- private static String readString(StreamTokenizer tokenizer)
- throws NumberFormatException
- {
- try {
- switch (tokenizer.nextToken()) {
- case StreamTokenizer.TT_EOF:
- throw new NumberFormatException();
- case StreamTokenizer.TT_WORD:
- return tokenizer.sval;
- case StreamTokenizer.TT_NUMBER:
- throw new NumberFormatException();
- default:
- throw new NumberFormatException();
- }
- } catch (IOException e) {
- throw new NumberFormatException();
- }
- }
- /**
- * ��������� ����������� �����. ����� ��������: ��� ������ ����� �� �����
- * ��������� (�������� ������) �������� ���, ��������� �� ����� (����� (0,
- * 0, 0)) � ������������ � ��� �����. ��� ������ ���� ��������� ���
- * ����������� � ��������� �����. ���� ����������� � ��������� ����� ���, ��
- * � �������� ��������� ����� � ���� ����� ������������ ���� ����. �
- * ��������� ������ (���� ���� �����������) ����������� ���� � ������������
- * ��� ���� �����.
- *
- * @param viewPortDimension
- * ���������� ����� ������
- */
- public void trace(final Dimension viewPortDimension)
- {
- final ResultImage result = new ResultImage(viewPortDimension,
- renderParameters.getGamma());
- final Scene3D workScene = sourceScene.clone();
- AffineTransform resultTransform = sceneState.getRotate().addLeft(
- sceneState.getShift());
- workScene.applyTransform(resultTransform);
- AffineTransform worldToCameraTransform = camera.getWorldTransform();
- workScene.applyTransform(worldToCameraTransform);
- // �������� ������ � ������ ����������� ������.
- // (���� ������ - width, �� ������� ������ [-width, width]
- GabariteBox box = sourceScene.getGabariteBox().clone();
- // ��������� �������������� � �� ������, ����� �����������
- // ���� �������
- box.applyTransform(camera.getWorldTransform());
- Point3D boxSize = box.getSize();
- final double width = boxSize.getX() * 0.5;
- final double height = boxSize.getY() * 0.5;
- int processorsNumber = Runtime.getRuntime().availableProcessors();
- assert( processorsNumber > 0 );
- final Thread[] workers = new Thread[processorsNumber];
- for( int i = 0; i < workers.length; i++) {
- final int threadNumber = i;
- workers[i] = new Thread(() -> {
- // ���������� ������ � ����� ��� ������� ������
- int threadWidth = (int) ((double) viewPortDimension.width / (double) workers
- .length);
- int start = threadNumber * threadWidth;
- int end = start + threadWidth;
- // ��� ������ ����� �� ����� ��������� �����������
- // �� ����
- for (int r = 0; r < viewPortDimension.height; r++) {
- //for (int c = 0; c < viewPortDimension.width; c++) {
- for (int c = start; c < end; c++) {
- // ���������� �����, �������� �����������
- // �������� ����
- double x = width
- * (((double) (2 * c) / (double) viewPortDimension.width) - 1.0);
- double y = height
- * (((double) (2 * r) / (double) viewPortDimension.height) - 1.0);
- double z = -1.0 * near;
- // ����������� ���, ���������� �� ����� (0, 0, 0)
- // (�����, � ������� ����������� ������) � ����� ��
- // ����������� ������
- // System.out.println(camera.getOrigin());
- Ray ray = new Ray(Point3D.Zero, new Point3D(x, y, z));
- // �������� �������� ������������� ��� ����� ����
- NormalizedPoint calculatedColor = calculateColor(ray, workScene);
- // ���������� ��� �������� ��� ������ �����
- result.setColor(calculatedColor, r, c);
- }
- }
- });
- workers[i].start();
- }
- for( int i = 0; i < workers.length; i++) {
- try {
- workers[i].join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- renderImage = result.getImage();
- isRender = true;
- }
- /**
- * ��������� �������� ������������� (����� � �����) ��� ��������� ����
- *
- * @param ray
- * @param workScene
- * @return
- */
- private NormalizedPoint calculateColor(Ray ray, Scene3D workScene)
- {
- Intersection bestIntersection = workScene.getBestHit(ray);
- // ���� ��� �� ���������� ������� �������
- // �� �����, �� ���� - ���� ����
- if (null == bestIntersection) {
- return renderParameters.getBackgroundColor();
- }
- Point3D normale = bestIntersection.getNormale().normalize();
- Shape hitShape = bestIntersection.getShape();
- ObjectCharacteristic characteristic = hitShape
- .getObjectCharacteristic();
- assert (null != hitShape);
- List<Light> lights = currentScene.getLights();
- // ���������� (������� �����)
- NormalizedPoint intercivity = new NormalizedPoint();
- intercivity.add(renderParameters.getScatterColor().multiply(
- characteristic.getAmbientCoefficient()));
- for (Light light : lights) {
- // ����������� ���������� � ����������� �� ���������� �� ���������
- double distance = Math.sqrt(bestIntersection.getHitPoint()
- .sub(light.getPosition()).length());
- double atten = attenuation(distance);
- // ��� �������� ����� ���������, �� ��������� �� ������ �����
- // ����������� � ���� �� ������� �������. ���� ���������, ��
- // ��������� ���������� ����� �� �����������
- // ��������� ��������� � ���������� ����������
- // ������ �� ��������� � �����������
- Point3D s = light.getPosition().sub(bestIntersection.getHitPoint())
- .normalize();
- double lambert = s.scalar(normale);
- if (lambert > 0.0) {
- NormalizedPoint lambertPart = light.getIntencivity()
- .multiply(characteristic.getDiffuseCoefficient())
- .multiply(lambert).multiply(atten);
- intercivity.add(lambertPart);
- }
- // ���������� ���������� �����
- // �������� ����������� �� �����������
- Point3D v = ray.getDirection().invert();
- Point3D h = v.sum(s).normalize();
- double phong = h.scalar(normale);
- if (phong > 0.0) {
- phong = Math.pow(phong, characteristic.getPower());
- NormalizedPoint phongPart = light.getIntencivity()
- .multiply(characteristic.getSpecularCoefficient())
- .multiply(phong).multiply(atten);
- intercivity.add(phongPart);
- }
- }
- return intercivity;
- }
- /**
- * ��������� ���������� ���������� ������������� �����, � ����������� ��
- * ���������� �� ���������
- *
- * @param distance
- * @return
- */
- private double attenuation(double distance)
- {
- double atten = 1.0 / (1.0 + 0.1 * distance);
- return atten;
- }
- /**
- * ��� �����. ����������, ��������� �� ����� � ���� ������-�� ���������
- *
- * @param hitPoint
- * ����� ����������� ���� � ������� �� �����
- * @param ray
- * ���, ��� �������� ������� ����� �����������
- * @param workScene
- * ������� �����
- * @return true, ���� ����� ��������� � ����
- */
- private boolean isInShadow(Point3D hitPoint, Point3D lightPosition,
- Ray ray, Scene3D workScene)
- {
- // ��������� �� ����� ����� ����� ��� ����, ����� �� ����� t = 0
- // �� ���� ����������� "���� �����" � ����� �������� (������
- // �������������)
- Point3D startPoint = hitPoint.sub(ray.getDirection().multiply(0.00001));
- Point3D direction = lightPosition.sub(hitPoint);
- Ray shadowRay = new Ray(startPoint, direction);
- return workScene.isHit(shadowRay);
- }
- public void resetRenderImage()
- {
- renderImage = null;
- isRender = false;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement