propane 3.3.1-java → 3.4.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|