Placeholder Image

字幕列表 影片播放

  • [BELL RINGING]

  • Hello, and welcome back to part 2

  • of building your own Processing library in Java.

  • Look, I'm working with Eclipse!

  • I love eclipse!

  • All of you will complain that I'm using Eclipse,

  • and I don't care.

  • I love Eclipse.

  • It's one of the first places I learned to program,

  • so it has a special place in my heart.

  • So what I did in the previous part--

  • you're probably going to want to go back to watch it

  • if you're here and you didn't--

  • was set up the development environment,

  • so install Eclipse, make sure I have Processing installed,

  • setup all the paths, the build paths, the project,

  • the template, the cloning, all of that stuff.

  • So what I am here right now, I successfully built the library.

  • So it shows up now in Processing under Import Library.

  • And, remember, I'm choosing OpenSimplexNoise as the topic.

  • It's very arbitrary, but I want to build something

  • that's actually useful and can be published as a real library.

  • But the library is here, but if I click this,

  • it automatically adds the import statement,

  • which you can see is just template.library.*.

  • So in this video, what I want to do is code the library itself

  • and make one example that uses it.

  • Probably the hardest part of making a library

  • is being thoughtful about the design

  • of the library API itself, how you make the examples,

  • as well as documenting it.

  • So that's more of a broader topic related

  • to how to maintain and publish an open-source library,

  • but I'm going to mostly focus on the technical details

  • of building the thing.

  • And maybe towards the end, I can circle back and talk more

  • about those key important concepts and topics

  • to having a healthy open-source project.

  • So first thing that I want to do,

  • if I want to customize this, it I

  • should say something like "import

  • shiffman.opensimplexnoise," or something like that.

  • I mean, I don't think that's what I'm going to call it.

  • I'm going to go back to Eclipse.

  • I'm going to go over here, and I'm looking for under Source.

  • And so, look, this is what's known as a package,

  • template.library.

  • And so, because the package name in the template

  • is just "template.library," that's what the import was,

  • template.library.

  • So I'm going to right-click on this,

  • I'm going to go to Refactor, and click Rename.

  • And then I'm going to come here, and I

  • got to pick a name for it.

  • Let's call it "algorithms.noise."

  • Ultimately, I think what could be exciting

  • about this library is to implement

  • a bunch of different noise algorithms, OpenSimplex

  • noise, fractal noise, gradient noise, Worley noise.

  • So many different kinds of noise algorithms

  • could be in here that would be additions and enhancements

  • to the built-in, original Perlin noise algorithm that's

  • in Processing itself.

  • So that'll be my name.

  • I'm going to click OK, excellent.

  • Now I want to go into the source code, which

  • is called "HelloLibrary."

  • So I am going to rename this also

  • by going to Refactor, Rename.

  • And I'm going to name that--

  • let's call this particular Java class "OpenSimplexNoise."

  • And I'm going to do Finish.

  • OK, great.

  • I'm going to go over here, and there we go.

  • Let's try rebuilding the library.

  • We don't need to rebuild it at every single stage,

  • but let's just rebuild it to see if what I did at least

  • shows up with the proper naming conventions.

  • So I go to Window, Show View, Ant.

  • Click here, and do Ant Build.

  • BUILD SUCCESSFUL is what you're looking for.

  • Go back to Processing, Sketch, Import Library,

  • OpenSimplexNoise.

  • There we go!

  • Interestingly, it's giving me an error message.

  • Let's try restarting Processing and see what happens.

  • All right, I restarted Processing,

  • and the error message went away.

  • So certain things that you change,

  • if you're changing the package name,

  • even though the new library files

  • are being built and brought over into Processing,

  • Processing has loaded what it thought all the package

  • names were when it started up, so you have to restart.

  • So I don't think with every single change

  • you make while you're building the library you're

  • going to have to restart Processing,

  • but that certainly is something you'll

  • have to do from time to time.

  • One of the things I like to do when

  • designing an open-source library is actually

  • write the example first in the way

  • that I imagine that it might be.

  • So even though I haven't built any

  • of the functionality of the library itself,

  • what I want to do is I want to take a simple processing

  • Perlin noise example that uses just

  • the built-in original Perlin noise from the 1980s algorithm,

  • and then change that example to use OpenSimplex noise.

  • So if I go to Examples, under Basics,

  • under Math, let's just take Noise1D,

  • and let's look at this example.

  • This Noise1D example is mapping the x location

  • of this circle it's drawing to the noise

  • implementation in Processing.

  • So I'm going to grab all this code,

  • copy it, close this out, and paste it in here.

  • And I'm going to imagine what I might do.

  • So I might do something like, OpenSimplexNoise noise.

  • And then I'm going to say "noise is a new OpenSimplexNoise."

  • So presumably the idea is that OpenSimplexNoise

  • would be an object inside of the package algorithms.noise.

  • Maybe I want to name that just "OpenSimplex,"

  • because by definition it's noise.

  • Who knows, but I want to create a new instance of it.

  • Maybe, optionally, there could be

  • a seed that goes in here, because I could

  • be randomly seeding the noise.

  • And then, what I would do is, say--

  • (CHUCKLING) and so let me call it something different

  • for it to be less confusion.

  • Let me call it "osnoise" for OpenSimplexNoise.

  • And then, probably what I would want to do is say

  • "osnoise.value," pass it this X offset.

  • And, actually, that's it!

  • Because, really, this is such a like--

  • even though the OpenSimplexNoise algorithm is quite complex,

  • I just want one function that gives me the noise value back.

  • And I'll call that value-- or, I could have called it "noise."

  • I don't know what to call it.

  • But, again, these types of naming an API design decisions,

  • while incredibly important, I'm going to maybe tackle later,

  • and through user testing and discussion,

  • and are less crucial right now in terms of the nuts and bolts

  • of how to build your library.

  • How to think about making an open-source library,

  • it's so important!

  • But right now I can just pick something.

  • Let's pick value.

  • Let me go back to the library code.

  • And I'm going to add a function now.

  • I'm going to add a function called "public value."

  • And it's going to receive an argument, like X offset, xoff.

  • And I'm going to say "return negative 5."

  • So I just want to test out this idea.

  • I want to add a function called--

  • oh!

  • This should be "public float value."

  • Because it's a Java function that returns a float.

  • It receives a float.

  • So, again, this is not the OpenSimplexNoise (CHUCKLING)

  • algorithm, but I am just going to have it return

  • negative 5 to see if it works.

  • And let's actually just give it the number 50.

  • Well, actually, noise should return a value between 0 and 1

  • or, in this case, maybe between negative 1 and 1.

  • So let's actually make it negative 0.5.

  • And, in Java, if I want it to be a float,

  • I've actually got to add that f to indicate float.

  • So, once again, I am going to build the library.

  • The library is rebuilt. Let's go back to the code.

  • Oh, wait, I'm getting an error.

  • "The constructor OpenSimplexNoise noise

  • is undefined."

  • Why am I getting that error?

  • Because I have a constructor OpenSimplexNoise--

  • oh!

  • It needs this thing, PApplet theParent.

  • Ah-ha!

  • What this is and how this works, PApplet theParent,

  • is probably something I should tackle or address

  • in maybe a third part or a fourth part to this series

  • because I don't think that I need it

  • for this particular OpenSimplexNoise library.

  • But this is a way of having the library know something

  • and communicate to or execute functions in the user's sketch

  • itself.

  • It's not something I initially need for OpenSimplexNoise,

  • but let me just keep it in here for right now.

  • I'll decide later if I can remove it.

  • But there's-- this is not a flaw of the library design.

  • It's now a flaw of my code where I need to say "this."

  • The keyword "this" in Java refers to "this class,"

  • and your Processing sketch is actually

  • a class that's just hidden from you when you're

  • working in Processing itself.

  • So now let me run this.

  • And we could see the negative 320.

  • Why is it negative 320?

  • Because I'm multiplying it by width.

  • So that's right, width is 640.

  • The only noise value I ever get back

  • is negative 0.5, multiplied by width is 320.

  • So now we're building the library

  • and we added our own function to a particular class

  • in the library itself.

  • The next step is let's actually put in the OpenSimplexNoise

  • algorithm.

  • Here is the r-- it's raw source code for Kurt Spencer's 2014

  • implementation of OpenSimplexNoise in Java.

  • Now, there's a little bit of an unfortunate

  • thing, which this class is also named "OpenSimplexNoise."

  • Again, here I am back to this naming thing.

  • Everything is quite difficult, but let's--

  • let me first just bring this into Eclipse.

  • So there's a variety of ways I could do that,

  • but I'm just going to copy paste it.

  • So I'm going to make-- here, I'm going to create a new class.

  • And I'm going to call it "OpenSimplexNoiseKS,"

  • the KS for Kurt Spencer's.

  • I want to keep that implementation entirely intact.

  • So I'm going to hit Finish.

  • I am going to paste it in, and then I am going to hit Save.

  • And then, I need to change this to KS.

  • I need to add the package declaration.

  • And then, I need to find other things.

  • Like, this should be KS, this should be KS,

  • this should be KS, this should be KS.

  • There we go.

  • Now that I have the OpenSimplexNoise original

  • implementation from Kurt Spencer as a separate class

  • here in my library, I have a decision to make.

  • Ultimately, what I want is for that functionality

  • to appear in my OpenSimplexNoise class.

  • And so I could extend the OpenSimplexNoiseKS class,

  • that would be known as inheritance.

  • Or I could really just wrap it by making an object in here,

  • like OpenSimplexNoiseKS generator that

  • is an instance of Kurt Spencer's OpenSimplexNoise

  • implementation.

  • And this is referred to as composition,

  • maybe like wrapping another class as an instance

  • inside of a class.

  • So the reason why I want to do this is I'm trying to--

  • I'm not trying to expose the full implementation

  • and just add a few window dressing things to it.

  • Although, that would be a legitimate way

  • of designing this library.

  • But I'd rather do it this way just to really hide that,

  • but have my own set of functions that make use

  • of the implementation there.

  • So I'm going to do that here.

  • And then, so in the constructor, I

  • need to create a generator equals new OpenSimplexNoiseKS.

  • And then, in this value function--

  • and I don't need this say hello function.

  • The welcome function is maybe nice to have.

  • This set-- I'm going to get rid of the set variable

  • and get variables.

  • Those are all just template functions.

  • But what I want to do now is, instead

  • of returning to some arbitrary number,

  • I want to return the generator.

  • And the function inside of the OpenSimplexNoise

  • is called "eval."

  • So maybe I'm actually going to call this "noise."

  • And the function's called "eval."

  • So I'm going to pass X offset to eval.

  • (CHUCKLING) The thing is, the eval--

  • the OpenSimplexNoise implementation

  • doesn't allow for one dimension.

  • But for me to get one dimension, I

  • could always just pass as the second argument a zero.

  • So why do I have an error here?

  • Let's look at what this error might be.

  • "Cannot convert from double to float."

  • Oh, right!

  • Because OpenSimplexNoise implementation

  • is all done with doubles, but processing and simplification

  • only works with floats.

  • So here's where I can now change this to be a float.

  • And there we go.

  • So now I have essentially wrapped

  • the general-- the eval function, which works in two dimensions,

  • to work in one dimension with floating-point numbers.

  • And now, if I rebuild the library, go back to Processing,

  • and I'm going to run this.

  • Oh, and it's called "noise" now.

  • I renamed it from "value" to "noise."

  • So this circle is disappearing off the screen

  • because I'm getting negative numbers.

  • The built-in noise implementation and processing

  • always gives you a value between 0 and 1,

  • where as this OpenSimplexNoise implementation gives you

  • a value between negative 1 and 1.

  • So there's probably some advantages

  • for me keeping that range between negative 1 and 1.

  • But if I want to make the case that what

  • I want people to be able to use this

  • for is to have their current Processing code just work out

  • of the box by changing it to the OpenSimplexNoise function, then

  • maybe what I should do is, here, I should actually say--

  • I'm going to say--

  • I'm going to just call a remap.

  • I'm going to make a function called "remap," private float--

  • or, double remap, double val.

  • And what I'm doing is I'm saying "return val plus 1 times 0.5,"

  • right?

  • Because a value between negative 1 and 1

  • would shift between 0 and 2, divided by 2

  • would shift between 0 and 1.

  • So I'm going to do that.

  • So I could rebuild and test this,

  • but I'm pretty sure that correction will work.

  • Let's now add functions for 2D, 3D, and 4D noise

  • to make sure those work as well.

  • So I'm going to do this.

  • (CHUCKLING) I'm just going to do this a few more times.

  • Then, I'm going to add a Y offset.

  • I'm going to add a Y offset and a Z offset.

  • And then, I'm going to add a Y offset, a Z offset,

  • and a U offset.

  • And so this would be xoff, yoff.

  • And, again, I could refactor this to probably

  • have them call each other, but I think this

  • will work fairly well for me.

  • And then, here.

  • So now we have 1D, 2D, 3D, and 4D noise.

  • And I also should add a constructor, which

  • allows me to pass in a seed.

  • So I'm going to say "int seed."

  • And I'm going to pass that seed to OpenSimplexNoise.

  • And with no seed, maybe I'll change it to just

  • call the other constructor "this" with theParent

  • and a System.currentTimeMillis.

  • So I'll use that as the seed.

  • Ah, so I have an error here.

  • Whoops.

  • Oh, it's because currentTime.Millis

  • is a long data type.

  • So maybe I'll change this to long.

  • I think that's probably OK, because you can always

  • give it an integer.

  • And so there we go.

  • So now I have two constructors.

  • If I just say "OpenSimplexNoise this," it'll pick a random seed

  • or I can give it a specific seed,

  • and it'll generate with that seed.

  • So now I'm done [CLAPS] with the basic functionality

  • of this library that I wanted to build.

  • So let's go back and build it again.

  • So people who are watching this live right now in the chat

  • are rightfully complaining about my redundant duplicated code

  • here.

  • At a minimum, let me refactor this to just have the first 1D

  • noise function.

  • Just return this.noise X offset, 0.

  • I do think that the implementations, as you

  • get to higher dimensions, run more slowly.

  • So I don't actually want to call those with fixed dimensions,

  • but I only want to do that for the first one.

  • So, again, I'm sure there's a way

  • to optimize or refactor that.

  • It'll come later in the building this library,

  • but I just want to get it to work.

  • Let me rebuild the library one more time.

  • Go back to Processing, and run it.

  • There we go.

  • The same exact example, but now with OpenSimplexNoise.

  • I'm going to hit Save.

  • And I'm actually going to now make this one of the examples.

  • Whoops.

  • So I'm going to call this, "OpenSimplex--

  • "OSNoise1D."

  • And then, I'm also going to save this as "OSNoise2D."

  • Let's also go and grab Noise2D.

  • And we're going to Sketch, Import Library,

  • OpenSimplexNoise for Processing.

  • I'm going to make a OpenSimplexNoise noise

  • instance.

  • I going to say "noise equals new OpenSimplexNoise noise this."

  • Then, here I'm going to say "noise.--

  • oh, let's call this "OSNoise."

  • And I'm going to say, osnoise noise.

  • And let's run this.

  • Look, the same exact example, but with OpenSimplexNoise!

  • Change this to regular noise and run it.

  • It looks like this.

  • Change this to "improved."

  • What I would say is improved OpenSimplexNoise,

  • and it looks like this.

  • So that's another example.

  • And so now, you'll see, by the way, in Eclipse,

  • you can see that the examples are showing up here.

  • And I can get rid of this hello example

  • because I don't need that.

  • I finally have a fully functioning, working version

  • of the library with two examples.

  • Here's the thing.

  • There's a lot more work for me to do.

  • I haven't added anything in the code

  • comments that will help generate documentation for the library.

  • I haven't published a library in a way

  • that it would show up here under Import Library, Add Library

  • in this actual list here.

  • This is a way of publishing it to the Processing

  • list of libraries itself.

  • But this is a good stopping point,

  • because now I'm at a point where you, the viewer,

  • could actually use this library.

  • So I will come back and do a third video

  • about cleaning up and finalizing and publishing

  • the library in a more public way.

  • But right now what I'm going to ask of you, the viewer,

  • is two things.

  • Number one, go and download and try this library yourself.

  • So I'm going to compress this folder

  • and make a file called "OpenSimplexNoise

  • for noise Processing.zip."

  • And I will add a link to the GitHub repo.

  • Here is the GitHub repo for the library.

  • If you go here, the link to this is in the video's description.

  • By the time you're watching this,

  • there will be more information in this README about how

  • to get your hands on this zip file

  • and manually install it to your Processing download.

  • So you can test the library.

  • You can give me feedback by filing an issue here on GitHub.

  • No issues have been filed yet.

  • And you could also contribute to the functionality

  • of this and documentation of this library.

  • So if you have some time and would

  • like to work out filling out this JSDoc,

  • information inside the source code itself.

  • If you really don't like the way (CHUCKLING)

  • I've written these four noise functions

  • and want to refactor that, we can

  • think about and have a discussion about the API design

  • decisions.

  • And after I let that cook for a little while,

  • I'll come back and do a third video

  • to show you these updates, what kinds of changes I've made,

  • and how to take that final last step to creating a website

  • and publishing your Processing library to a website,

  • and having it appear in the Processing contributions

  • manager itself.

  • All right, [CLAPS] I hope this has been helpful to you.

  • I look forward to seeing this project grow.

  • We can add some other noise algorithms to it.

  • There's going to be a lot of fun in creating

  • this open-source project as a Coding Train community

  • and adding it to Processing itself.

  • Thanks for watching, and I'll see you sometime soon

  • in the third part to the series.

  • Goodbye!

  • [TRAIN FLUTE SOUND]

  • [THEME MUSIC]

[BELL RINGING]

字幕與單字

單字即點即查 點擊單字可以查詢單字解釋

B1 中級

如何製作一個處理(Java)庫第2部分。 (How to Make a Processing (Java) Library Part 2)

  • 0 0
    林宜悉 發佈於 2021 年 01 月 14 日
影片單字