propane 3.3.1-java → 3.4.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.mvn/wrapper/MavenWrapperDownloader.java +117 -0
- data/.mvn/wrapper/maven-wrapper.properties +2 -3
- data/.travis.yml +9 -0
- data/CHANGELOG.md +7 -5
- data/README.md +1 -1
- data/Rakefile +8 -21
- data/lib/propane/native_folder.rb +16 -11
- data/lib/propane/version.rb +1 -1
- data/mvnw +127 -51
- data/mvnw.cmd +182 -145
- data/pom.rb +50 -48
- data/pom.xml +15 -6
- data/propane.gemspec +3 -3
- data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
- data/src/main/java/monkstone/vecmath/vec3/Vec3.java +2 -2
- data/src/main/java/processing/awt/PGraphicsJava2D.java +1616 -1609
- data/src/main/java/processing/awt/PShapeJava2D.java +273 -265
- data/src/main/java/processing/awt/PSurfaceAWT.java +830 -817
- data/src/main/java/processing/core/PApplet.java +3990 -3990
- data/src/main/java/processing/core/PGraphics.java +37 -37
- data/src/main/java/processing/core/PImage.java +9 -9
- data/src/main/java/processing/core/PMatrix2D.java +6 -0
- data/src/main/java/processing/core/PShape.java +2 -2
- data/src/main/java/processing/core/PShapeOBJ.java +425 -409
- data/src/main/java/processing/core/PShapeSVG.java +167 -159
- data/src/main/java/processing/core/PSurfaceNone.java +10 -0
- data/src/main/java/processing/core/ThinkDifferent.java +7 -14
- data/src/main/java/processing/event/Event.java +7 -6
- metadata +9 -7
@@ -1087,7 +1087,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
1087
1087
|
* obscure rendering features that cannot be implemented in a consistent
|
1088
1088
|
* manner across renderers. Many options will often graduate to standard
|
1089
1089
|
* features instead of hints over time.
|
1090
|
-
*
|
1090
|
+
*
|
1091
1091
|
* hint(ENABLE_OPENGL_4X_SMOOTH) - Enable 4x anti-aliasing for P3D. This
|
1092
1092
|
* can help force anti-aliasing if it has not been enabled by the user. On
|
1093
1093
|
* some graphics cards, this can also be set by the graphics driver's
|
@@ -1095,13 +1095,13 @@ public class PGraphics extends PImage implements PConstants {
|
|
1095
1095
|
* be called immediately after the size() command because it resets the
|
1096
1096
|
* renderer, obliterating any settings and anything drawn (and like size(),
|
1097
1097
|
* re-running the code that came before it again).
|
1098
|
-
*
|
1098
|
+
*
|
1099
1099
|
* hint(DISABLE_OPENGL_2X_SMOOTH) - In Processing 1.0, Processing always
|
1100
1100
|
* enables 2x smoothing when the P3D renderer is used. This hint disables
|
1101
1101
|
* the default 2x smoothing and returns the smoothing behavior found in
|
1102
1102
|
* earlier releases, where smooth() and noSmooth() could be used to enable
|
1103
1103
|
* and disable smoothing, though the quality was inferior.
|
1104
|
-
*
|
1104
|
+
*
|
1105
1105
|
* hint(ENABLE_NATIVE_FONTS) - Use the native version fonts when they are
|
1106
1106
|
* installed, rather than the bitmapped version from a .vlw file. This is
|
1107
1107
|
* useful with the default (or JAVA2D) renderer setting, as it will improve
|
@@ -1110,7 +1110,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
1110
1110
|
* machine (because you have the font installed) but lousy on others'
|
1111
1111
|
* machines if the identical font is unavailable. This option can only be
|
1112
1112
|
* set per-sketch, and must be called before any use of textFont().
|
1113
|
-
*
|
1113
|
+
*
|
1114
1114
|
* hint(DISABLE_DEPTH_TEST) - Disable the zbuffer, allowing you to draw on
|
1115
1115
|
* top of everything at will. When depth testing is disabled, items will be
|
1116
1116
|
* drawn to the screen sequentially, like a painting. This hint is most
|
@@ -1120,14 +1120,14 @@ public class PGraphics extends PImage implements PConstants {
|
|
1120
1120
|
* hint(ENABLE_DEPTH_TEST), but note that with the depth buffer cleared,
|
1121
1121
|
* any 3D drawing that happens later in draw() will ignore existing shapes
|
1122
1122
|
* on the screen.
|
1123
|
-
*
|
1123
|
+
*
|
1124
1124
|
* hint(ENABLE_DEPTH_SORT) - Enable primitive z-sorting of triangles and
|
1125
1125
|
* lines in P3D and OPENGL. This can slow performance considerably, and the
|
1126
1126
|
* algorithm is not yet perfect. Restore the default with hint(DISABLE_DEPTH_SORT).
|
1127
|
-
*
|
1127
|
+
*
|
1128
1128
|
* hint(DISABLE_OPENGL_ERROR_REPORT) - Speeds up the P3D renderer setting
|
1129
1129
|
* by not checking for errors while running. Undo with hint(ENABLE_OPENGL_ERROR_REPORT).
|
1130
|
-
*
|
1130
|
+
*
|
1131
1131
|
* hint(ENABLE_BUFFER_READING) - Depth and stencil buffers in P2D/P3D will be
|
1132
1132
|
* downsampled to make PGL#readPixels work with multisampling. Enabling this
|
1133
1133
|
* introduces some overhead, so if you experience bad performance, disable
|
@@ -1136,17 +1136,17 @@ public class PGraphics extends PImage implements PConstants {
|
|
1136
1136
|
* creating your PGraphics2D/3D. You can restore the default with
|
1137
1137
|
* hint(DISABLE_BUFFER_READING) if you don't plan to read depth from
|
1138
1138
|
* this PGraphics anymore.
|
1139
|
-
*
|
1139
|
+
*
|
1140
1140
|
* hint(ENABLE_KEY_REPEAT) - Auto-repeating key events are discarded
|
1141
1141
|
* by default (works only in P2D/P3D); use this hint to get all the key events
|
1142
1142
|
* (including auto-repeated). Call hint(DISABLE_KEY_REPEAT) to get events
|
1143
1143
|
* only when the key goes physically up or down.
|
1144
|
-
*
|
1144
|
+
*
|
1145
1145
|
* hint(DISABLE_ASYNC_SAVEFRAME) - P2D/P3D only - save() and saveFrame()
|
1146
1146
|
* will not use separate threads for saving and will block until the image
|
1147
1147
|
* is written to the drive. This was the default behavior in 3.0b7 and before.
|
1148
1148
|
* To enable, call hint(ENABLE_ASYNC_SAVEFRAME).
|
1149
|
-
*
|
1149
|
+
*
|
1150
1150
|
* As of release 0149, unhint() has been removed in favor of adding
|
1151
1151
|
* additional ENABLE/DISABLE constants to reset the default behavior. This
|
1152
1152
|
* prevents the double negatives, and also reinforces which hints can be
|
@@ -1208,12 +1208,12 @@ public class PGraphics extends PImage implements PConstants {
|
|
1208
1208
|
* specifies a position in 2D and the <b>vertex()</b> function with three
|
1209
1209
|
* parameters specifies a position in 3D. Each shape will be outlined with
|
1210
1210
|
* the current stroke color and filled with the fill color.
|
1211
|
-
*
|
1211
|
+
*
|
1212
1212
|
* Transformations such as <b>translate()</b>, <b>rotate()</b>, and
|
1213
1213
|
* <b>scale()</b> do not work within <b>beginShape()</b>. It is also not
|
1214
1214
|
* possible to use other shapes, such as <b>ellipse()</b> or <b>rect()</b>
|
1215
1215
|
* within <b>beginShape()</b>.
|
1216
|
-
*
|
1216
|
+
*
|
1217
1217
|
* The P3D renderer settings allow <b>stroke()</b> and <b>fill()</b>
|
1218
1218
|
* settings to be altered per-vertex, however the default P2D renderer does
|
1219
1219
|
* not. Settings such as <b>strokeWeight()</b>, <b>strokeCap()</b>, and
|
@@ -1358,7 +1358,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
1358
1358
|
* Sets a texture to be applied to vertex points. The <b>texture()</b>
|
1359
1359
|
* function must be called between <b>beginShape()</b> and
|
1360
1360
|
* <b>endShape()</b> and before any calls to <b>vertex()</b>.
|
1361
|
-
*
|
1361
|
+
*
|
1362
1362
|
* When textures are in use, the fill color is ignored. Instead, use tint()
|
1363
1363
|
* to specify the color of the texture as it is applied to the shape.
|
1364
1364
|
*
|
@@ -4165,7 +4165,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
4165
4165
|
* CENTER, and RIGHT set the display characteristics of the letters in
|
4166
4166
|
* relation to the values for the <b>x</b> and <b>y</b> parameters of the
|
4167
4167
|
* <b>text()</b> function.
|
4168
|
-
*
|
4168
|
+
*
|
4169
4169
|
* In Processing 0125 and later, an optional second parameter can be used
|
4170
4170
|
* to vertically align the text. BASELINE is the default, and the vertical
|
4171
4171
|
* alignment will be reset to BASELINE if the second parameter is not used.
|
@@ -4173,12 +4173,12 @@ public class PGraphics extends PImage implements PConstants {
|
|
4173
4173
|
* offsets the line based on the current <b>textDescent()</b>. For multiple
|
4174
4174
|
* lines, the final line will be aligned to the bottom, with the previous
|
4175
4175
|
* lines appearing above it.
|
4176
|
-
*
|
4176
|
+
*
|
4177
4177
|
* When using <b>text()</b> with width and height parameters, BASELINE is
|
4178
4178
|
* ignored, and treated as TOP. (Otherwise, text would by default draw
|
4179
4179
|
* outside the box, since BASELINE is the default setting. BASELINE is not
|
4180
4180
|
* a useful drawing mode for text drawn in a rectangle.)
|
4181
|
-
*
|
4181
|
+
*
|
4182
4182
|
* The vertical alignment is based on the value of <b>textAscent()</b>,
|
4183
4183
|
* which many fonts do not specify correctly. It may be necessary to use a
|
4184
4184
|
* hack and offset by a few pixels by hand so that the offset looks
|
@@ -5348,7 +5348,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
5348
5348
|
* Rotates a shape the amount specified by the <b>angle</b> parameter.
|
5349
5349
|
* Angles should be specified in radians (values from 0 to TWO_PI) or
|
5350
5350
|
* converted to radians with the <b>radians()</b> function.
|
5351
|
-
*
|
5351
|
+
*
|
5352
5352
|
* Objects are always rotated around their relative position to the origin
|
5353
5353
|
* and positive numbers rotate objects in a clockwise direction.
|
5354
5354
|
* Transformations apply to everything that happens after and subsequent
|
@@ -5356,7 +5356,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
5356
5356
|
* <b>rotate(HALF_PI)</b> and then <b>rotate(HALF_PI)</b> is the same as
|
5357
5357
|
* <b>rotate(PI)</b>. All tranformations are reset when <b>draw()</b>
|
5358
5358
|
* begins again.
|
5359
|
-
*
|
5359
|
+
*
|
5360
5360
|
* Technically, <b>rotate()</b> multiplies the current transformation
|
5361
5361
|
* matrix by a rotation matrix. This function can be further controlled by
|
5362
5362
|
* the <b>pushMatrix()</b> and <b>popMatrix()</b>.
|
@@ -5559,7 +5559,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
5559
5559
|
* <b>shearX(PI/2)</b> and then <b>shearX(PI/2)</b> is the same as
|
5560
5560
|
* <b>shearX(PI)</b>. If <b>shearX()</b> is called within the
|
5561
5561
|
* <b>draw()</b>, the transformation is reset when the loop begins again.
|
5562
|
-
*
|
5562
|
+
*
|
5563
5563
|
* Technically, <b>shearX()</b> multiplies the current transformation
|
5564
5564
|
* matrix by a rotation matrix. This function can be further controlled by
|
5565
5565
|
* the <b>pushMatrix()</b> and <b>popMatrix()</b> functions.
|
@@ -5593,7 +5593,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
5593
5593
|
* <b>shearY(PI/2)</b> and then <b>shearY(PI/2)</b> is the same as
|
5594
5594
|
* <b>shearY(PI)</b>. If <b>shearY()</b> is called within the
|
5595
5595
|
* <b>draw()</b>, the transformation is reset when the loop begins again.
|
5596
|
-
*
|
5596
|
+
*
|
5597
5597
|
* Technically, <b>shearY()</b> multiplies the current transformation
|
5598
5598
|
* matrix by a rotation matrix. This function can be further controlled by
|
5599
5599
|
* the <b>pushMatrix()</b> and <b>popMatrix()</b> functions.
|
@@ -6115,7 +6115,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
6115
6115
|
* transformations (scale, rotate, translate, etc.) The X value can be used
|
6116
6116
|
* to place an object in space relative to the location of the original
|
6117
6117
|
* point once the transformations are no longer in use.
|
6118
|
-
*
|
6118
|
+
*
|
6119
6119
|
* In the example, the <b>modelX()</b>, <b>modelY()</b>, and
|
6120
6120
|
* <b>modelZ()</b> functions record the location of a box in space after
|
6121
6121
|
* being placed using a series of translate and rotate commands. After
|
@@ -6408,7 +6408,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
6408
6408
|
*
|
6409
6409
|
* Sets the width of the stroke used for lines, points, and the border
|
6410
6410
|
* around shapes. All widths are set in units of pixels.
|
6411
|
-
*
|
6411
|
+
*
|
6412
6412
|
* When drawing with P3D, series of connected lines (such as the stroke
|
6413
6413
|
* around a polygon, triangle, or ellipse) produce unattractive results
|
6414
6414
|
* when a thick stroke weight is set (<a
|
@@ -6437,7 +6437,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
6437
6437
|
* are either mitered, beveled, or rounded and specified with the
|
6438
6438
|
* corresponding parameters MITER, BEVEL, and ROUND. The default joint is
|
6439
6439
|
* MITER.
|
6440
|
-
*
|
6440
|
+
*
|
6441
6441
|
* This function is not available with the P3D renderer, (<a
|
6442
6442
|
* href="http://code.google.com/p/processing/issues/detail?id=123">see
|
6443
6443
|
* Issue 123</a>). More information about the renderers can be found in the
|
@@ -6461,7 +6461,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
6461
6461
|
* Sets the style for rendering line endings. These ends are either
|
6462
6462
|
* squared, extended, or rounded and specified with the corresponding
|
6463
6463
|
* parameters SQUARE, PROJECT, and ROUND. The default cap is ROUND.
|
6464
|
-
*
|
6464
|
+
*
|
6465
6465
|
* This function is not available with the P3D renderer (<a
|
6466
6466
|
* href="http://code.google.com/p/processing/issues/detail?id=123">see
|
6467
6467
|
* Issue 123</a>). More information about the renderers can be found in the
|
@@ -6512,7 +6512,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
6512
6512
|
* is either specified in terms of the RGB or HSB color depending on the
|
6513
6513
|
* current <b>colorMode()</b> (the default color space is RGB, with each
|
6514
6514
|
* value in the range from 0 to 255).
|
6515
|
-
*
|
6515
|
+
*
|
6516
6516
|
* When using hexadecimal notation to specify a color, use "#" or "0x"
|
6517
6517
|
* before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six
|
6518
6518
|
* digits to specify a color (the way colors are specified in HTML and
|
@@ -6520,7 +6520,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
6520
6520
|
* hexadecimal value must be specified with eight characters; the first two
|
6521
6521
|
* characters define the alpha component and the remainder the red, green,
|
6522
6522
|
* and blue components.
|
6523
|
-
*
|
6523
|
+
*
|
6524
6524
|
* The value for the parameter "gray" must be less than or equal to the
|
6525
6525
|
* current maximum value as specified by <b>colorMode()</b>. The default
|
6526
6526
|
* maximum value is 255.
|
@@ -6753,7 +6753,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
6753
6753
|
* color is either specified in terms of the RGB or HSB color depending on
|
6754
6754
|
* the current <b>colorMode()</b> (the default color space is RGB, with
|
6755
6755
|
* each value in the range from 0 to 255).
|
6756
|
-
*
|
6756
|
+
*
|
6757
6757
|
* When using hexadecimal notation to specify a color, use "#" or "0x"
|
6758
6758
|
* before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six
|
6759
6759
|
* digits to specify a color (the way colors are specified in HTML and
|
@@ -6761,11 +6761,11 @@ public class PGraphics extends PImage implements PConstants {
|
|
6761
6761
|
* hexadecimal value must be specified with eight characters; the first two
|
6762
6762
|
* characters define the alpha component and the remainder the red, green,
|
6763
6763
|
* and blue components.
|
6764
|
-
*
|
6764
|
+
*
|
6765
6765
|
* The value for the parameter "gray" must be less than or equal to the
|
6766
6766
|
* current maximum value as specified by <b>colorMode()</b>. The default
|
6767
6767
|
* maximum value is 255.
|
6768
|
-
*
|
6768
|
+
*
|
6769
6769
|
* To change the color of an image (or a texture), use tint().
|
6770
6770
|
*
|
6771
6771
|
* ( end auto-generated )
|
@@ -7313,13 +7313,13 @@ public class PGraphics extends PImage implements PConstants {
|
|
7313
7313
|
* of the Processing window. The default background is light gray. In the
|
7314
7314
|
* <b>draw()</b> function, the background color is used to clear the
|
7315
7315
|
* display window at the beginning of each frame.
|
7316
|
-
*
|
7316
|
+
*
|
7317
7317
|
* An image can also be used as the background for a sketch, however its
|
7318
7318
|
* width and height must be the same size as the sketch window. To resize
|
7319
7319
|
* an image 'b' to the size of the sketch window, use b.resize(width, height).
|
7320
|
-
*
|
7320
|
+
*
|
7321
7321
|
* Images used as background will ignore the current <b>tint()</b> setting.
|
7322
|
-
*
|
7322
|
+
*
|
7323
7323
|
* It is not possible to use transparency (alpha) in background colors with
|
7324
7324
|
* the main drawing surface, however they will work properly with <b>createGraphics()</b>.
|
7325
7325
|
*
|
@@ -7450,13 +7450,13 @@ public class PGraphics extends PImage implements PConstants {
|
|
7450
7450
|
/**
|
7451
7451
|
* Takes an RGB or ARGB image and sets it as the background.
|
7452
7452
|
* The width and height of the image must be the same size as the sketch.
|
7453
|
-
* Use image.resize(width, height) to make short work of such a task
|
7454
|
-
*
|
7453
|
+
* Use image.resize(width, height) to make short work of such a task.
|
7454
|
+
*
|
7455
7455
|
* Note that even if the image is set as RGB, the high 8 bits of each pixel
|
7456
7456
|
* should be set opaque (0xFF000000) because the image data will be copied
|
7457
7457
|
* directly to the screen, and non-opaque background images may have strange
|
7458
|
-
* behavior. Use image.filter(OPAQUE) to handle this easily
|
7459
|
-
*
|
7458
|
+
* behavior. Use image.filter(OPAQUE) to handle this easily.
|
7459
|
+
*
|
7460
7460
|
* When using 3D, this will also clear the zbuffer (if it exists).
|
7461
7461
|
*
|
7462
7462
|
* @param image PImage to set as background (must be same size as the sketch window)
|
@@ -8349,7 +8349,7 @@ public class PGraphics extends PImage implements PConstants {
|
|
8349
8349
|
* Return true if this renderer should be drawn to the screen. Defaults to
|
8350
8350
|
* returning true, since nearly all renderers are on-screen beasts. But can
|
8351
8351
|
* be overridden for subclasses like PDF so that a window doesn't open up.
|
8352
|
-
*
|
8352
|
+
*
|
8353
8353
|
* A better name? showFrame, displayable, isVisible, visible, shouldDisplay,
|
8354
8354
|
* what to call this?
|
8355
8355
|
*/
|
@@ -40,11 +40,11 @@ import java.awt.image.*;
|
|
40
40
|
* fields for the <b>width</b> and <b>height</b> of the image, as well as
|
41
41
|
* an array called <b>pixels[]</b> that contains the values for every pixel
|
42
42
|
* in the image. The methods described below allow easy access to the
|
43
|
-
* image's pixels and alpha channel and simplify the process of compositing
|
44
|
-
*
|
43
|
+
* image's pixels and alpha channel and simplify the process of compositing.
|
44
|
+
* using the <b>pixels[]</b> array, be sure to use the
|
45
45
|
* <b>loadPixels()</b> method on the image to make sure that the pixel data
|
46
|
-
* is properly loaded
|
47
|
-
*
|
46
|
+
* is properly loaded.
|
47
|
+
* create a new image, use the <b>createImage()</b> function. Do not
|
48
48
|
* use the syntax <b>new PImage()</b>.
|
49
49
|
*
|
50
50
|
* ( end auto-generated )
|
@@ -184,11 +184,11 @@ public class PImage implements PConstants, Cloneable {
|
|
184
184
|
* pixel in the image. A group of methods, described below, allow easy
|
185
185
|
* access to the image's pixels and alpha channel and simplify the process
|
186
186
|
* of compositing.
|
187
|
-
*
|
187
|
+
*
|
188
188
|
* Before using the <b>pixels[]</b> array, be sure to use the
|
189
189
|
* <b>loadPixels()</b> method on the image to make sure that the pixel data
|
190
190
|
* is properly loaded.
|
191
|
-
*
|
191
|
+
*
|
192
192
|
* To create a new image, use the <b>createImage()</b> function (do not use
|
193
193
|
* <b>new PImage()</b>).
|
194
194
|
* ( end auto-generated )
|
@@ -478,7 +478,7 @@ public class PImage implements PConstants, Cloneable {
|
|
478
478
|
*
|
479
479
|
* Loads the pixel data for the image into its <b>pixels[]</b> array. This
|
480
480
|
* function must always be called before reading from or writing to <b>pixels[]</b>.
|
481
|
-
*
|
481
|
+
* renderers may or may not seem to require <b>loadPixels()</b>
|
482
482
|
* or <b>updatePixels()</b>. However, the rule is that any time you want to
|
483
483
|
* manipulate the <b>pixels[]</b> array, you must first call
|
484
484
|
* <b>loadPixels()</b>, and after changes have been made, call
|
@@ -517,14 +517,14 @@ public class PImage implements PConstants, Cloneable {
|
|
517
517
|
* Updates the image with the data in its <b>pixels[]</b> array. Use in
|
518
518
|
* conjunction with <b>loadPixels()</b>. If you're only reading pixels from
|
519
519
|
* the array, there's no need to call <b>updatePixels()</b>.
|
520
|
-
*
|
520
|
+
* renderers may or may not seem to require <b>loadPixels()</b>
|
521
521
|
* or <b>updatePixels()</b>. However, the rule is that any time you want to
|
522
522
|
* manipulate the <b>pixels[]</b> array, you must first call
|
523
523
|
* <b>loadPixels()</b>, and after changes have been made, call
|
524
524
|
* <b>updatePixels()</b>. Even if the renderer may not seem to use this
|
525
525
|
* function in the current Processing release, this will always be subject
|
526
526
|
* to change.
|
527
|
-
*
|
527
|
+
*
|
528
528
|
* Currently, none of the renderers use the additional parameters to
|
529
529
|
* <b>updatePixels()</b>, however this may be implemented in the future.
|
530
530
|
*
|
@@ -151,11 +151,13 @@ public class PMatrix2D implements PMatrix {
|
|
151
151
|
*
|
152
152
|
* @throws IllegalArgumentException
|
153
153
|
*/
|
154
|
+
@Override
|
154
155
|
public void translate(float x, float y, float z) {
|
155
156
|
throw new IllegalArgumentException("Cannot use translate(x, y, z) on a PMatrix2D.");
|
156
157
|
}
|
157
158
|
|
158
159
|
// Implementation roughly based on AffineTransform.
|
160
|
+
@Override
|
159
161
|
public void rotate(float angle) {
|
160
162
|
float s = sin(angle);
|
161
163
|
float c = cos(angle);
|
@@ -175,6 +177,7 @@ public class PMatrix2D implements PMatrix {
|
|
175
177
|
*
|
176
178
|
* @throws IllegalArgumentException
|
177
179
|
*/
|
180
|
+
@Override
|
178
181
|
public void rotateX(float angle) {
|
179
182
|
throw new IllegalArgumentException("Cannot use rotateX() on a PMatrix2D.");
|
180
183
|
}
|
@@ -197,14 +200,17 @@ public class PMatrix2D implements PMatrix {
|
|
197
200
|
*
|
198
201
|
* @throws IllegalArgumentException
|
199
202
|
*/
|
203
|
+
@Override
|
200
204
|
public void rotate(float angle, float v0, float v1, float v2) {
|
201
205
|
throw new IllegalArgumentException("Cannot use this version of rotate() on a PMatrix2D.");
|
202
206
|
}
|
203
207
|
|
208
|
+
@Override
|
204
209
|
public void scale(float s) {
|
205
210
|
scale(s, s);
|
206
211
|
}
|
207
212
|
|
213
|
+
@Override
|
208
214
|
public void scale(float sx, float sy) {
|
209
215
|
m00 *= sx;
|
210
216
|
m01 *= sy;
|
@@ -405,7 +405,7 @@ public class PShape implements PConstants {
|
|
405
405
|
*
|
406
406
|
* Returns a boolean value "true" if the image is set to be visible, "false"
|
407
407
|
* if not. This is modified with the <b>setVisible()</b> parameter.
|
408
|
-
*
|
408
|
+
*
|
409
409
|
* The visibility of a shape is usually controlled by whatever program
|
410
410
|
* created the SVG file. For instance, this parameter is controlled by
|
411
411
|
* showing or hiding the shape in the layers palette in Adobe Illustrator.
|
@@ -427,7 +427,7 @@ public class PShape implements PConstants {
|
|
427
427
|
*
|
428
428
|
* Sets the shape to be visible or invisible. This is determined by the
|
429
429
|
* value of the <b>visible</b> parameter.
|
430
|
-
*
|
430
|
+
*
|
431
431
|
* The visibility of a shape is usually controlled by whatever program
|
432
432
|
* created the SVG file. For instance, this parameter is controlled by
|
433
433
|
* showing or hiding the shape in the layers palette in Adobe Illustrator.
|
@@ -2,6 +2,7 @@ package processing.core;
|
|
2
2
|
|
3
3
|
import java.io.BufferedReader;
|
4
4
|
import java.io.File;
|
5
|
+
import java.io.IOException;
|
5
6
|
import java.util.ArrayList;
|
6
7
|
import java.util.HashMap;
|
7
8
|
import java.util.Map;
|
@@ -19,444 +20,459 @@ import java.util.Map;
|
|
19
20
|
*/
|
20
21
|
public class PShapeOBJ extends PShape {
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
/**
|
24
|
+
* Initializes a new OBJ Object with the given filename.
|
25
|
+
*
|
26
|
+
* @param parent
|
27
|
+
* @param filename
|
28
|
+
*/
|
29
|
+
public PShapeOBJ(PApplet parent, String filename) {
|
30
|
+
this(parent, parent.createReader(filename), getBasePath(parent, filename));
|
31
|
+
}
|
32
|
+
|
33
|
+
public PShapeOBJ(PApplet parent, BufferedReader reader) {
|
34
|
+
this(parent, reader, "");
|
35
|
+
}
|
36
|
+
|
37
|
+
public PShapeOBJ(PApplet parent, BufferedReader reader, String basePath) {
|
38
|
+
ArrayList<OBJFace> faces = new ArrayList<>();
|
39
|
+
ArrayList<OBJMaterial> materials = new ArrayList<>();
|
40
|
+
ArrayList<PVector> coords = new ArrayList<>();
|
41
|
+
ArrayList<PVector> normals = new ArrayList<>();
|
42
|
+
ArrayList<PVector> texcoords = new ArrayList<>();
|
43
|
+
parseOBJ(parent, basePath, reader,
|
44
|
+
faces, materials, coords, normals, texcoords);
|
45
|
+
|
46
|
+
// The OBJ geometry is stored with each face in a separate child shape.
|
47
|
+
parent = null;
|
48
|
+
family = GROUP;
|
49
|
+
addChildren(faces, materials, coords, normals, texcoords);
|
50
|
+
}
|
51
|
+
|
52
|
+
protected PShapeOBJ(OBJFace face, OBJMaterial mtl,
|
53
|
+
ArrayList<PVector> coords,
|
54
|
+
ArrayList<PVector> normals,
|
55
|
+
ArrayList<PVector> texcoords) {
|
56
|
+
family = GEOMETRY;
|
57
|
+
switch (face.vertIdx.size()) {
|
58
|
+
case 3:
|
59
|
+
kind = TRIANGLES;
|
60
|
+
break;
|
61
|
+
case 4:
|
62
|
+
kind = QUADS;
|
63
|
+
break;
|
64
|
+
default:
|
65
|
+
kind = POLYGON;
|
66
|
+
break;
|
27
67
|
}
|
28
68
|
|
29
|
-
|
30
|
-
|
69
|
+
stroke = false;
|
70
|
+
fill = true;
|
71
|
+
|
72
|
+
// Setting material properties for the new face
|
73
|
+
fillColor = rgbaValue(mtl.kd);
|
74
|
+
ambientColor = rgbaValue(mtl.ka);
|
75
|
+
specularColor = rgbaValue(mtl.ks);
|
76
|
+
shininess = mtl.ns;
|
77
|
+
if (mtl.kdMap != null) {
|
78
|
+
// If current material is textured, then tinting the texture using the
|
79
|
+
// diffuse color.
|
80
|
+
tintColor = rgbaValue(mtl.kd, mtl.d);
|
31
81
|
}
|
32
82
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
ArrayList<PVector> texcoords = new ArrayList<PVector>();
|
39
|
-
parseOBJ(parent, basePath, reader,
|
40
|
-
faces, materials, coords, normals, texcoords);
|
41
|
-
|
42
|
-
// The OBJ geometry is stored with each face in a separate child shape.
|
43
|
-
parent = null;
|
44
|
-
family = GROUP;
|
45
|
-
addChildren(faces, materials, coords, normals, texcoords);
|
46
|
-
}
|
47
|
-
|
48
|
-
protected PShapeOBJ(OBJFace face, OBJMaterial mtl,
|
49
|
-
ArrayList<PVector> coords,
|
50
|
-
ArrayList<PVector> normals,
|
51
|
-
ArrayList<PVector> texcoords) {
|
52
|
-
family = GEOMETRY;
|
53
|
-
if (face.vertIdx.size() == 3) {
|
54
|
-
kind = TRIANGLES;
|
55
|
-
} else if (face.vertIdx.size() == 4) {
|
56
|
-
kind = QUADS;
|
57
|
-
} else {
|
58
|
-
kind = POLYGON;
|
59
|
-
}
|
60
|
-
|
61
|
-
stroke = false;
|
62
|
-
fill = true;
|
63
|
-
|
64
|
-
// Setting material properties for the new face
|
65
|
-
fillColor = rgbaValue(mtl.kd);
|
66
|
-
ambientColor = rgbaValue(mtl.ka);
|
67
|
-
specularColor = rgbaValue(mtl.ks);
|
68
|
-
shininess = mtl.ns;
|
69
|
-
if (mtl.kdMap != null) {
|
70
|
-
// If current material is textured, then tinting the texture using the
|
71
|
-
// diffuse color.
|
72
|
-
tintColor = rgbaValue(mtl.kd, mtl.d);
|
73
|
-
}
|
74
|
-
|
75
|
-
vertexCount = face.vertIdx.size();
|
76
|
-
vertices = new float[vertexCount][12];
|
77
|
-
for (int j = 0; j < face.vertIdx.size(); j++) {
|
78
|
-
int vertIdx, normIdx, texIdx;
|
79
|
-
PVector vert, norms, tex;
|
80
|
-
|
81
|
-
vert = norms = tex = null;
|
82
|
-
|
83
|
-
vertIdx = face.vertIdx.get(j).intValue() - 1;
|
84
|
-
vert = coords.get(vertIdx);
|
85
|
-
|
86
|
-
if (j < face.normIdx.size()) {
|
87
|
-
normIdx = face.normIdx.get(j).intValue() - 1;
|
88
|
-
if (-1 < normIdx) {
|
89
|
-
norms = normals.get(normIdx);
|
90
|
-
}
|
91
|
-
}
|
92
|
-
|
93
|
-
if (j < face.texIdx.size()) {
|
94
|
-
texIdx = face.texIdx.get(j).intValue() - 1;
|
95
|
-
if (-1 < texIdx) {
|
96
|
-
tex = texcoords.get(texIdx);
|
97
|
-
}
|
98
|
-
}
|
83
|
+
vertexCount = face.vertIdx.size();
|
84
|
+
vertices = new float[vertexCount][12];
|
85
|
+
for (int j = 0; j < face.vertIdx.size(); j++) {
|
86
|
+
int vertIdx, normIdx, texIdx;
|
87
|
+
PVector vert, norms, tex;
|
99
88
|
|
100
|
-
|
101
|
-
vertices[j][Y] = vert.y;
|
102
|
-
vertices[j][Z] = vert.z;
|
89
|
+
vert = norms = tex = null;
|
103
90
|
|
104
|
-
|
105
|
-
|
106
|
-
vertices[j][PGraphics.B] = mtl.kd.z;
|
107
|
-
vertices[j][PGraphics.A] = 1;
|
91
|
+
vertIdx = face.vertIdx.get(j) - 1;
|
92
|
+
vert = coords.get(vertIdx);
|
108
93
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
}
|
114
|
-
|
115
|
-
if (tex != null) {
|
116
|
-
vertices[j][PGraphics.U] = tex.x;
|
117
|
-
vertices[j][PGraphics.V] = tex.y;
|
118
|
-
}
|
119
|
-
|
120
|
-
if (mtl != null && mtl.kdMap != null) {
|
121
|
-
image = mtl.kdMap;
|
122
|
-
}
|
94
|
+
if (j < face.normIdx.size()) {
|
95
|
+
normIdx = face.normIdx.get(j) - 1;
|
96
|
+
if (-1 < normIdx) {
|
97
|
+
norms = normals.get(normIdx);
|
123
98
|
}
|
124
|
-
|
125
|
-
|
126
|
-
protected void addChildren(ArrayList<OBJFace> faces,
|
127
|
-
ArrayList<OBJMaterial> materials,
|
128
|
-
ArrayList<PVector> coords,
|
129
|
-
ArrayList<PVector> normals,
|
130
|
-
ArrayList<PVector> texcoords) {
|
131
|
-
int mtlIdxCur = -1;
|
132
|
-
OBJMaterial mtl = null;
|
133
|
-
for (int i = 0; i < faces.size(); i++) {
|
134
|
-
OBJFace face = faces.get(i);
|
135
|
-
|
136
|
-
// Getting current material.
|
137
|
-
if (mtlIdxCur != face.matIdx || face.matIdx == -1) {
|
138
|
-
// To make sure that at least we get the default material
|
139
|
-
mtlIdxCur = PApplet.max(0, face.matIdx);
|
140
|
-
mtl = materials.get(mtlIdxCur);
|
141
|
-
}
|
99
|
+
}
|
142
100
|
|
143
|
-
|
144
|
-
|
145
|
-
|
101
|
+
if (j < face.texIdx.size()) {
|
102
|
+
texIdx = face.texIdx.get(j) - 1;
|
103
|
+
if (-1 < texIdx) {
|
104
|
+
tex = texcoords.get(texIdx);
|
146
105
|
}
|
106
|
+
}
|
107
|
+
|
108
|
+
vertices[j][X] = vert.x;
|
109
|
+
vertices[j][Y] = vert.y;
|
110
|
+
vertices[j][Z] = vert.z;
|
111
|
+
|
112
|
+
vertices[j][PGraphics.R] = mtl.kd.x;
|
113
|
+
vertices[j][PGraphics.G] = mtl.kd.y;
|
114
|
+
vertices[j][PGraphics.B] = mtl.kd.z;
|
115
|
+
vertices[j][PGraphics.A] = 1;
|
116
|
+
|
117
|
+
if (norms != null) {
|
118
|
+
vertices[j][PGraphics.NX] = norms.x;
|
119
|
+
vertices[j][PGraphics.NY] = norms.y;
|
120
|
+
vertices[j][PGraphics.NZ] = norms.z;
|
121
|
+
}
|
122
|
+
|
123
|
+
if (tex != null) {
|
124
|
+
vertices[j][PGraphics.U] = tex.x;
|
125
|
+
vertices[j][PGraphics.V] = tex.y;
|
126
|
+
}
|
127
|
+
|
128
|
+
if (mtl.kdMap != null) {
|
129
|
+
image = mtl.kdMap;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
protected void addChildren(ArrayList<OBJFace> faces,
|
135
|
+
ArrayList<OBJMaterial> materials,
|
136
|
+
ArrayList<PVector> coords,
|
137
|
+
ArrayList<PVector> normals,
|
138
|
+
ArrayList<PVector> texcoords) {
|
139
|
+
int mtlIdxCur = -1;
|
140
|
+
OBJMaterial mtl = null;
|
141
|
+
for (int i = 0; i < faces.size(); i++) {
|
142
|
+
OBJFace face = faces.get(i);
|
143
|
+
|
144
|
+
// Getting current material.
|
145
|
+
if (mtlIdxCur != face.matIdx || face.matIdx == -1) {
|
146
|
+
// To make sure that at least we get the default material
|
147
|
+
mtlIdxCur = PApplet.max(0, face.matIdx);
|
148
|
+
mtl = materials.get(mtlIdxCur);
|
149
|
+
}
|
150
|
+
|
151
|
+
// Creating child shape for current face.
|
152
|
+
PShape child = new PShapeOBJ(face, mtl, coords, normals, texcoords);
|
153
|
+
addChild(child);
|
147
154
|
}
|
155
|
+
}
|
156
|
+
|
157
|
+
static protected void parseOBJ(PApplet parent, String path,
|
158
|
+
BufferedReader reader,
|
159
|
+
ArrayList<OBJFace> faces,
|
160
|
+
ArrayList<OBJMaterial> materials,
|
161
|
+
ArrayList<PVector> coords,
|
162
|
+
ArrayList<PVector> normals,
|
163
|
+
ArrayList<PVector> texcoords) {
|
164
|
+
Map<String, Integer> mtlTable = new HashMap<>();
|
165
|
+
int mtlIdxCur = -1;
|
166
|
+
boolean readv, readvn, readvt;
|
167
|
+
try {
|
168
|
+
|
169
|
+
readv = readvn = readvt = false;
|
170
|
+
String line;
|
171
|
+
String gname = "object";
|
172
|
+
while ((line = reader.readLine()) != null) {
|
173
|
+
// Parse the line.
|
174
|
+
line = line.trim();
|
175
|
+
if (line.equals("") || line.indexOf('#') == 0) {
|
176
|
+
// Empty line of comment, ignore line
|
177
|
+
continue;
|
178
|
+
}
|
148
179
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
180
|
+
// The below patch/hack comes from Carlos Tomas Marti and is a
|
181
|
+
// fix for single backslashes in Rhino obj files
|
182
|
+
// BEGINNING OF RHINO OBJ FILES HACK
|
183
|
+
// Statements can be broken in multiple lines using '\' at the
|
184
|
+
// end of a line.
|
185
|
+
// In regular expressions, the backslash is also an escape
|
186
|
+
// character.
|
187
|
+
// The regular expression \\ matches a single backslash. This
|
188
|
+
// regular expression as a Java string, becomes "\\\\".
|
189
|
+
// That's right: 4 backslashes to match a single one.
|
190
|
+
while (line.contains("\\")) {
|
191
|
+
line = line.split("\\\\")[0];
|
192
|
+
final String s = reader.readLine();
|
193
|
+
if (s != null) {
|
194
|
+
line += s;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
// END OF RHINO OBJ FILES HACK
|
198
|
+
|
199
|
+
String[] parts = line.split("\\s+");
|
200
|
+
// if not a blank line, process the line.
|
201
|
+
if (parts.length > 0) {
|
202
|
+
switch (parts[0]) {
|
203
|
+
case "v": {
|
204
|
+
// vertex
|
205
|
+
PVector tempv = new PVector(Float.valueOf(parts[1]),
|
206
|
+
Float.valueOf(parts[2]),
|
207
|
+
Float.valueOf(parts[3]));
|
208
|
+
coords.add(tempv);
|
209
|
+
readv = true;
|
210
|
+
break;
|
211
|
+
}
|
212
|
+
case "vn":
|
213
|
+
// normal
|
214
|
+
PVector tempn = new PVector(Float.valueOf(parts[1]),
|
215
|
+
Float.valueOf(parts[2]),
|
216
|
+
Float.valueOf(parts[3]));
|
217
|
+
normals.add(tempn);
|
218
|
+
readvn = true;
|
219
|
+
break;
|
220
|
+
case "vt": {
|
221
|
+
// uv, inverting v to take into account Processing's inverted Y axis
|
222
|
+
// with respect to OpenGL.
|
223
|
+
PVector tempv = new PVector(Float.valueOf(parts[1]),
|
224
|
+
1 - Float.valueOf(parts[2]));
|
225
|
+
texcoords.add(tempv);
|
226
|
+
readvt = true;
|
227
|
+
break;
|
228
|
+
}
|
229
|
+
// Object name is ignored, for now.
|
230
|
+
case "o":
|
231
|
+
break;
|
232
|
+
case "mtllib":
|
233
|
+
if (parts[1] != null) {
|
234
|
+
String fn = parts[1];
|
235
|
+
if (!fn.contains(File.separator) && !path.equals("")) {
|
236
|
+
// Relative file name, adding the base path.
|
237
|
+
fn = path + File.separator + fn;
|
238
|
+
}
|
239
|
+
BufferedReader mreader = parent.createReader(fn);
|
240
|
+
if (mreader != null) {
|
241
|
+
parseMTL(parent, fn, path, mreader, materials, mtlTable);
|
242
|
+
mreader.close();
|
170
243
|
}
|
244
|
+
}
|
245
|
+
break;
|
246
|
+
case "g":
|
247
|
+
gname = 1 < parts.length ? parts[1] : "";
|
248
|
+
break;
|
249
|
+
case "usemtl":
|
250
|
+
// Getting index of current active material (will be applied on
|
251
|
+
// all subsequent faces).
|
252
|
+
if (parts[1] != null) {
|
253
|
+
String mtlname = parts[1];
|
254
|
+
if (mtlTable.containsKey(mtlname)) {
|
255
|
+
Integer tempInt = mtlTable.get(mtlname);
|
256
|
+
mtlIdxCur = tempInt;
|
257
|
+
} else {
|
258
|
+
mtlIdxCur = -1;
|
259
|
+
}
|
260
|
+
}
|
261
|
+
break;
|
262
|
+
case "f":
|
263
|
+
// Face setting
|
264
|
+
OBJFace face = new OBJFace();
|
265
|
+
face.matIdx = mtlIdxCur;
|
266
|
+
face.name = gname;
|
267
|
+
for (int i = 1; i < parts.length; i++) {
|
268
|
+
String seg = parts[i];
|
269
|
+
|
270
|
+
if (seg.indexOf("/") > 0) {
|
271
|
+
String[] forder = seg.split("/");
|
272
|
+
|
273
|
+
if (forder.length > 2) {
|
274
|
+
// Getting vertex and texture and normal indexes.
|
275
|
+
if (forder[0].length() > 0 && readv) {
|
276
|
+
face.vertIdx.add(Integer.valueOf(forder[0]));
|
277
|
+
}
|
171
278
|
|
172
|
-
|
173
|
-
|
174
|
-
// BEGINNING OF RHINO OBJ FILES HACK
|
175
|
-
// Statements can be broken in multiple lines using '\' at the
|
176
|
-
// end of a line.
|
177
|
-
// In regular expressions, the backslash is also an escape
|
178
|
-
// character.
|
179
|
-
// The regular expression \\ matches a single backslash. This
|
180
|
-
// regular expression as a Java string, becomes "\\\\".
|
181
|
-
// That's right: 4 backslashes to match a single one.
|
182
|
-
while (line.contains("\\")) {
|
183
|
-
line = line.split("\\\\")[0];
|
184
|
-
final String s = reader.readLine();
|
185
|
-
if (s != null) {
|
186
|
-
line += s;
|
279
|
+
if (forder[1].length() > 0 && readvt) {
|
280
|
+
face.texIdx.add(Integer.valueOf(forder[1]));
|
187
281
|
}
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
if (
|
195
|
-
|
196
|
-
PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(),
|
197
|
-
Float.valueOf(parts[2]).floatValue(),
|
198
|
-
Float.valueOf(parts[3]).floatValue());
|
199
|
-
coords.add(tempv);
|
200
|
-
readv = true;
|
201
|
-
} else if (parts[0].equals("vn")) {
|
202
|
-
// normal
|
203
|
-
PVector tempn = new PVector(Float.valueOf(parts[1]).floatValue(),
|
204
|
-
Float.valueOf(parts[2]).floatValue(),
|
205
|
-
Float.valueOf(parts[3]).floatValue());
|
206
|
-
normals.add(tempn);
|
207
|
-
readvn = true;
|
208
|
-
} else if (parts[0].equals("vt")) {
|
209
|
-
// uv, inverting v to take into account Processing's inverted Y axis
|
210
|
-
// with respect to OpenGL.
|
211
|
-
PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(),
|
212
|
-
1 - Float.valueOf(parts[2]).
|
213
|
-
floatValue());
|
214
|
-
texcoords.add(tempv);
|
215
|
-
readvt = true;
|
216
|
-
} else if (parts[0].equals("o")) {
|
217
|
-
// Object name is ignored, for now.
|
218
|
-
} else if (parts[0].equals("mtllib")) {
|
219
|
-
if (parts[1] != null) {
|
220
|
-
String fn = parts[1];
|
221
|
-
if (fn.indexOf(File.separator) == -1 && !path.equals("")) {
|
222
|
-
// Relative file name, adding the base path.
|
223
|
-
fn = path + File.separator + fn;
|
224
|
-
}
|
225
|
-
BufferedReader mreader = parent.createReader(fn);
|
226
|
-
if (mreader != null) {
|
227
|
-
parseMTL(parent, fn, path, mreader, materials, mtlTable);
|
228
|
-
mreader.close();
|
229
|
-
}
|
230
|
-
}
|
231
|
-
} else if (parts[0].equals("g")) {
|
232
|
-
gname = 1 < parts.length ? parts[1] : "";
|
233
|
-
} else if (parts[0].equals("usemtl")) {
|
234
|
-
// Getting index of current active material (will be applied on
|
235
|
-
// all subsequent faces).
|
236
|
-
if (parts[1] != null) {
|
237
|
-
String mtlname = parts[1];
|
238
|
-
if (mtlTable.containsKey(mtlname)) {
|
239
|
-
Integer tempInt = mtlTable.get(mtlname);
|
240
|
-
mtlIdxCur = tempInt.intValue();
|
241
|
-
} else {
|
242
|
-
mtlIdxCur = -1;
|
243
|
-
}
|
244
|
-
}
|
245
|
-
} else if (parts[0].equals("f")) {
|
246
|
-
// Face setting
|
247
|
-
OBJFace face = new OBJFace();
|
248
|
-
face.matIdx = mtlIdxCur;
|
249
|
-
face.name = gname;
|
250
|
-
|
251
|
-
for (int i = 1; i < parts.length; i++) {
|
252
|
-
String seg = parts[i];
|
253
|
-
|
254
|
-
if (seg.indexOf("/") > 0) {
|
255
|
-
String[] forder = seg.split("/");
|
256
|
-
|
257
|
-
if (forder.length > 2) {
|
258
|
-
// Getting vertex and texture and normal indexes.
|
259
|
-
if (forder[0].length() > 0 && readv) {
|
260
|
-
face.vertIdx.add(Integer.valueOf(forder[0]));
|
261
|
-
}
|
262
|
-
|
263
|
-
if (forder[1].length() > 0 && readvt) {
|
264
|
-
face.texIdx.add(Integer.valueOf(forder[1]));
|
265
|
-
}
|
266
|
-
|
267
|
-
if (forder[2].length() > 0 && readvn) {
|
268
|
-
face.normIdx.add(Integer.valueOf(forder[2]));
|
269
|
-
}
|
270
|
-
} else if (forder.length > 1) {
|
271
|
-
// Getting vertex and texture/normal indexes.
|
272
|
-
if (forder[0].length() > 0 && readv) {
|
273
|
-
face.vertIdx.add(Integer.valueOf(forder[0]));
|
274
|
-
}
|
275
|
-
|
276
|
-
if (forder[1].length() > 0) {
|
277
|
-
if (readvt) {
|
278
|
-
face.texIdx.add(Integer.valueOf(forder[1]));
|
279
|
-
} else if (readvn) {
|
280
|
-
face.normIdx.add(Integer.valueOf(forder[1]));
|
281
|
-
}
|
282
|
-
|
283
|
-
}
|
284
|
-
|
285
|
-
} else if (forder.length > 0) {
|
286
|
-
// Getting vertex index only.
|
287
|
-
if (forder[0].length() > 0 && readv) {
|
288
|
-
face.vertIdx.add(Integer.valueOf(forder[0]));
|
289
|
-
}
|
290
|
-
}
|
291
|
-
} else {
|
292
|
-
// Getting vertex index only.
|
293
|
-
if (seg.length() > 0 && readv) {
|
294
|
-
face.vertIdx.add(Integer.valueOf(seg));
|
295
|
-
}
|
296
|
-
}
|
297
|
-
}
|
298
|
-
|
299
|
-
faces.add(face);
|
282
|
+
|
283
|
+
if (forder[2].length() > 0 && readvn) {
|
284
|
+
face.normIdx.add(Integer.valueOf(forder[2]));
|
285
|
+
}
|
286
|
+
} else if (forder.length > 1) {
|
287
|
+
// Getting vertex and texture/normal indexes.
|
288
|
+
if (forder[0].length() > 0 && readv) {
|
289
|
+
face.vertIdx.add(Integer.valueOf(forder[0]));
|
300
290
|
}
|
301
|
-
}
|
302
|
-
}
|
303
291
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
292
|
+
if (forder[1].length() > 0) {
|
293
|
+
if (readvt) {
|
294
|
+
face.texIdx.add(Integer.valueOf(forder[1]));
|
295
|
+
} else if (readvn) {
|
296
|
+
face.normIdx.add(Integer.valueOf(forder[1]));
|
297
|
+
}
|
309
298
|
|
310
|
-
|
311
|
-
e.printStackTrace();
|
312
|
-
}
|
313
|
-
}
|
299
|
+
}
|
314
300
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
try {
|
320
|
-
String line;
|
321
|
-
OBJMaterial currentMtl = null;
|
322
|
-
while ((line = reader.readLine()) != null) {
|
323
|
-
// Parse the line
|
324
|
-
line = line.trim();
|
325
|
-
String parts[] = line.split("\\s+");
|
326
|
-
if (parts.length > 0) {
|
327
|
-
// Extract the material data.
|
328
|
-
if (parts[0].equals("newmtl")) {
|
329
|
-
// Starting new material.
|
330
|
-
String mtlname = parts[1];
|
331
|
-
currentMtl = addMaterial(mtlname, materials, materialsHash);
|
332
|
-
} else {
|
333
|
-
if (currentMtl == null) {
|
334
|
-
currentMtl = addMaterial("material" + materials.size(),
|
335
|
-
materials, materialsHash);
|
336
|
-
}
|
337
|
-
if (parts[0].equals("map_Kd") && parts.length > 1) {
|
338
|
-
// Loading texture map.
|
339
|
-
String texname = parts[1];
|
340
|
-
if (texname.indexOf(File.separator) == -1 && !path.equals("")) {
|
341
|
-
// Relative file name, adding the base path.
|
342
|
-
texname = path + File.separator + texname;
|
343
|
-
}
|
344
|
-
|
345
|
-
File file = new File(parent.dataPath(texname));
|
346
|
-
if (file.exists()) {
|
347
|
-
currentMtl.kdMap = parent.loadImage(texname);
|
348
|
-
} else {
|
349
|
-
System.err.println("The texture map \"" + texname + "\" "
|
350
|
-
+ "in the materials definition file \"" + mtlfn + "\" "
|
351
|
-
+ "is missing or inaccessible, make sure "
|
352
|
-
+ "the URL is valid or that the file has been "
|
353
|
-
+ "added to your sketch and is readable.");
|
354
|
-
}
|
355
|
-
} else if (parts[0].equals("Ka") && parts.length > 3) {
|
356
|
-
// The ambient color of the material
|
357
|
-
currentMtl.ka.x = Float.valueOf(parts[1]).floatValue();
|
358
|
-
currentMtl.ka.y = Float.valueOf(parts[2]).floatValue();
|
359
|
-
currentMtl.ka.z = Float.valueOf(parts[3]).floatValue();
|
360
|
-
} else if (parts[0].equals("Kd") && parts.length > 3) {
|
361
|
-
// The diffuse color of the material
|
362
|
-
currentMtl.kd.x = Float.valueOf(parts[1]).floatValue();
|
363
|
-
currentMtl.kd.y = Float.valueOf(parts[2]).floatValue();
|
364
|
-
currentMtl.kd.z = Float.valueOf(parts[3]).floatValue();
|
365
|
-
} else if (parts[0].equals("Ks") && parts.length > 3) {
|
366
|
-
// The specular color weighted by the specular coefficient
|
367
|
-
currentMtl.ks.x = Float.valueOf(parts[1]).floatValue();
|
368
|
-
currentMtl.ks.y = Float.valueOf(parts[2]).floatValue();
|
369
|
-
currentMtl.ks.z = Float.valueOf(parts[3]).floatValue();
|
370
|
-
} else if ((parts[0].equals("d")
|
371
|
-
|| parts[0].equals("Tr")) && parts.length > 1) {
|
372
|
-
// Reading the alpha transparency.
|
373
|
-
currentMtl.d = Float.valueOf(parts[1]).floatValue();
|
374
|
-
} else if (parts[0].equals("Ns") && parts.length > 1) {
|
375
|
-
// The specular component of the Phong shading model
|
376
|
-
currentMtl.ns = Float.valueOf(parts[1]).floatValue();
|
377
|
-
}
|
301
|
+
} else if (forder.length > 0) {
|
302
|
+
// Getting vertex index only.
|
303
|
+
if (forder[0].length() > 0 && readv) {
|
304
|
+
face.vertIdx.add(Integer.valueOf(forder[0]));
|
378
305
|
}
|
306
|
+
}
|
307
|
+
} else {
|
308
|
+
// Getting vertex index only.
|
309
|
+
if (seg.length() > 0 && readv) {
|
310
|
+
face.vertIdx.add(Integer.valueOf(seg));
|
311
|
+
}
|
379
312
|
}
|
380
|
-
|
381
|
-
|
382
|
-
|
313
|
+
}
|
314
|
+
faces.add(face);
|
315
|
+
break;
|
316
|
+
default:
|
317
|
+
break;
|
318
|
+
}
|
383
319
|
}
|
384
|
-
|
320
|
+
}
|
385
321
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
materials.add(currentMtl);
|
392
|
-
return currentMtl;
|
393
|
-
}
|
322
|
+
if (materials.isEmpty()) {
|
323
|
+
// No materials definition so far. Adding one default material.
|
324
|
+
OBJMaterial defMtl = new OBJMaterial();
|
325
|
+
materials.add(defMtl);
|
326
|
+
}
|
394
327
|
|
395
|
-
|
396
|
-
return 0xFF000000 | ((int) (color.x * 255) << 16)
|
397
|
-
| ((int) (color.y * 255) << 8)
|
398
|
-
| (int) (color.z * 255);
|
328
|
+
} catch (IOException | NumberFormatException e) {
|
399
329
|
}
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
330
|
+
}
|
331
|
+
|
332
|
+
static protected void parseMTL(PApplet parent, String mtlfn, String path,
|
333
|
+
BufferedReader reader,
|
334
|
+
ArrayList<OBJMaterial> materials,
|
335
|
+
Map<String, Integer> materialsHash) {
|
336
|
+
try {
|
337
|
+
String line;
|
338
|
+
OBJMaterial currentMtl = null;
|
339
|
+
while ((line = reader.readLine()) != null) {
|
340
|
+
// Parse the line
|
341
|
+
line = line.trim();
|
342
|
+
String parts[] = line.split("\\s+");
|
343
|
+
if (parts.length > 0) {
|
344
|
+
// Extract the material data.
|
345
|
+
if (parts[0].equals("newmtl")) {
|
346
|
+
// Starting new material.
|
347
|
+
String mtlname = parts[1];
|
348
|
+
currentMtl = addMaterial(mtlname, materials, materialsHash);
|
349
|
+
} else {
|
350
|
+
if (currentMtl == null) {
|
351
|
+
currentMtl = addMaterial("material" + materials.size(),
|
352
|
+
materials, materialsHash);
|
353
|
+
}
|
354
|
+
if (parts[0].equals("map_Kd") && parts.length > 1) {
|
355
|
+
// Loading texture map.
|
356
|
+
String texname = parts[1];
|
357
|
+
if (!texname.contains(File.separator) && !path.equals("")) {
|
358
|
+
// Relative file name, adding the base path.
|
359
|
+
texname = path + File.separator + texname;
|
360
|
+
}
|
361
|
+
|
362
|
+
File file = new File(parent.dataPath(texname));
|
363
|
+
if (file.exists()) {
|
364
|
+
currentMtl.kdMap = parent.loadImage(texname);
|
365
|
+
} else {
|
366
|
+
System.err.println("The texture map \"" + texname + "\" "
|
367
|
+
+ "in the materials definition file \"" + mtlfn + "\" "
|
368
|
+
+ "is missing or inaccessible, make sure "
|
369
|
+
+ "the URL is valid or that the file has been "
|
370
|
+
+ "added to your sketch and is readable.");
|
371
|
+
}
|
372
|
+
} else if (parts[0].equals("Ka") && parts.length > 3) {
|
373
|
+
// The ambient color of the material
|
374
|
+
currentMtl.ka.x = Float.valueOf(parts[1]);
|
375
|
+
currentMtl.ka.y = Float.valueOf(parts[2]);
|
376
|
+
currentMtl.ka.z = Float.valueOf(parts[3]);
|
377
|
+
} else if (parts[0].equals("Kd") && parts.length > 3) {
|
378
|
+
// The diffuse color of the material
|
379
|
+
currentMtl.kd.x = Float.valueOf(parts[1]);
|
380
|
+
currentMtl.kd.y = Float.valueOf(parts[2]);
|
381
|
+
currentMtl.kd.z = Float.valueOf(parts[3]);
|
382
|
+
} else if (parts[0].equals("Ks") && parts.length > 3) {
|
383
|
+
// The specular color weighted by the specular coefficient
|
384
|
+
currentMtl.ks.x = Float.valueOf(parts[1]);
|
385
|
+
currentMtl.ks.y = Float.parseFloat(parts[2]);
|
386
|
+
currentMtl.ks.z = Float.parseFloat(parts[3]);
|
387
|
+
} else if ((parts[0].equals("d")
|
388
|
+
|| parts[0].equals("Tr")) && parts.length > 1) {
|
389
|
+
// Reading the alpha transparency.
|
390
|
+
currentMtl.d = Float.parseFloat(parts[1]);
|
391
|
+
} else if (parts[0].equals("Ns") && parts.length > 1) {
|
392
|
+
// The specular component of the Phong shading model
|
393
|
+
currentMtl.ns = Float.parseFloat(parts[1]);
|
394
|
+
}
|
395
|
+
}
|
423
396
|
}
|
397
|
+
}
|
398
|
+
} catch (IOException | NumberFormatException e) {
|
424
399
|
}
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
400
|
+
}
|
401
|
+
|
402
|
+
protected static OBJMaterial addMaterial(String mtlname,
|
403
|
+
ArrayList<OBJMaterial> materials,
|
404
|
+
Map<String, Integer> materialsHash) {
|
405
|
+
OBJMaterial currentMtl = new OBJMaterial(mtlname);
|
406
|
+
materialsHash.put(mtlname, materials.size());
|
407
|
+
materials.add(currentMtl);
|
408
|
+
return currentMtl;
|
409
|
+
}
|
410
|
+
|
411
|
+
protected static int rgbaValue(PVector color) {
|
412
|
+
return 0xFF000000 | ((int) (color.x * 255) << 16)
|
413
|
+
| ((int) (color.y * 255) << 8)
|
414
|
+
| (int) (color.z * 255);
|
415
|
+
}
|
416
|
+
|
417
|
+
protected static int rgbaValue(PVector color, float alpha) {
|
418
|
+
return ((int) (alpha * 255) << 24)
|
419
|
+
| ((int) (color.x * 255) << 16)
|
420
|
+
| ((int) (color.y * 255) << 8)
|
421
|
+
| (int) (color.z * 255);
|
422
|
+
}
|
423
|
+
|
424
|
+
// Stores a face from an OBJ file
|
425
|
+
static protected class OBJFace {
|
426
|
+
|
427
|
+
ArrayList<Integer> vertIdx;
|
428
|
+
ArrayList<Integer> texIdx;
|
429
|
+
ArrayList<Integer> normIdx;
|
430
|
+
int matIdx;
|
431
|
+
String name;
|
432
|
+
|
433
|
+
OBJFace() {
|
434
|
+
vertIdx = new ArrayList<>();
|
435
|
+
texIdx = new ArrayList<>();
|
436
|
+
normIdx = new ArrayList<>();
|
437
|
+
matIdx = -1;
|
438
|
+
name = "";
|
435
439
|
}
|
440
|
+
}
|
436
441
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
442
|
+
static protected String getBasePath(PApplet parent, String filename) {
|
443
|
+
// Obtaining the path
|
444
|
+
File file = new File(parent.dataPath(filename));
|
445
|
+
if (!file.exists()) {
|
446
|
+
file = parent.sketchFile(filename);
|
447
|
+
}
|
448
|
+
String absolutePath = file.getAbsolutePath();
|
449
|
+
return absolutePath.substring(0,
|
450
|
+
absolutePath.lastIndexOf(File.separator));
|
451
|
+
}
|
452
|
+
|
453
|
+
// Stores a material defined in an MTL file.
|
454
|
+
static protected class OBJMaterial {
|
455
|
+
|
456
|
+
String name;
|
457
|
+
PVector ka;
|
458
|
+
PVector kd;
|
459
|
+
PVector ks;
|
460
|
+
float d;
|
461
|
+
float ns;
|
462
|
+
PImage kdMap;
|
463
|
+
|
464
|
+
OBJMaterial() {
|
465
|
+
this("default");
|
466
|
+
}
|
451
467
|
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
}
|
468
|
+
OBJMaterial(String name) {
|
469
|
+
this.name = name;
|
470
|
+
ka = new PVector(0.5f, 0.5f, 0.5f);
|
471
|
+
kd = new PVector(0.5f, 0.5f, 0.5f);
|
472
|
+
ks = new PVector(0.5f, 0.5f, 0.5f);
|
473
|
+
d = 1.0f;
|
474
|
+
ns = 0.0f;
|
475
|
+
kdMap = null;
|
461
476
|
}
|
477
|
+
}
|
462
478
|
}
|