1 /* 2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab 3 * Copyright (C) 2012-2013 - Scilab Enterprises - Calixte Denizet 4 * 5 * Copyright (C) 2012 - 2016 - Scilab Enterprises 6 * 7 * This file is hereby licensed under the terms of the GNU GPL v2.0, 8 * pursuant to article 5.3.4 of the CeCILL v.2.1. 9 * This file was originally licensed under the terms of the CeCILL v2.1, 10 * and continues to be available under such terms. 11 * For more information, see the COPYING file which you should have received 12 * along with this program. 13 */ 14 15 package org.scilab.forge.scirenderer.implementation.g2d.motor; 16 17 import java.awt.Color; 18 import java.awt.Dimension; 19 import java.awt.Graphics2D; 20 import java.awt.RenderingHints; 21 import java.awt.Stroke; 22 import java.awt.image.BufferedImage; 23 import java.nio.FloatBuffer; 24 import java.nio.IntBuffer; 25 import java.util.Arrays; 26 import java.util.List; 27 28 import org.scilab.forge.scirenderer.DrawingTools; 29 import org.scilab.forge.scirenderer.buffers.ElementsBuffer; 30 import org.scilab.forge.scirenderer.clipping.ClippingPlane; 31 import org.scilab.forge.scirenderer.implementation.g2d.G2DCanvas; 32 import org.scilab.forge.scirenderer.implementation.g2d.buffers.G2DElementsBuffer; 33 import org.scilab.forge.scirenderer.implementation.g2d.texture.G2DTextureDrawingTools; 34 import org.scilab.forge.scirenderer.implementation.g2d.texture.G2DTextureManager; 35 import org.scilab.forge.scirenderer.shapes.appearance.Appearance; 36 import org.scilab.forge.scirenderer.shapes.geometry.Geometry; 37 import org.scilab.forge.scirenderer.shapes.geometry.Geometry.FaceCullingMode; 38 import org.scilab.forge.scirenderer.texture.AnchorPosition; 39 import org.scilab.forge.scirenderer.texture.Texture; 40 import org.scilab.forge.scirenderer.tranformations.Transformation; 41 import org.scilab.forge.scirenderer.tranformations.Vector3d; 42 import org.scilab.forge.scirenderer.tranformations.Vector3f; 43 44 import org.scilab.forge.scirenderer.lightning.Light; 45 import org.scilab.forge.scirenderer.lightning.LightManager; 46 import org.scilab.forge.scirenderer.implementation.g2d.lighting.G2DLight; 47 import org.scilab.forge.scirenderer.implementation.g2d.lighting.G2DLightManager; 48 import org.scilab.forge.scirenderer.shapes.appearance.Material; 49 50 /** 51 * @author Calixte DENIZET 52 */ 53 public class Motor3D { 54 55 private Transformation transf; 56 private Transformation singleTransf; 57 private FaceCullingMode mode = FaceCullingMode.BOTH; 58 private Graphics2D g2d; 59 private Dimension dim; 60 private G2DTextureDrawingTools textureDrawingTools; 61 private G2DCanvas canvas; 62 63 /** 64 * Default constructor 65 * @param g2d a Graphics2D object where to draw 66 * @param dim the graphic dimensions 67 */ Motor3D(G2DCanvas canvas, Graphics2D g2d, Dimension dim)68 public Motor3D(G2DCanvas canvas, Graphics2D g2d, Dimension dim) { 69 this.canvas = canvas; 70 this.g2d = g2d; 71 this.dim = dim; 72 this.textureDrawingTools = new G2DTextureDrawingTools(g2d); 73 AbstractDrawable3DObject.resetDefaultPrecedence(); 74 } 75 setGraphics(Graphics2D g2d)76 public void setGraphics(Graphics2D g2d) { 77 this.g2d = g2d; 78 this.textureDrawingTools.setGraphics(g2d); 79 } 80 setAntialiased(boolean aa)81 public void setAntialiased(boolean aa) { 82 if (aa) { 83 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 84 } else { 85 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); 86 } 87 } 88 is2DView()89 public boolean is2DView() { 90 return canvas.getMainDrawer().is2DView(); 91 } 92 setClippingPlanes(List<ClippingPlane> clippingPlanes)93 public void setClippingPlanes(List<ClippingPlane> clippingPlanes) { 94 Scene.setClippingPlanes(clippingPlanes); 95 } 96 97 /** 98 * Set the face culling mode 99 * @param mode the mode to set 100 */ setFaceCullingMode(FaceCullingMode mode)101 public void setFaceCullingMode(FaceCullingMode mode) { 102 this.mode = mode; 103 } 104 105 /** 106 * Set the current transformation 107 * @param transf the transformation to set 108 */ setTransformation(Transformation transf, Transformation single)109 public void setTransformation(Transformation transf, Transformation single) { 110 this.transf = transf; 111 this.singleTransf = single; 112 } 113 getCurrentTransformation()114 public Transformation getCurrentTransformation() { 115 return transf; 116 } 117 getCurrentSingleTransformation()118 public Transformation getCurrentSingleTransformation() { 119 return singleTransf; 120 } 121 122 /** 123 * Reset this motor 124 * @param color the filling color 125 */ reset(Color color)126 public void reset(Color color) { 127 transf = null; 128 mode = FaceCullingMode.BOTH; 129 g2d.setColor(color); 130 g2d.fillRect(0, 0, (int) dim.getWidth(), (int) dim.getHeight()); 131 Scene.clear(); 132 } 133 134 /** 135 * Clear the depth buffer 136 */ clearDepth()137 public void clearDepth() { 138 Scene.clearDepth(); 139 } 140 141 /** 142 * Draw the scene in the Graphics2D 143 */ draw()144 public void draw() { 145 Scene.drawRoot(g2d); 146 clean(); 147 } 148 clean()149 public void clean() { 150 Scene.clearAll(); 151 G2DTextureManager.clear(); 152 } 153 drawTexture(DrawingTools drawingTools, BufferedImage image, Texture texture)154 public void drawTexture(DrawingTools drawingTools, BufferedImage image, Texture texture) { 155 try { 156 SpritedRectangle o = new SpritedRectangle(new Vector3d(0, 0, 0), transf, image, texture.getMagnificationFilter()); 157 add(o); 158 } catch (InvalidPolygonException e) { } 159 } 160 161 /** 162 * Add the geometry to the scene 163 * @param drawingTools the DrawingTools 164 * @param geometry the geometry to draw 165 * @param appearance the appearance to use 166 */ draw(DrawingTools drawingTools, Geometry geometry, Appearance appearance)167 public void draw(DrawingTools drawingTools, Geometry geometry, Appearance appearance) { 168 setFaceCullingMode(geometry.getFaceCullingMode()); 169 FloatBuffer vertexBuffer = geometry.getVertices().getData(); 170 171 IntBuffer indicesBuffer = null;; 172 if (geometry.getIndices() != null) { 173 indicesBuffer = geometry.getIndices().getData(); 174 } 175 176 IntBuffer wireIndicesBuffer = null; 177 if (geometry.getWireIndices() != null) { 178 wireIndicesBuffer = geometry.getWireIndices().getData(); 179 } 180 181 FloatBuffer colorBuffer = null; 182 if (geometry.getColors() != null) { 183 colorBuffer = geometry.getColors().getData(); 184 } 185 186 FloatBuffer normalBuffer = null; 187 if (geometry.getNormals() != null) { 188 normalBuffer = geometry.getNormals().getData(); 189 } 190 191 Texture texture = appearance.getTexture(); 192 FloatBuffer textureCoordinatesBuffer = null; 193 BufferedImage image = null; 194 if (texture != null && geometry.getTextureCoordinates() != null) { 195 textureCoordinatesBuffer = geometry.getTextureCoordinates().getData(); 196 image = ((G2DTextureManager.G2DTexture) texture).getImage(); 197 } 198 199 G2DLightManager lm = (G2DLightManager)drawingTools.getLightManager(); 200 lm.setMaterial(appearance.getMaterial()); 201 202 if (geometry.getFillDrawingMode() != Geometry.FillDrawingMode.NONE) { 203 addTriangles(vertexBuffer, normalBuffer, colorBuffer, appearance.getFillColor(), indicesBuffer, textureCoordinatesBuffer, image, texture, geometry.getFillDrawingMode(), lm); 204 } 205 206 if (geometry.getLineDrawingMode() != Geometry.LineDrawingMode.NONE) { 207 if (appearance.getLineColor() == null) { 208 addSegments(vertexBuffer, colorBuffer, null, wireIndicesBuffer, geometry.getLineDrawingMode(), appearance); 209 } else { 210 addSegments(vertexBuffer, null, appearance.getLineColor(), wireIndicesBuffer, geometry.getLineDrawingMode(), appearance); 211 } 212 } 213 } 214 draw(DrawingTools drawingTools, Texture texture, AnchorPosition anchor, ElementsBuffer positions, int offset, int stride, double rotationAngle, org.scilab.forge.scirenderer.shapes.appearance.Color auxColor, ElementsBuffer colors)215 public void draw(DrawingTools drawingTools, Texture texture, AnchorPosition anchor, ElementsBuffer positions, int offset, int stride, double rotationAngle, org.scilab.forge.scirenderer.shapes.appearance.Color auxColor, ElementsBuffer colors) { 216 FloatBuffer positionsBuffer = positions.getData(); 217 float[] buffer; 218 offset = offset < 0 ? 0 : offset; 219 stride = stride < 1 ? 1 : stride; 220 Color[] colorsArray = null; 221 222 positionsBuffer.rewind(); 223 if (positionsBuffer.hasArray()) { 224 buffer = positionsBuffer.array(); 225 } else { 226 buffer = new float[positionsBuffer.limit()]; 227 positionsBuffer.get(buffer); 228 } 229 Vector3d[] verticesArray = getMultiVectors(buffer, transf, false); 230 231 if (colors != null) { 232 FloatBuffer colorsBuffer = colors.getData(); 233 colorsBuffer.rewind(); 234 if (colorsBuffer.hasArray()) { 235 buffer = colorsBuffer.array(); 236 } else { 237 buffer = new float[colorsBuffer.limit()]; 238 colorsBuffer.get(buffer); 239 } 240 colorsArray = getMultiColors(buffer); 241 } 242 243 for (int i = offset; i < verticesArray.length; i += stride) { 244 try { 245 Vector3d v = verticesArray[i]; 246 SpritedRectangle o; 247 if (colorsArray == null) { 248 o = new SpritedRectangle(v, texture, anchor, textureDrawingTools, rotationAngle, null, null); 249 } else { 250 o = new SpritedRectangle(v, texture, anchor, textureDrawingTools, rotationAngle, (Color) auxColor, colorsArray[i]); 251 } 252 add(o); 253 } catch (InvalidPolygonException e) { } 254 } 255 } 256 257 public void draw(DrawingTools drawingTools, Texture texture, AnchorPosition anchor, Vector3d position, double rotationAngle) { 258 try { 259 add(new SpritedRectangle(transf.project(position), texture, anchor, textureDrawingTools, rotationAngle, null, null)); 260 } catch (InvalidPolygonException e) { } 261 } 262 263 /** 264 * Add a Triangle to the scene 265 * @param tri the triangle to add 266 */ 267 private void add(Triangle tri) { 268 final boolean is2d = is2DView(); 269 if (is2d) { 270 Scene.addToRoot(is2d, tri); 271 } else { 272 Vector3d normal = tri.getNormal(); 273 if (normal != null) { 274 //normal = transf.projectDirection(normal); 275 if ((mode == FaceCullingMode.CW && normal.getZ() > 0) || (mode == FaceCullingMode.CCW && normal.getZ() < 0) || mode == FaceCullingMode.BOTH) { 276 Scene.addToRoot(is2d, tri); 277 } 278 } else { 279 Scene.addToRoot(is2d, tri); 280 } 281 } 282 } 283 284 /** 285 * Add a segment to the scene 286 * @param s the segment to add 287 */ 288 private void add(Segment s) { 289 Scene.addToRoot(is2DView(), s); 290 } 291 292 private void add(SpritedRectangle sprite) { 293 Scene.addToRoot(is2DView(), sprite); 294 } 295 296 private void add(PolyLine p) { 297 Scene.addToRoot(is2DView(), p); 298 } 299 300 /** 301 * Get arrays from Buffer 302 * @param vertices a buffer containing vertices 303 * @param colors a buffer containing the colors 304 * @param defaultColor the color to use when colors is null 305 * @param indices a buffer containing the index of the vertices to retrieve 306 * @return an array of length 2 containing the vertices array and the colors array 307 */ 308 private Object[] getArrays(FloatBuffer vertices, FloatBuffer colors, Color defaultColor, FloatBuffer textureCoords, IntBuffer indices) { 309 float[] buffer; 310 Vector3d[] verticesArray; 311 Vector3d[] textureCoordsArray = null; 312 Color[] colorsArray; 313 314 vertices.rewind(); 315 if (vertices.hasArray()) { 316 buffer = vertices.array(); 317 } else { 318 buffer = new float[vertices.limit()]; 319 vertices.get(buffer); 320 } 321 verticesArray = getMultiVectors(buffer, transf, false); 322 323 if (colors != null) { 324 colors.rewind(); 325 if (colors.hasArray()) { 326 buffer = colors.array(); 327 } else { 328 buffer = new float[colors.limit()]; 329 colors.get(buffer); 330 } 331 colorsArray = getMultiColors(buffer); 332 } else { 333 colorsArray = new Color[vertices.limit() / G2DElementsBuffer.ELEMENT_SIZE]; 334 Arrays.fill(colorsArray, defaultColor); 335 } 336 337 if (textureCoords != null) { 338 textureCoords.rewind(); 339 if (textureCoords.hasArray()) { 340 buffer = textureCoords.array(); 341 } else { 342 buffer = new float[textureCoords.limit()]; 343 textureCoords.get(buffer); 344 } 345 textureCoordsArray = getMultiVectors(buffer); 346 } 347 348 if (indices != null) { 349 indices.rewind(); 350 int[] ind; 351 if (indices.hasArray()) { 352 ind = indices.array(); 353 } else { 354 ind = new int[indices.limit()]; 355 indices.get(ind); 356 } 357 Vector3d[] va = new Vector3d[ind.length]; 358 Color[] ca = new Color[ind.length]; 359 Vector3d[] ta = null; 360 if (textureCoords != null) { 361 ta = new Vector3d[ind.length]; 362 } 363 364 for (int i = 0; i < ind.length; i++) { 365 va[i] = verticesArray[ind[i]]; 366 ca[i] = colorsArray[ind[i]]; 367 if (ta != null) { 368 ta[i] = textureCoordsArray[ind[i]]; 369 } 370 } 371 verticesArray = va; 372 colorsArray = ca; 373 textureCoordsArray = ta; 374 } 375 376 return new Object[] {verticesArray, colorsArray, textureCoordsArray}; 377 } 378 379 /** 380 * Convert the buffer vertices into vertices array and put the segments in the scene 381 * @param vertices a buffer containing vertices 382 * @param colors a buffer containing the colors 383 * @param defaultColor the color to use when colors is null 384 * @param indices a buffer containing the index of the vertices to retrieve 385 * @param drawingMode the drawing mode 386 * @param stroke the Stroke to use to draw a segment 387 */ 388 private void addSegments(FloatBuffer vertices, FloatBuffer colors, Color defaultColor, IntBuffer indices, Geometry.LineDrawingMode drawingMode, Appearance appearance) { 389 Object[] arrays = getArrays(vertices, colors, defaultColor, null, indices); 390 Vector3d[] verticesArray = (Vector3d[]) arrays[0]; 391 Color[] colorsArray = (Color[]) arrays[1]; 392 Vector3d[] v; 393 Color[] c; 394 double cumLength = 0; 395 396 if (verticesArray.length <= 1) { 397 return; 398 } 399 400 switch (drawingMode) { 401 case SEGMENTS_STRIP : 402 if (is2DView()) { 403 List<PolyLine> list = PolyLine.getPolyLines(verticesArray, colorsArray, G2DStroke.getStroke(appearance, 0), false); 404 for (PolyLine p : list) { 405 add(p); 406 } 407 } else { 408 for (int i = 0; i < verticesArray.length - 1; i++) { 409 v = new Vector3d[] {verticesArray[i], verticesArray[i + 1]}; 410 c = new Color[] {colorsArray[i], colorsArray[i + 1]}; 411 try { 412 add(new Segment(v, c, G2DStroke.getStroke(appearance, cumLength), false)); 413 cumLength += Segment.getLength(v); 414 } catch (InvalidPolygonException e) { 415 cumLength = 0; 416 } 417 } 418 } 419 break; 420 case SEGMENTS_LOOP : 421 if (is2DView()) { 422 List<PolyLine> list = PolyLine.getPolyLines(verticesArray, colorsArray, G2DStroke.getStroke(appearance, 0), true); 423 for (PolyLine p : list) { 424 add(p); 425 } 426 } else { 427 for (int i = 0; i < verticesArray.length - 1; i++) { 428 v = new Vector3d[] {verticesArray[i], verticesArray[i + 1]}; 429 c = new Color[] {colorsArray[i], colorsArray[i + 1]}; 430 try { 431 add(new Segment(v, c, G2DStroke.getStroke(appearance, cumLength), false)); 432 cumLength += Segment.getLength(v); 433 } catch (InvalidPolygonException e) { 434 cumLength = 0; 435 } 436 } 437 int n = verticesArray.length - 1; 438 v = new Vector3d[] {verticesArray[n], verticesArray[0]}; 439 c = new Color[] {colorsArray[n], colorsArray[0]}; 440 try { 441 add(new Segment(v, c, G2DStroke.getStroke(appearance, cumLength), false)); 442 } catch (InvalidPolygonException e) { } 443 } 444 break; 445 case SEGMENTS : 446 default : 447 for (int i = 0; i < verticesArray.length - 1; i += 2) { 448 v = new Vector3d[] {verticesArray[i], verticesArray[i + 1]}; 449 c = new Color[] {colorsArray[i], colorsArray[i + 1]}; 450 try { 451 add(new Segment(v, c, G2DStroke.getStroke(appearance, 0), is2DView())); 452 } catch (InvalidPolygonException e) { } 453 } 454 break; 455 } 456 } 457 458 /** 459 * Convert the buffer vertices into vertices array and put the triangles in the scene 460 * @param vertices a buffer containing vertices 461 * @param normals a buffer containing the normals (not used) 462 * @param colors a buffer containing the colors 463 * @param defaultColor the color to use when colors is null 464 * @param indices a buffer containing the index of the vertices to retrieve 465 * @param drawingMode the drawing mode 466 */ 467 private void addTriangles(FloatBuffer vertices, FloatBuffer normals, FloatBuffer colors, Color defaultColor, IntBuffer indices, FloatBuffer textureCoords, final BufferedImage image, Texture texture, Geometry.FillDrawingMode drawingMode, G2DLightManager lightManager) { 468 Object[] arrays = getArrays(vertices, colors, defaultColor, textureCoords, indices); 469 Vector3d[] verticesArray = (Vector3d[]) arrays[0]; 470 Color[] colorsArray = (Color[]) arrays[1]; 471 Vector3d[] textureCoordsArray = (Vector3d[]) arrays[2]; 472 Vector3d[] v; 473 Color[] c; 474 Texture.Filter filter = Texture.Filter.NEAREST; 475 476 if (texture != null) { 477 filter = texture.getMagnificationFilter(); 478 } 479 480 colorsArray = applyLighting(vertices, normals, indices, colorsArray, lightManager); 481 482 switch (drawingMode) { 483 case TRIANGLE_FAN : 484 for (int i = 1; i < verticesArray.length - 1; i++) { 485 v = new Vector3d[] {verticesArray[0], verticesArray[i], verticesArray[i + 1]}; 486 try { 487 if (image == null) { 488 c = new Color[] {colorsArray[0], colorsArray[i], colorsArray[i + 1]}; 489 add(new Triangle(v, c, null)); 490 } else { 491 add(new Triangle(v, new Vector3d[] {textureCoordsArray[0], textureCoordsArray[i], textureCoordsArray[i + 1]}, image, filter)); 492 } 493 } catch (InvalidPolygonException e) { } 494 } 495 int n = verticesArray.length - 1; 496 v = new Vector3d[] {verticesArray[0], verticesArray[n], verticesArray[1]}; 497 try { 498 if (image == null) { 499 c = new Color[] {colorsArray[0], colorsArray[n], colorsArray[1]}; 500 add(new Triangle(v, c, null)); 501 } else { 502 add(new Triangle(v, new Vector3d[] {textureCoordsArray[0], textureCoordsArray[n], textureCoordsArray[1]}, image, filter)); 503 } 504 } catch (InvalidPolygonException e) { } 505 break; 506 case TRIANGLE_STRIP : 507 for (int i = 0; i < verticesArray.length - 2; i++) { 508 v = new Vector3d[] {verticesArray[i], verticesArray[i + 1], verticesArray[i + 2]}; 509 try { 510 if (image == null) { 511 c = new Color[] {colorsArray[i], colorsArray[i + 1], colorsArray[i + 2]}; 512 add(new Triangle(v, c, null)); 513 } else { 514 add(new Triangle(v, new Vector3d[] {textureCoordsArray[i], textureCoordsArray[i + 1], textureCoordsArray[i + 2]}, image, filter)); 515 } 516 } catch (InvalidPolygonException e) { } 517 } 518 break; 519 case TRIANGLES : 520 default : 521 for (int i = 0; i < verticesArray.length - 2; i += 3) { 522 v = new Vector3d[] {verticesArray[i], verticesArray[i + 1], verticesArray[i + 2]}; 523 try { 524 if (image == null) { 525 c = new Color[] {colorsArray[i], colorsArray[i + 1], colorsArray[i + 2]}; 526 add(new Triangle(v, c, null)); 527 } else { 528 add(new Triangle(v, new Vector3d[] {textureCoordsArray[i], textureCoordsArray[i + 1], textureCoordsArray[i + 2]}, image, filter)); 529 } 530 } catch (InvalidPolygonException e) { } 531 } 532 break; 533 } 534 } 535 536 /** 537 * Convert an array of float into an array of Vector3d objects 538 * @param vertices an array of float containing (vertices.length / G2DElementsBuffer.ELEMENT_SIZE) vectors coordinates 539 * @param t the transformation to use for the projection 540 * @param dir if true t.projectDirection() is used rather than t.project() 541 * @return an array of Vector3d containing the vertices 542 */ 543 private static final Vector3d[] getMultiVectors(final float[] vertices, final Transformation t, final boolean dir) { 544 Vector3d[] v = new Vector3d[vertices.length / G2DElementsBuffer.ELEMENT_SIZE]; 545 if (dir) { 546 int j = 0; 547 for (int i = 0; i < v.length; i++) { 548 v[i] = t.projectDirection(new Vector3d(vertices[j], vertices[j + 1], vertices[j + 2])); 549 j += G2DElementsBuffer.ELEMENT_SIZE; 550 } 551 } else { 552 int j = 0; 553 for (int i = 0; i < v.length; i++) { 554 v[i] = t.project(new Vector3d(vertices[j], vertices[j + 1], vertices[j + 2])); 555 j += G2DElementsBuffer.ELEMENT_SIZE; 556 } 557 } 558 559 return v; 560 } 561 562 /** 563 * Convert an array of float into an array of Vector3d objects 564 * @param vertices an array of float containing (vertices.length / G2DElementsBuffer.ELEMENT_SIZE) vectors coordinates 565 * @return an array of Vector3d containing the vertices 566 */ 567 private static final Vector3d[] getMultiVectors(final float[] vertices) { 568 Vector3d[] v = new Vector3d[vertices.length / G2DElementsBuffer.ELEMENT_SIZE]; 569 int j = 0; 570 for (int i = 0; i < v.length; i++) { 571 v[i] = new Vector3d(vertices[j], vertices[j + 1], vertices[j + 2]); 572 j += G2DElementsBuffer.ELEMENT_SIZE; 573 } 574 575 return v; 576 } 577 578 /** 579 * Convert a float array into a Color array 580 * @param colors a float array 581 * @return an array of Color 582 */ 583 private static final Color[] getMultiColors(final float[] colors) { 584 Color[] c = new Color[colors.length / G2DElementsBuffer.ELEMENT_SIZE]; 585 int j = 0; 586 Color prev = Color.BLACK; 587 for (int i = 0; i < c.length; i++) { 588 c[i] = new Color(colors[j], colors[j + 1], colors[j + 2], colors[j + 3]); 589 if (prev.equals(c[i])) { 590 c[i] = prev; 591 } 592 prev = c[i]; 593 j += G2DElementsBuffer.ELEMENT_SIZE; 594 } 595 596 return c; 597 } 598 599 /** 600 * Perform per-vertex lighting 601 */ 602 private Color[] applyLighting(FloatBuffer vertices, FloatBuffer normals, IntBuffer index, Color[] colors, G2DLightManager lightManager) { 603 604 if (!lightManager.isLightningEnable() || vertices == null || normals == null 605 || index == null || colors == null) { 606 return colors; 607 } 608 609 Material mat = lightManager.getMaterial(); 610 if (mat == null) { 611 return colors; 612 } 613 614 float[] vertexTransf = lightManager.getVertexTransform(); 615 float[] normalTransf = lightManager.getNormalTransform(); 616 //for transformed vertices camera is at origin. 617 Vector3f camera = new Vector3f(0.f, 0.f , 0.f); 618 Vector3f[] vertexArray = LightHelper.getIndexedVector3f(vertices, index, G2DElementsBuffer.ELEMENT_SIZE, vertexTransf); 619 Vector3f[] normalArray = LightHelper.getIndexedVector3f(normals, index, G2DElementsBuffer.ELEMENT_SIZE, normalTransf); 620 621 for (int i = 0; i < normalArray.length; ++i) { 622 normalArray[i] = normalArray[i].getNormalized(); 623 } 624 625 626 Color[] outColors = new Color[colors.length]; 627 boolean first = true; 628 for (int i = 0; i < lightManager.getLightNumber(); ++i) { 629 G2DLight l = (G2DLight)lightManager.getLight(i); 630 631 if (l == null || !l.isEnable()) { 632 continue; 633 } 634 635 outColors = LightHelper.applyLight(l, mat, camera, vertexArray, normalArray, colors, outColors, vertexTransf, !first); 636 first = false; 637 } 638 return outColors; 639 } 640 } 641