Advertisement
Guest User

HELP

a guest
May 31st, 2016
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.13 KB | None | 0 0
  1. package model;
  2.  
  3. import java.awt.Dimension;
  4. import java.awt.image.BufferedImage;
  5. import java.io.File;
  6. import java.io.FileNotFoundException;
  7. import java.io.FileReader;
  8. import java.io.IOException;
  9. import java.io.StreamTokenizer;
  10. import java.util.ArrayList;
  11. import java.util.LinkedList;
  12. import java.util.List;
  13.  
  14. import model.objects.ObjectCharacteristic;
  15. import model.objects.Shape;
  16. import model.objects.Sphere;
  17. import model.objects.Triangle;
  18. import model.raytracer.Intersection;
  19. import model.raytracer.Ray;
  20. import model.raytracer.RenderParameters;
  21. import model.raytracer.ResultImage;
  22. import model.transform.base.AffineTransform;
  23. import model.transform.transform.Movement;
  24. import model.transform.transform.Proection;
  25. import model.transform.transform.RotateX;
  26. import model.transform.transform.RotateY;
  27. import settings.ModelDefault;
  28. import state.SceneState;
  29. import utilites.FileUtils;
  30.  
  31.  
  32. public class Model {
  33. // ��������� �����������
  34. private RenderParameters renderParameters;
  35. // ���� �� ��������� ����� (�� �����)
  36. private boolean isreadScene = false;
  37. // ��������� ����������
  38. private BufferedImage renderImage;
  39.  
  40. public BufferedImage getRenderImage()
  41. {
  42. return renderImage;
  43. }
  44.  
  45. // ��������� �� ����������� ����������� � ���������� ���������
  46. private boolean isRender;
  47.  
  48. public boolean isRender()
  49. {
  50. return isRender;
  51. }
  52.  
  53. private double zoom = ModelDefault.ZOOM_COFEEICIENT;
  54. private double rotate = ModelDefault.ROTATE_COEFFICIENT;
  55. /**
  56. * �������� �����. �������� ���� ���, � ����� ����� �� ��������.
  57. */
  58. private Scene3D sourceScene;
  59. /**
  60. * ������� ����� (� ������ �������� � ������)
  61. */
  62. private Scene3D currentScene;
  63. /**
  64. * ����������� �����
  65. */
  66. private Scene3D renderScene;
  67. private Camera camera;
  68. /**
  69. * ��������� ����� (����� � �������)
  70. */
  71. private SceneState sceneState = new SceneState();
  72.  
  73. public SceneState getSceneState()
  74. {
  75. return sceneState;
  76. }
  77.  
  78. /**
  79. * �������������� ��� �������� �������� ������ ������ � ������������ �����
  80. */
  81. AffineTransform perspectiveTransform;
  82. // ���������� �� ������ ���������
  83. double far;
  84. // ���������� �� �������� ���������
  85. double near;
  86.  
  87. public Model() {
  88. }
  89.  
  90. /**
  91. * ������ ����� ����� � ��������� ����������� ��������������
  92. *
  93. * @param objects
  94. * ��������� ��������, ����������� �� �����
  95. * @param lights
  96. * ��������� ���������� �����
  97. */
  98. private void initScene(Shape[] objects, List<Light> lights)
  99. {
  100. sourceScene = new Scene3D(objects, lights);
  101. calculateCurrentScene();
  102. camera = new Camera(calculateCameraOrigin());
  103. calculateDistance();
  104. calculatePerspectiveTransform();
  105. }
  106.  
  107. private void calculatePerspectiveTransform()
  108. {
  109. GabariteBox box = sourceScene.getGabariteBox().clone();
  110. // ��������� �������������� � �� ������, ����� �����������
  111. // ���� �������
  112. box.applyTransform(camera.getWorldTransform());
  113. Point3D boxSize = box.getSize();
  114. perspectiveTransform = new Proection(boxSize.getX(), boxSize.getY(),
  115. -1.0 * near, -1.0 * far);
  116. }
  117.  
  118. /**
  119. * ����������� ���������� �� �������� � ������ ����������
  120. */
  121. private void calculateDistance()
  122. {
  123. GabariteBox box = sourceScene.getGabariteBox();
  124. Point3D boxSize = box.getSize();
  125. // ���������� �� ������ �� �������� ������ �����
  126. near = sourceScene.calculateShift(ModelDefault.angle) - boxSize.getZ();
  127. far = near + 1.5 * boxSize.getX();
  128. }
  129.  
  130. /**
  131. * ��������� ����� ������ (�� ��� X)
  132. *
  133. * @return
  134. */
  135. private Point3D calculateCameraOrigin()
  136. {
  137. double shift = sourceScene.calculateShift(ModelDefault.angle);
  138. Point3D origin = new Point3D(.0, .0, shift);
  139. return origin;
  140. }
  141.  
  142. /**
  143. * ��������� ����������� �������������� ��� ������, ����� �������� ��
  144. * �������� � ���� ������
  145. *
  146. */
  147. public void process(Dimension viewPortDimension)
  148. {
  149. if (null == renderScene) {
  150. renderScene = currentScene;
  151. AffineTransform worldToCameraTransform = camera.getWorldTransform();
  152. renderScene.applyTransform(worldToCameraTransform);
  153. renderScene.applyTransform(perspectiveTransform);
  154. renderScene.perspectiveDivide();
  155. // renderScene.clipInCanocicalVolume(CanonicalVolume.canonicalOneCube);
  156. renderScene.transformToViewPort(viewPortDimension);
  157. }
  158. }
  159.  
  160. public Scene3D getResult()
  161. {
  162. return renderScene;
  163. }
  164.  
  165. /**
  166. * �������� �����
  167. *
  168. * @param notches
  169. * ���������� ������� (�������� ������� ����), �� ������� �����
  170. * �������� �����. � ������ �������������� �������� �����
  171. * ������������, � ������ �������������� - ����������
  172. */
  173. public void shiftScene(int notches)
  174. {
  175. double calculatedShift = ((double) notches) * zoom;
  176. AffineTransform shiftTransform = new Movement(.0, .0, calculatedShift);
  177. sceneState.applyShift(shiftTransform);
  178. calculateCurrentScene();
  179. }
  180.  
  181. public void calculateCurrentScene()
  182. {
  183. if (isreadScene) {
  184. currentScene = sourceScene.clone();
  185. AffineTransform resultTransform = sceneState.getRotate().addLeft(
  186. sceneState.getShift());
  187. currentScene.applyTransform(resultTransform);
  188. // ��������� ������� ����� ����������, �� �����
  189. // ������ �� �����������
  190. renderScene = null;
  191. }
  192. }
  193.  
  194. public void rotateScene(double x, double y)
  195. {
  196. double rotateY = rotate * x;
  197. double rotateX = rotate * y;
  198. AffineTransform rotateTransform = new RotateY(rotateY)
  199. .addLeft(new RotateX(rotateX));
  200. sceneState.applyRotate(rotateTransform);
  201. calculateCurrentScene();
  202. }
  203.  
  204.  
  205.  
  206.  
  207. public void readFromFile(File inputFile) throws IOException
  208. {
  209. assert (null != inputFile);
  210. FileReader fileReader = null;
  211. try {
  212. fileReader = new FileReader(inputFile);
  213. StreamTokenizer tokenizer = new StreamTokenizer(fileReader);
  214. assert (null != tokenizer);
  215. tokenizer.slashSlashComments(true);
  216. renderParameters = new RenderParameters();
  217. readBackgroundColor(tokenizer);
  218. readGamma(tokenizer);
  219. // ������� �����������. � ������ ��������� - ������ 1
  220. readInt(tokenizer);
  221. readScatterColor(tokenizer);
  222. List<Light> lights = readLights(tokenizer);
  223. Shape[] objects = readObjects(tokenizer);
  224. clear();
  225. initScene(objects, lights);
  226. isreadScene = true;
  227. calculateCurrentScene();
  228. } catch (FileNotFoundException e) {
  229. throw new IOException(e);
  230. } catch (NumberFormatException e) {
  231. throw new IOException(e);
  232. } finally {
  233. FileUtils.closeQuietly(fileReader);
  234. }
  235. }
  236.  
  237. private void clear()
  238. {
  239. sourceScene = null;
  240. currentScene = null;
  241. renderImage = null;
  242. camera = null;
  243. isreadScene = false;
  244. isRender = false;
  245. sceneState.reset();
  246. }
  247.  
  248. public boolean isIsreadScene()
  249. {
  250. return isreadScene;
  251. }
  252.  
  253. private Shape[] readObjects(StreamTokenizer tokenizer)
  254. {
  255.  
  256. List<Shape> objectList = new ArrayList<>();
  257.  
  258. try{
  259. while (true){
  260. Shape shape = readShape(tokenizer);
  261. if (null != shape) {
  262. objectList.add(shape);
  263. }
  264.  
  265. }
  266. } catch (Exception e){
  267.  
  268. }
  269. Shape[] objects = new Shape[objectList.size()];
  270. objectList.toArray(objects);
  271. return objects;
  272. }
  273.  
  274. /**
  275. * ������ ������ (��������)
  276. *
  277. * @param tokenizer
  278. * @return
  279. */
  280. private Shape readShape(StreamTokenizer tokenizer)
  281. {
  282. String primitiveName = readString(tokenizer).toUpperCase();
  283. // ������ ��������� ����� �������� ������ �
  284. // �������������� � �������
  285. if (primitiveName.equals("TRIANGLE")) {
  286. return readTriagnle(tokenizer);
  287. } else
  288. if (primitiveName.equals("SPHERE")) {
  289. return readSphere(tokenizer);
  290. } else
  291. if (primitiveName.equals("BOX")) {
  292. return readQuadric(tokenizer);
  293. } else {
  294. throw new NumberFormatException("Unknown type of primitive");
  295. }
  296. }
  297.  
  298. /**
  299. * ������ �������. �� ��������� ������ ��������� �� �������� � ����������,
  300. * �� ���������� null
  301. *
  302. * @param tokenizer
  303. * @return
  304. */
  305. private Shape readQuadric(StreamTokenizer tokenizer)
  306. {
  307. // � �������� 16 ����������
  308. for (int i = 0; i < 16; i++) {
  309. readDouble(tokenizer);
  310. }
  311. // � 2 ��������������
  312. readObjectCharacteristic(tokenizer);
  313. readObjectCharacteristic(tokenizer);
  314. return null;
  315. }
  316.  
  317. private Shape readSphere(StreamTokenizer tokenizer)
  318. {
  319. Point3D center = readPoint3D(tokenizer);
  320. double radius = readDouble(tokenizer);
  321. ObjectCharacteristic charact = readObjectCharacteristic(tokenizer);
  322. Sphere sphere = new Sphere(center, radius, charact);
  323. return sphere;
  324. }
  325.  
  326. private Shape readTriagnle(StreamTokenizer tokenizer)
  327. {
  328. Point3D first = readPoint3D(tokenizer);
  329. Point3D second = readPoint3D(tokenizer);
  330. Point3D third = readPoint3D(tokenizer);
  331. ObjectCharacteristic charact = readObjectCharacteristic(tokenizer);
  332. Triangle triangle = new Triangle(first, second, third, charact);
  333. return triangle;
  334. }
  335.  
  336. private Point3D readPoint3D(StreamTokenizer tokenizer)
  337. {
  338. return new Point3D(readDouble(tokenizer), readDouble(tokenizer),
  339. readDouble(tokenizer));
  340. }
  341.  
  342. private ObjectCharacteristic readObjectCharacteristic(
  343. StreamTokenizer tokenizer)
  344. {
  345. ObjectCharacteristic objHCharacteristic = new ObjectCharacteristic();
  346. objHCharacteristic
  347. .setAmbientDiffuseCoefficient(readNormalizedPoint(tokenizer));
  348. objHCharacteristic
  349. .setSpecularCoefficient(readNormalizedPoint(tokenizer));
  350. objHCharacteristic.setPower(readDouble(tokenizer));
  351. // objHCharacteristic.setKt(readDouble(tokenizer));
  352. // objHCharacteristic.setN1(readDouble(tokenizer));
  353. // objHCharacteristic.setN2(readDouble(tokenizer));
  354. return objHCharacteristic;
  355. }
  356.  
  357. private NormalizedPoint readNormalizedPoint(StreamTokenizer tokenizer)
  358. {
  359. double values[] = new double[3];
  360. for (int i = 0; i < 3; i++) {
  361. values[i] = readDouble(tokenizer);
  362. }
  363. return new NormalizedPoint(values);
  364. }
  365.  
  366. /**
  367. * ��������� ��������� �����
  368. *
  369. * @param tokenizer
  370. */
  371. private List<Light> readLights(StreamTokenizer tokenizer)
  372. {
  373. int lightsNumber = readInt(tokenizer);
  374. if (lightsNumber < 1) {
  375. throw new NumberFormatException("Lights number must be more 0");
  376. }
  377. List<Light> lights = new LinkedList<Light>();
  378. for (int i = 0; i < lightsNumber; i++) {
  379. Light light = readLight(tokenizer);
  380. if (null != light) {
  381. lights.add(light);
  382. }
  383. }
  384. return lights;
  385. }
  386.  
  387. private Light readLight(StreamTokenizer tokenizer)
  388. {
  389. Light light = new Light(readPoint3D(tokenizer),
  390. readNormalizedPoint(tokenizer));
  391. return light;
  392. }
  393.  
  394. /**
  395. * ������ �������� ��������� ������������� ��� ����������� �����
  396. *
  397. * @param tokenizer
  398. */
  399. private void readScatterColor(StreamTokenizer tokenizer)
  400. {
  401. renderParameters.setScatterColor(readNormalizedPoint(tokenizer));
  402. }
  403.  
  404. private void readGamma(StreamTokenizer tokenizer)
  405. {
  406. double gamma = readDouble(tokenizer);
  407. renderParameters.setGamma(gamma);
  408. }
  409.  
  410. private void readBackgroundColor(StreamTokenizer tokenizer)
  411. {
  412. int red = readInt(tokenizer);
  413. int green = readInt(tokenizer);
  414. int blue = readInt(tokenizer);
  415. renderParameters.setBackgroundColor(ColorUtils.colorToIntencivity(red,
  416. green, blue));
  417. }
  418.  
  419. private static double readDouble(StreamTokenizer tokenizer)
  420. throws NumberFormatException
  421. {
  422. try {
  423. switch (tokenizer.nextToken()) {
  424. case StreamTokenizer.TT_EOF:
  425. throw new NumberFormatException();
  426. case StreamTokenizer.TT_WORD:
  427. throw new NumberFormatException();
  428. case StreamTokenizer.TT_NUMBER:
  429. return (double) tokenizer.nval;
  430. default:
  431. throw new NumberFormatException();
  432. }
  433. } catch (IOException e) {
  434. throw new NumberFormatException();
  435. }
  436. }
  437.  
  438. private static int readInt(StreamTokenizer tokenizer)
  439. throws NumberFormatException
  440. {
  441. try {
  442. switch (tokenizer.nextToken()) {
  443. case StreamTokenizer.TT_EOF:
  444. throw new NumberFormatException();
  445. case StreamTokenizer.TT_WORD:
  446. throw new NumberFormatException();
  447. case StreamTokenizer.TT_NUMBER:
  448. return (int) (tokenizer.nval);
  449. default:
  450. throw new NumberFormatException();
  451. }
  452. } catch (IOException e) {
  453. throw new NumberFormatException();
  454. }
  455. }
  456.  
  457. private static String readString(StreamTokenizer tokenizer)
  458. throws NumberFormatException
  459. {
  460. try {
  461. switch (tokenizer.nextToken()) {
  462. case StreamTokenizer.TT_EOF:
  463. throw new NumberFormatException();
  464. case StreamTokenizer.TT_WORD:
  465. return tokenizer.sval;
  466. case StreamTokenizer.TT_NUMBER:
  467. throw new NumberFormatException();
  468. default:
  469. throw new NumberFormatException();
  470. }
  471. } catch (IOException e) {
  472. throw new NumberFormatException();
  473. }
  474. }
  475.  
  476. /**
  477. * ��������� ����������� �����. ����� ��������: ��� ������ ����� �� �����
  478. * ��������� (�������� ������) �������� ���, ��������� �� ����� (����� (0,
  479. * 0, 0)) � ������������ � ��� �����. ��� ������ ���� ��������� ���
  480. * ����������� � ��������� �����. ���� ����������� � ��������� ����� ���, ��
  481. * � �������� ��������� ����� � ���� ����� ������������ ���� ����. �
  482. * ��������� ������ (���� ���� �����������) ����������� ���� � ������������
  483. * ��� ���� �����.
  484. *
  485. * @param viewPortDimension
  486. * ���������� ����� ������
  487. */
  488. public void trace(final Dimension viewPortDimension)
  489. {
  490. final ResultImage result = new ResultImage(viewPortDimension,
  491. renderParameters.getGamma());
  492. final Scene3D workScene = sourceScene.clone();
  493. AffineTransform resultTransform = sceneState.getRotate().addLeft(
  494. sceneState.getShift());
  495. workScene.applyTransform(resultTransform);
  496. AffineTransform worldToCameraTransform = camera.getWorldTransform();
  497. workScene.applyTransform(worldToCameraTransform);
  498. // �������� ������ � ������ ����������� ������.
  499. // (���� ������ - width, �� ������� ������ [-width, width]
  500. GabariteBox box = sourceScene.getGabariteBox().clone();
  501. // ��������� �������������� � �� ������, ����� �����������
  502. // ���� �������
  503. box.applyTransform(camera.getWorldTransform());
  504. Point3D boxSize = box.getSize();
  505. final double width = boxSize.getX() * 0.5;
  506. final double height = boxSize.getY() * 0.5;
  507.  
  508. int processorsNumber = Runtime.getRuntime().availableProcessors();
  509. assert( processorsNumber > 0 );
  510.  
  511.  
  512. final Thread[] workers = new Thread[processorsNumber];
  513. for( int i = 0; i < workers.length; i++) {
  514. final int threadNumber = i;
  515. workers[i] = new Thread(() -> {
  516.  
  517.  
  518. // ���������� ������ � ����� ��� ������� ������
  519. int threadWidth = (int) ((double) viewPortDimension.width / (double) workers
  520. .length);
  521. int start = threadNumber * threadWidth;
  522. int end = start + threadWidth;
  523. // ��� ������ ����� �� ����� ��������� �����������
  524. // �� ����
  525. for (int r = 0; r < viewPortDimension.height; r++) {
  526. //for (int c = 0; c < viewPortDimension.width; c++) {
  527. for (int c = start; c < end; c++) {
  528. // ���������� �����, �������� �����������
  529. // �������� ����
  530. double x = width
  531. * (((double) (2 * c) / (double) viewPortDimension.width) - 1.0);
  532. double y = height
  533. * (((double) (2 * r) / (double) viewPortDimension.height) - 1.0);
  534. double z = -1.0 * near;
  535. // ����������� ���, ���������� �� ����� (0, 0, 0)
  536. // (�����, � ������� ����������� ������) � ����� ��
  537. // ����������� ������
  538. // System.out.println(camera.getOrigin());
  539. Ray ray = new Ray(Point3D.Zero, new Point3D(x, y, z));
  540. // �������� �������� ������������� ��� ����� ����
  541. NormalizedPoint calculatedColor = calculateColor(ray, workScene);
  542. // ���������� ��� �������� ��� ������ �����
  543. result.setColor(calculatedColor, r, c);
  544. }
  545. }
  546.  
  547.  
  548. });
  549. workers[i].start();
  550. }
  551.  
  552. for( int i = 0; i < workers.length; i++) {
  553. try {
  554. workers[i].join();
  555. } catch (InterruptedException e) {
  556. e.printStackTrace();
  557. }
  558. }
  559.  
  560. renderImage = result.getImage();
  561. isRender = true;
  562. }
  563.  
  564. /**
  565. * ��������� �������� ������������� (����� � �����) ��� ��������� ����
  566. *
  567. * @param ray
  568. * @param workScene
  569. * @return
  570. */
  571. private NormalizedPoint calculateColor(Ray ray, Scene3D workScene)
  572. {
  573. Intersection bestIntersection = workScene.getBestHit(ray);
  574. // ���� ��� �� ���������� ������� �������
  575. // �� �����, �� ���� - ���� ����
  576. if (null == bestIntersection) {
  577. return renderParameters.getBackgroundColor();
  578. }
  579. Point3D normale = bestIntersection.getNormale().normalize();
  580. Shape hitShape = bestIntersection.getShape();
  581. ObjectCharacteristic characteristic = hitShape
  582. .getObjectCharacteristic();
  583. assert (null != hitShape);
  584. List<Light> lights = currentScene.getLights();
  585. // ���������� (������� �����)
  586. NormalizedPoint intercivity = new NormalizedPoint();
  587. intercivity.add(renderParameters.getScatterColor().multiply(
  588. characteristic.getAmbientCoefficient()));
  589. for (Light light : lights) {
  590. // ����������� ���������� � ����������� �� ���������� �� ���������
  591. double distance = Math.sqrt(bestIntersection.getHitPoint()
  592. .sub(light.getPosition()).length());
  593. double atten = attenuation(distance);
  594. // ��� �������� ����� ���������, �� ��������� �� ������ �����
  595. // ����������� � ���� �� ������� �������. ���� ���������, ��
  596. // ��������� ���������� ����� �� �����������
  597.  
  598. // ��������� ��������� � ���������� ����������
  599. // ������ �� ��������� � �����������
  600. Point3D s = light.getPosition().sub(bestIntersection.getHitPoint())
  601. .normalize();
  602. double lambert = s.scalar(normale);
  603. if (lambert > 0.0) {
  604. NormalizedPoint lambertPart = light.getIntencivity()
  605. .multiply(characteristic.getDiffuseCoefficient())
  606. .multiply(lambert).multiply(atten);
  607. intercivity.add(lambertPart);
  608. }
  609. // ���������� ���������� �����
  610. // �������� ����������� �� �����������
  611. Point3D v = ray.getDirection().invert();
  612. Point3D h = v.sum(s).normalize();
  613. double phong = h.scalar(normale);
  614. if (phong > 0.0) {
  615. phong = Math.pow(phong, characteristic.getPower());
  616. NormalizedPoint phongPart = light.getIntencivity()
  617. .multiply(characteristic.getSpecularCoefficient())
  618. .multiply(phong).multiply(atten);
  619. intercivity.add(phongPart);
  620. }
  621. }
  622. return intercivity;
  623. }
  624.  
  625. /**
  626. * ��������� ���������� ���������� ������������� �����, � ����������� ��
  627. * ���������� �� ���������
  628. *
  629. * @param distance
  630. * @return
  631. */
  632. private double attenuation(double distance)
  633. {
  634. double atten = 1.0 / (1.0 + 0.1 * distance);
  635. return atten;
  636. }
  637.  
  638. /**
  639. * ��� �����. ����������, ��������� �� ����� � ���� ������-�� ���������
  640. *
  641. * @param hitPoint
  642. * ����� ����������� ���� � ������� �� �����
  643. * @param ray
  644. * ���, ��� �������� ������� ����� �����������
  645. * @param workScene
  646. * ������� �����
  647. * @return true, ���� ����� ��������� � ����
  648. */
  649. private boolean isInShadow(Point3D hitPoint, Point3D lightPosition,
  650. Ray ray, Scene3D workScene)
  651. {
  652. // ��������� �� ����� ����� ����� ��� ����, ����� �� ����� t = 0
  653. // �� ���� ����������� "���� �����" � ����� �������� (������
  654. // �������������)
  655. Point3D startPoint = hitPoint.sub(ray.getDirection().multiply(0.00001));
  656. Point3D direction = lightPosition.sub(hitPoint);
  657. Ray shadowRay = new Ray(startPoint, direction);
  658. return workScene.isHit(shadowRay);
  659. }
  660.  
  661. public void resetRenderImage()
  662. {
  663. renderImage = null;
  664. isRender = false;
  665. }
  666. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement