Computational Design Live Stream #86

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello oh what is this here the microphone okay here microphone destiny microphone all right and everything looks good youtube is complaining about audio but audio looks fine on my end can you hear me can someone hear me hello people people in the chat people in the background people all across the globe hello hello hello welcome hey arasto richard hierro how do you pronounce that here hello everyone how's everyone doing i'm very happy to be here i'm back i'm back choo choo choo parametric cam okay this might be another case of too much coffee in the morning uh hey andre hola come on uh okay and then the camera needs yes exactly the camera needs that to shield okay that's great yeah christina hello welcome all right okay so what is going on it's been too long oh my god it's been almost a month that i haven't streamed that is terrible can you give me some thumbs down on the chat that is not acceptable not cool i am actually very sad that that has been the case but um what can i say beginning of the semester preparing classes the acadia conference i was co-chairing it this year it was it was just a lot i could barely keep up with everything so [Music] i apologize to all of you for not having not done this for a while for not being consistent but it is what it is sometimes life gets in the way but hopefully things are under control um my life is back on track kind of and i can get to doing this a bit more often now um because as i said i actually said myself at the beginning of the year my new year resolution was to hit 100 live streams by the end of the year we i am not on track for doing that so i may have to push it a little bit at some point by the end of the of the month or i don't know i have thanksgiving vacation sometime soon coming in in two weeks so maybe i take that opportunity to do a little bit more of live streaming because i really want to finish this serious advanced development in grasshopper okay so let's get before we get into business a few things so hi this is jose luis if you don't know me this is parametric camp we do live streams we discuss computational design we record tutorials live with the help of a lot of beautiful people who in the chat who help me fix my code and like suggest good things to in introducing the chat in the in the tutorials so we do this live and because i like human human interaction and and yes um and if you want to know when we go live you want to be up to date well maybe you want to consider hitting the notification button here on the channel liking the video liking the subscribing to the channel maybe following us on social media we're particularly active on instagram and we also have a discord server the link is in the description of this video that you can log in and we have offline conversations with the community we shared work people ask troubleshooting questions we have a lot of things going on and we also have a google calendar that you can subscribe to get notifications on your guru and calendar of when we go live okay if you were new to if you were new to to this channel now i have a couple of things that i wanted to share first of all last week what is this whatever what am i doing okay last week was the last week was the end of the acadia conference the conference for computer aided design in architecture so um it was really awesome not because i was organizing it but uh i thought it was very interesting panel discussions paper presentations people in the field of computational design doing research and trying to push the feel in a critical way so if it was free registration for students this year so if you had the chance of attending then good for you if you didn't you can still register until the end of the month i believe and then you will get access to the recordings that will be made public at some point by the end by the end of the um [Music] if you want to see if you didn't register but you still want to see some stuff the acadia.org youtube channel has some of the keynotes some of the panel discussions so if you want to check some of that you can do it here otherwise if you want to check the actual paper presentations those will be made public but you have to register in order to access them those will be made available sometime very soon so registration for the conference and then you will get a link at some point now what else uh yes so i am as you know whoever doesn't know i teach this class called introduction to computational design at the harvard graduate school of design and we have guest lectures throughout the semester we have had in the past this semester already we've had andrew human and gabriella rossi two very interesting lectures about augmenting architecture with computational workflows and doing fabrication specific robotic fabrication aided by machine learning i thought these were two were very cool but especially this afternoon so at 5 30 p.m et my time so that's in roughly what's that going to be in seven and a half hours from now venezuela is going to give the last guest lecture in the semester it's going to be about critical computation emotive matter critical issues in design technology activism feminism it's going to be super interesting so it's going to be open and live streamed for free the link to that i'm posting it in the chat right now but you can also just google it pretty easily okay all right and aside from that do i have any other announcements or things i wanted to share oh yeah yeah yeah yeah okay i we are preparing something really cool so let me show that can i show that what is this oh yes so because the season is coming very soon uh me and okay so let me say wait matt parker christmas stream exactly so i'm not sure if you're familiar with matt parker he is this guy here on the corner he's a mathematician he's a and he's a recreational mathematician and stand-up comedian so on his youtube channel stand-up maths he did this project last year where he basically attached 500 leds to his christmas tree each one of the leds was individually addressable and then he did this super interesting routine to calibrate where each one of those leds was in 3d space so that he could automatically uh capture the xyz location of the of the of all the leds and then create programs that illuminated the tree based on that xyz location so i thought it was super interesting so i've been working with some of my teaching assistants at harvard and we've been trying to replicate maths tree and we got some mild success so we do have a tree with the led lights and uh some calibration it's not perfect we're working on it but it's there's something it's working and something that we did because this is also part of one of the assignments in my class is that we wrote a bunch of custom c-sharp script components to load though the coordinates of those points and to create custom animations for the tree that we were simulating in grasshopper okay so what that means is that we have a file with like a simulation and rendering etc etc for animating lights on the tree and what you can see here is like a super simple animation where you have like basically a plane of white light that is moving upwards along the tree okay just as simple as that so what i would like to do in some live streams very soon is i would actually like to make this i would like to recreate this as an exercise on here on the chat and here on the on the channel make some videos about that and perhaps by the end by december if any of you have picked up and understood the code and want to create your own sequences maybe you can run it you can run them by the tree that we have and we can have like a christmas event where you share your files i run them in the tree you see them live executed i don't know i think that could be super cool so there's going to be some of that coming very soon just stay tuned uh we're still working on the tree we're still working on on on a few kinks but it's looking pretty good so far okay i don't know how that's going to happen or when or whatever but we will make some something happen to get together because remember also every year by the end of the year we do a community event so we all every all the parametric campers who are interested we all jump on a zoom call and we have a large zoom conversation that is also streamed to youtube it's fun we get to know each other human human interaction so maybe as a fun exercise we can do some of that during the live stream okay beautiful all right how about adding some to it and make it real time oh my god fine i may let you connect with via web sockets to the tree we'll see we'll see that's actually not a terrible idea i like i like it a lot maybe we can use remo sharp to just inject code into the c-sharp script component and do something huh you would like that huh okay all right so now to regular business what are we doing today we are continuing with the um with the advanced development in grasshopper okay playlist which as far as i remember it's been a long time unfortunately as far as i remember we were the last thing that we did was continuous execution and with the dynamic relaxations and fixes physics simulations and um and what's now on my list what's now on my list is loading external assemblies so the idea [Music] the idea that in order to use classes we need to actually load them as external assemblies and how we can use that technique to load c-sharp libraries to load c-sharp libraries in grasshopper and and use them so i think that's what we're going to cover today in order to do that i'm going to have to do to write a little bit of code because i didn't i don't have i actually have some code for the s for the for the um for the example but i don't have code for i have code for the exercises the code that we were working on last live stream where we were using um geometry 3 sharp i think was called the library so that is going to be one thing but i need to write a simple code so i'm going to write a simple example the idea here is first of all in the video what i want to explain is the difference the problem of having a component that has a class inside of it and then passing an instance of that class to another object and how that is not going to work even if i have the same class on both components so i'm going to create like something like a person um so for example this is going to be name this is going to be age is professor all right and then here for example i'm going to paste jose luis age there's going to be a hundred and professor is going to be a boolean toggle that's going to be true all right beautiful and then what i would like to do here is to um create a person so let me do this full screen okay and then i will i will create a person class in this x in this c here but what i would like to do is i would like to uh i would like to now take a person class and deconstruct it into name age and uh is professor okay is professor okay and i'm going to do the following i'm going to just construct vector i'm going to construct a vector here and i'm going to just just because i'm going i want to show the idea of constructing and deconstructing entities um and then decons drag vector and then i got the vector and then here i can plug in as like a bunch of and whatever and so that's going to be here uh [Music] okay yeah there you go so what i would like to do is i would like to do something similar here what i just plug in the name the age and the professor okay and maybe should i write this in c sharp actually maybe i should write this in c sharp why not uh yeah actually that would make sense uh and then i'm going to click v here and i'm going to spit out x y and z okay so i'm going to copy and paste this here okay i'm going to say this is a double this is a double no not an integer a double another double here and then output is whatever it is and v i want to x y and z so this is going to be one thing this is going to be another thing and this is going to be another thing okay and then here what i can just do is i can say well vector 3d p is going to be equal to a new vector 3d x y and z and then b is that for example and i'm going to use algorithm outputs output so that's one thing so that's great and then here i type hint this to be vector3d and here i can say x equals v dot x y equals b dot y equals b c okay and these are the abs okay so this works it gives me the result all right and then what i want to do here is the same idea i want to create but i want to do it custom i want to have a class that i've written and i want to be able to exchange that class between multiple components because i want to use them so what i would do here is i would say well maybe in the custom additional code i can say public um public plus person and this is going to be equal to um [Music] bring name public stream name probably integer h public boolean uh is professor all right and the constructor is going to be a public person name age and is professor and then this name is going to be this n is going to be a and then this ip this is professor is going to be ib okay and this has to be string integer and boolean i'm going to add a public override to string to string here and that's going to be for example return this that name [Music] plus h and then age and then is professor [Music] then is that each percussion okay so if i have that now okay i can get this here and then i can copy and paste all right i'm just going to keep it here and then that's where i'm going to pick up the exercise okay i think i'm going to pick up from there all right am i correct here learning [Music] all right so if that's the case i think i can start recording and then let me write some notes here uh here so today is in 10 10 today is the 10th right yep all right so are we ready to start how's everyone doing and i'm going to shut down my email because i'm receiving oh god uh oh boy okay okay shall we do this uh right oof it's been a while i'm kind of rusting okay let's do this i'm going to save this somewhere which is probably going to be um nope i'm going to save this here in parametric camp files advanced development 4.7 eternal assemblies four point seven [Music] eight i don't know that's please okay let's do this hi this is jose luis here at parametric camp and welcome to another video in our series advanced development in grasshopper uh you may see that my beard is a little longer and i have more hair than in the previous video there's been a like a time gap in between the recording of this video and the previous ones i hope you don't mind so excuse me what are we taking a look today today uh this video is about loading external assemblies and the idea is that in grasshopper just like in any other place where you can write code the idea is that very often we rely on using custom classes and custom objects for the sake of transferring data between different entities and as ways of encapsulating data in in objects that represent some kind of notion so for example in grasshopper we are very used to the idea of for example creating a vector using individual primitives such as for example numbers with decimal part that becomes an object that is a vector structure that has the three parameters that we can then exchange multiply operate with or even deconstruct in some other component so that we get those initial primitives but the idea is that the transfer the data that is being transferred between these two components is an entity an object that is derived from a class the vector3d class that comes bundled with grasshopper and with rhino a very clear illustration of that is if we were to replicate the same logic here um we would basically create a c-sharp script component that takes three input tracked in rhino common to create an object to create an instance of a vector which we output on this component and then this second component here the which is going to deconstruct that vector takes in as an input you can see that it takes in a vector3d object and then once i double click you can see that we have that object as a class here and the outputs we can just take the x y and z properties of this vector and output okay so this idea that we can use custom classes or custom structures to exchange complex data types between components and operate with them it's the basic building blocks of object oriented programming it's a super super common technique it's the most common paradigm in modern computer programming languages and uh you're gonna see it everywhere basically now we have we can use vector3d because it's part of the bundle the grasshopper plus rhino framework that we're working with and if you were working in unity or in some other environment you would have similar access to similar geometric entities but what about if you want to supersede this and you're actually writing your own super empower classes that represent some kind of notion that you're working with and that encapsulates a lot of data inside of it what if you were doing that yourself but you wanted to operate with your data in a similar way that we have here you could you would want to exchange between components these custom classes these custom objects that you are creating yourself so we're going to see an example of that here today which is going to be for example let me say that for some reason i am working with um a class that i'm going to name a person and the idea is that this person is made out of a bunch of particular properties like for example the name the age and whether if this person is a professor or not okay in grasshopper in c-sharp what we can do is we can write custom c sharpscript components that here on the additional custom code we can write our own classes so we can create a new class that is a person that has the three fields name age and professor we can have a constructor that takes the data and saves it in in this class and then we can have a a string method and override to just create a more um human readable form of this object correct now if i were to do this and i wanted to create a person object that was output by this component the first thing that i need to do is i need to go here i need to make sure that the inputs name age and professor have the correct types in this case string integer and boolean and then here now that the types are correct what i can do is like we've been doing in all my previous videos we write the algorithm so for example i'm going to define a person variable that is going to be called p and it's going to be a new person of with the value of name age and is professor so that is the data that is coming in from the component at this point i can create this variable of the type person because i am defining what a person class is in my c-sharp script component all right now what i can do is i can just output that over so i can say person is going to be equal to this new variable that i just created and if i run this code what i get is this thing that is the person is facilities the age is 100 and whether if it's professor is true or false and more or less age so this is faithfully representing what the professor is correct now the idea is that i want to bring this let's say that i want to operate with persons and i could like mingle persons together multiply them together i don't know this is just a theoretical example okay but let's see let's say that i wanted to mimic this behavior so i wanted to now have another component that takes an object of the person class and then is able to deconstruct it into its primitive parameters so the name agent whether if it's a professor the first problem that i encounter is that remember how for c-sharp script components we need to right-click animate we need to make sure that the type of the input is the correct type so that we can operate properly with that object if that is the case then the first problem we run into is that if i right click on person and if i go to type hint you can see that i don't have a type of person anywhere here because grasshopper only gives me types that come with rhino common or there are primitives so that is the first problem that i run into so what i can do is just for the sake of i'm going to cancel the public overwrite here i'm just going to call what what did i do i'm just going to comment this out all right so that what we can see is that the type that is coming from here is something that c-sharp stringifies into your script instance plus person all right i'm not sure what that is i will explain in a second but the solution to that is that because we don't have an explicit type available to us what we're going to do is we're going to choose the most generic type that's going to be system object which is the type that all objects in c-sharp inherit from so the parent object is going to be always be system object if i do that then if i double click here you can see that person is now this generic type but what i can do now is i can say well inside of my grasshopper script component what i can do is i can cast this object that is generic into something that is customized which is the type of person so what i could do is i could say i'm going to say that the variable p of the type person has to be the input that is coming in cast to the class person all right so this is called casting is when you translate objects from one type to another i have a video on our learning c-sharp series where you can learn more about this and it should be popping on a link over there or there should be a card somewhere or there should be a description a link in the description okay if i do this this should work but it will not because what happens is that my component is complaining because the type or namespace person could not be found it's just not accessible here why is that the case well it turns out that this component this one here the one on the right has no idea of what a person class is because the person class has been defined in the other component and because just like many other things classes when you define them inside of a component they get scoped inside of that component and they're not available to other components that are not inside of the same scope so a solution to this could be okay well i'm just going to copy all this code all right i'm going to paste it here and now i have the same person class i have the same person class in both places okay if i do that that is going to solve some problems but it's also not going to give me the solution which is and then the error that i get is actually really strange it says um cannot cast from person a to person b type a originates from this signature in the context load form and if we look at the full error message it's like a full but type b originates in some other form and they're not compatible etc etc what is going on here well um it turns out that what i just did as logical as it might seem it's actually not possible to do it's not possible because the person class here on component a and the other person class in component b even though they are both identical they have the exact same text they have the exact same properties the code is identical to the letter even though that's the case because of the nature of how grasshopper works because each component each c-sharp component is compiled internally in the background and it becomes its own thing when each one of the two components are compiled they get different signatures they get different memory addresses blah blah whatever so even though the code is identical for both of them because they get compiled in different places in the eyes of the computer they are different entities they're just separate things even though they have the same name the same properties etc the computer is not able to see that because of compilation issues so because they're compiling different places the computer treats them as different things and because it treats them as different classes it's not able to cast from one to the other it's just simply not okay uh what would be a good example for this uh imagine i don't know two cars that are identical but are manufactured by different factories but the every single atom that they do is identical uh for us humans we would able we would probably be able to say that they're the same thing but for a computer because they're coming from different places they're probably different types of cars and they're not able is not able to mix them together that was not a great metaphor but you get the point what i'm trying to get here okay so um this is unfortunate because as a pro as a pro computational designer you probably want to start working on libraries of classes and collections of objects that can encapsulate a lot of your really cool functionality that you're working on and you may want to be able to exchange that information between different components you may even create your own plugins that are running on classes and methods and functions that are customized by yourself so what is the solution that we can do then here well it turns out that in the case of grasshopper different platforms treat this problem differently in the case of grasshopper this approach copy paste in the same class in the two components just doesn't work there's literally no good way around it except for very complicated marshalling operations it's just not good so the actual good way of doing this is to take that code extract all the goodness of your classes etc that you are customizing creating an independent assembly one that gets compiled once somewhere outside of grasshopper and then loading that assembly into your c sharp components and then so that the same assembly is loaded by different instances and because but because it's the same assembly with the same signature all the components can exchange and marshal and cast that information without any problem so how does that look like of course i'm going to show you an example of that let's take a look at that beautiful how was that was that clear okay i need to remind myself add card to um to casting from learning c okay all right beautiful so what is the next thing we're going to do this is going to we're going to save this here and we're going to we're going to open video studio and we're going to create a a person class should i do this live or should i just show up with the project uh i'm going to do this real quick really uh and maybe i should uh where is parametric camp okay [Music] and then videos how about regular class creating a vector class oh this video has 3 000 views already that's very nice okay so we're gonna keep that there okay and i'm gonna start from here what i'm going to do real quick right now is that i'm going to create a visual studio project to create a library that contains a class of the type person just like we wrote in c-sharp and i'm going to do it really quick because i actually have a full video here on my other list on the learning c-sharp list calling creating a vector class where i actually go over the whole process of visual studio creating a library writing a full class this is actually really really it's a really interesting video if you want to learn more about how to create your own libraries that can be reused in different places so i really recommend you check this video out a link will be popping also in a card or it will be in the description of this video you can find that out okay so i'm going to go real quick i'm going to create a new project in visual studio not visual studio code it's going to be a library um it's going to be a class library for the dot net where is dot net framework uh okay i'm moving class this is for windows forums um console application class library for the.net framework okay that was uh very far away class library for the.net framework i'm going to put this on my desktop and i'm going to call this a person class for example okay and it's going to be 4.6 because i believe that's a good version to work with rhino and grasshopper and then here what i'm going to do is i'm going to paste the code that i had in that i had in grasshopper okay so i'm going to save this i'm going to rename this class i'm going to call this person all right and then this is basically my person this is a library that contains one class called person with the same properties that i had in c sharp okay what i'm going to do now is i'm going to build this solution and as i build that solution that has created on my desktop you can see my desktop has the full project person class the person the person and in binaries in debug i have this dll person class that contains that code again all of this i went over in my other videos so if you're interested in learning more you can check out the other video all right so what i'm going to do is i'm going to now go to where i have my c my grasshopper file and i have no idea where that is let me look that up sorry so i guess that's going to be here in advance loading exactly so this is the file that i had for um [Music] this is the file that i have for um the grasshopper file that i have with the code that i was showing okay so what i'm going to do is i'm just going to drop this dll right next to the file just because having dlls having assemblies and grasshopper files next to each other just makes a lot of things easier okay so i'm going to do that and then i'm going to close this and i'm going to go back to my grasshopper file okay so you can see i'm going to actually copy and paste this somewhere else so that you can see that this is the one that doesn't work and this is if you look at these files at some point in the future so what i'm going to do is i'm going to remove from here i'm going to remove that i'm going to remove the custom person class and i'm going to remove it also from here i'm going to remove it from both places all right now you can see that the two components are complaining because they don't understand what a person is the code used to be inside but now what we want to do is we want to load that code from an assembly that is external so i have compiled the person class in a library and i want to load it here the way i'm going to do this is by right-clicking here and you can see that c-sharp script components have this section called manage assemblies if i do that what you can see is that it has this kind of environment where you can reference external assemblies that contain c sharp code so what i'm going to do is i'm going to add here and i am prompt already to the folder you can see that person class shows up again this is because i copy pasted the the dll right onto next to where my grasshopper file was and if i do this and i reference it okay you can see that now the if i manage you can see that person class is available on my c skip component however the code is still telling me that the namespace or person could not be found why is that i just loaded it well it turns out that loading an assembly and referencing the assembly are two different processes so this integrated development environment this window here has access to the person class because it loaded the file but it's not using it and because it's not using it then this code is not working the way to use that is to expand this this area that we have on the top of the c-sharp screen component where we are loading all the external assemblies that this c-sharp script component is using it's using as you can see some some default system libraries is using the rhino and the rhino geometry namespaces and it's using a few other namespaces that are coming specifically just from grasshopper okay so the idea is that here what i can just say is i'm going to use uh the person class namespace that i defined for my library and if i run this code now i believe it should actually work yes so instead of writing using person i need to refer to the namespace and the namespace is this thing that shows up here so if i had a lot of different libraries a lot of different classes in the same name space person cat dog whatever they would all be loaded by just loading the namespace so as i use the namespace then person as an entity becomes available and then you can see that this component all of a sudden starts working what this component does here is well we have the same problem here so let me first reference the assembly so i could load it here but because i loaded it before i can just use the same one so i'm just going to go to the recent ones and drop it here and then now i have the same problem is not available anymore so what i can do here is i can say using person class for example and then as i do this you can see that no errors are found anymore because i can effectively convert from a person the person object that was coming to my component which was a generic object i can convert it to an actual person class because again the person that i'm learning from here it has the same signature that the one that was generated by uh the other component and then just as simple as that i can say outputs now name is going to be p dot name um what was it h is going to be p dot and you can see how the autocomplete is already giving me all these nice options because it's picking them up from the compiled library so i get h and then whether if is professor or not is going to be p dot is a professor and then ta-da so now if i change the inputs or if i change the professor i'm not 45 okay i'm a hundred years old so if i change that data then this data change correspondingly because there is a properly flowing connection between the two components with a class that is recognized by two components because it's coming from the same assembly that i compiled myself externally all right so this might seem trivial or a stupid problem to have to deal with but it's it's a problem that derives from how c-sharp gets compiled in computers in operating systems it's but it's something that sometimes we have to deal with however my invitation to you is to consider that this that we have learned in this video is actually quite helpful and very good practice because if instead of copy pasting code between different components which is something that is very difficult to manage if what you do is as a general practice you start abstracting code that you write yourself that contains all your power all your really cool algorithms if you extract it into entities that are standalone and can be exchanged between any different software in this case if you extract them as a dll in c sharp that can be used in grasshopper but also in unity in vvvvvvvv in other in any other c-sharp based environment then your code becomes more reusable more resilient to changes less error prone it's actually a really really good practice and this technique is also at the core of how other people use external third-party libraries to improve their code and to make it more powerful or how people create third-party code and offers it out to the world for other people to use it okay this is uh it's a super super common practice and i for example have written a bunch of c sharp libraries myself that people are using out there in the world okay and i constantly use them for my own practice that libraries that other people have have used and have contributed to the community it's a really really common practice okay so i hope this was useful and in order to to further illustrate this idea what we're going to do in the next video is that um we're going to do a hands-on example where we're going to program a bunch of custom components that do mesh operations like remeshing reducing the mesh etc etc but in order to but instead of doing it manually ourselves or instead of doing it with the capacities that rhino common gives us what we're going to do is we're going to use a third-party library so a dll that we're going to download from the internet that somebody is giving us and we're going to use that to extract to use its functionality but embed that functionality into our grasshopper components this again is really really the basics of how modern plugins for example in grasshopper are developed so if you're interested in learning more about that check out our next video mesh components and how to import third-party libraries and use them to your advantage okay in the meantime if you thought this video was useful maybe consider liking the video maybe subscribing to the channel and maybe even hitting the notification button to get to know when we publish new videos we go live or just leave a comment and say thank you because this was nice or say that this was a terrible video and why you think so that's also perfectly fine okay thank you very much and see you on the next video bye bye all right thank you richard i'm happy you find this useful uh let me save okay so what is next uh we're gonna close this what are we doing next i would like to save this here and i'm going to take the person class and i'm going to copy it so that i don't lose it i'm going to remind myself that i need to add a card to vector class from learning chart so this is my this is my video editing notes uh yes victor next video is about g3 sharp which by the way victor helped me debug last time in the last um in the last uh in the last live stream where i was trying to use the library and i was re ran into this problem and he picked up the file and he helped me debug and came up with the solution thanks a lot for that victor that was really helpful yes the next video i'm going to record right now is that video that uh we researched a month ago now and i need to actually pull up my files which i read over there so i'm going to take a one minute break i'm gonna get some water and i'll be right back okay stay there don't go anywhere it's going to be awesome awesome oh that was going to be a more dramatic wait wait so awesome it's going to be awesome awesome alrighty so where were we all right so where were we um yes so we were doing third party assemblies loading libraries and we needed and where do i have the code for that so last time i can't find the code for that so last time last live stream was basically a research live stream where i was doing research for the exercise that i was trying to do right now that i'm about to do right now and console test uh crossover test i see um it's here so is it this one uh test fixed no what about this one oh that's a lot oh of course we need the head yes open file yes okay yes so i think this is the one that i we were doing and this is the head [Music] test stew okay so if that's the case then what i'm going to do is i'm going to create a new file here e7 mesh components so i'm going to take that one i'm going to rename it e7 mesh components i'm going to also copy the head um i'm doing this on my site monitor by the way sorry about that mesh components i'm loading the head all right oh should i mesh components and ah no dynamic simulation oh too bad i did not include this oh no that's not cool we want the full library data components we want the full library [Music] yeah that's not cool so let me s let me fix that so we're going to say okay let me do this real quick because otherwise my ocd is just not going to let me uh let me sleep tonight so so if i open now this i got dynamic simulation and then i'm going to okay so this is going to be here this one is going to go here and this one is going to go here okay and that's going to be dynamic simulation dynamic simulation dynamic simulation components okay so that's going to be this one and i'm going to save this i'm going to close and close and close and then this should be now dynamic simulation components and that's there okay and the file should be okay so now if i copy and paste this one here and i call this mesh components and i call this mesh components all right so we should be able to have here mesh components and then i start working on this and we have the head and what i'm going to do is i'm going to open another rhino on the side and that rhino is going to be my cheat sheet so that i can look at what i did and replicate it so that's going to be here mesh components i'm going to be reading this here and then for mesh components i'm going to be loading in here this grasshopper file okay i need the geometry three okay that's going to be here and then what am i going to do geometry three sharp gradient space uh releases from nougat so how did i do it did i compile it oh it looks like i did okay i compiled it all right so should i just uh do that what is the best way to go about this for the example i may want to do a clone and compile your right i wonder what do you think should we do this on the video just to so that people can so that people have a sense of okay i don't know no template all right i guess i guess we are going to do it yes i guess we're going to do it yeah okay so the video is going to be i will record the introduction at some point the new package is a difference i'll be more a little bit more work to use nougat yeah you can't that it doesn't take that long you're right let's just do it because people might not be familiar with this so so yeah okay so the video is going to be uh the video is going to be [Music] the introduction which i will record at the end then it's going to be probably introduct introduction to geometry three sharp so i will explain the author the library and then i can show the github i clone the repo i run in visual studio and compile the thing and then i take the file and then i put the file in a folder and i start doing the grasshopper work that sounds about right okay you you folks need to remind me to remove to to to to you need to remind me to record the introduction which i always forget and what was the name thomas karsten no what was the name of the author i forget uh scots radiant space about tutorials can someone help me i used to know the name of the author uh but i forget carson [Music] right in space ah ryan schmidt that was easy okay gradient space gradient space um okay so i'm going to start here um [Music] okay so let's do this [Music] second video that's going to be mesh components okay um let's begin so as i mentioned in the introduction uh we're not going to write our own mesh simplification remeshing algorithms whatever that's actually quite tricky and it requires like quite some expertise so what we're going to do is we're going to rely on the kindness of other people that have made this work for us and have created libraries of code that they have put out out there for free as open source and that we can benefit from this is fortunately very often the case these days with a lot of people who contribute open source code to the world and that researchers academics or even for commercial purposes sometimes that you can use so in this case for the case of mesh manipulation i am actually very fond of this library called geometry 3 sharp created by gradient space which i believe is kind of a brand name that the author ryan smith has been working on for quite some time ryan's work is amazing you should definitely check it out he was the author of mesh mixer which will ended up acquired by autodesk and he also works for epic games making a lot of three modern he's a really really interesting guy so in his website gradient space you have a set of libraries that are available for use it has like a grasshopper a slicer library gcode library he's very much into 3d printing and he also has a set of tutorials for using c-sharp his his work in unity or stand-alone so for example a lot of the code we're going to be writing is informed by these tutorials that he has here so if we go to open source and if we go to the geometry three sharp you can see that he has a link to a github repository which contains the code for the geometry three sharp library this library is basically a full geometry kernel it has vectors it has a lot of curves operations etc etc polylines blah blah but especially it's really good for mesh simplification and mesh algorithms so if you're interested in learning more you can just go to the readme and look at the documentation there's a bunch of tutorials there's lists to the core methods that you can find it it takes a while to get used to someone else's code but if the author is nice enough to provide a good documentation then that's typically a good way to start so we have the c-sharp library the open source is here but what do we do with this if you're perhaps like a bit new to c-sharp development you might feel a little lost so typically in c-sharp we use two things in order to use someone else's code if you go to releases you can see that here in text you can see that there's a bunch of official releases so packages that the author has bundled and that the author considers working fine maybe it has some bugs but it's something that should be published as usable but if you look closely in this case what we get is that these releases are nuget packages nuget packages is the form that visual studio has to have some kind of central repository of libraries that people can add to their own projects this would be very interesting if we were already working with a visual studio project so we just insert the new nuget and we're good to go or if we were working in unity which i believe has nugget support as well i'm not entirely sure about that right now but because what we need is for our grasshopper plugin what we need is just the dll the file the file that contains all the code what we're actually going to do is instead of going through the nuget package what we're going to do is we're going to download the source code we're going to open it in visual studio and we're going to compile it ourselves which is something way simpler in c sharp is much simpler than it actually sounds so what i'm going to do is i'm not even going to bother with forking blah blah version i'm just going to double i'm just going to download the whole repository as a zip file and i'm going to put it on my desktop okay if i look through my 17 windows you can see that the zip file is now here i am going to extract it into geometry blah blah blah master and now i have this folder and in the folder you can see that i have the visual studio project that contains the food library so if i do for example if i click here on geometry three sharp blah blah you will see how all of a sudden i have a solution with the geometry three sharp project loaded all all and then if i go to core for example and i can see for example i have vector array i have a class for vectors arrays i can i have a utility class i have units i have for example g3 interfaces file system i have a lot of i can have the vector i can actually check the source code of the project which is extremely extremely cool um so i'm really i'm actually really happy thank you very much ryan for your contribution but because we're not going to modify the source code which we could if we wanted to extend it um in uh write our own functions if we found the bug we could do it here we're not going to need to do that what i need is to take this project and to compile all this code into a dll that then i can load into grasshopper so the way i'm going to do that is by going to here to build build solution and then there's going to be some stuff going on here and he told me that yeah this work it succeeded so we're good and then inside of the project this folder has popped up called binder bin and in bin and in debug you can see that i have these two files this is a debug file we don't really need that and i have the geometry 3 dot dll file that contains all the code all right so that's going to be um that's going to be the file that i need so what i'm going to do now is i'm going to um take that file and i'm going to paste it into the file that i had next to the folder where i have the files that i'm going to be using in right now so if you see i already have my all my previous exercises and all of that we have it here so this is like the prototype for our plugin or correct and then here i have a mesh components section where i'm going to be writing new components that are loading from this library and then here on my rhino viewport i have this low poly version of a 3d scan of my head that i did a few years ago do i look i have this 3d scan of my head which is a mesh object which i'm going to be using for debugging and testing okay all right so we are ready we have grino file graph profile and we have the compiled file which is next to our grasa profile so the next step is going to be writing our first um writing our first component that takes a regular grasshopper mesh and converts it into a g3 mesh so let's take a look at how that works um [Music] okay so how am i going to do this the first thing we need to do um where can i look at the image this one and where is the mesh the mesh three okay that was here and then the first thing is converting from mesh to d mesh three okay how do i explain why we need to do that how do i explain why we need to do that we need to do that because meshes in rhino are not compatible with meshes in g3 so we need to do this kind of translation is that too obvious how does that relate to the previous video related to the previous video um i may just start explaining this right away because when you call okay message is not cross-platform yeah because it's for the same reasons all right let me let me try if not we can just uh go over again [Music] the first thing we need to understand is that for the same reasons that i have explained or even more obvious reasons than what i have explained in my previous video it turns out that because in rhino we are working with meshes that have a particular way of a particular internal structure a particular way they work those meshes are not going to be compatible with the way the g3 library treated treats its own meshes and it turns out that the g3 sharp library has its own mesh structure called the d mesh three and if we actually look at the documentation you can see that it's a dynamic index triangle mesh and it has all this like goodness about why it's great and what elements are linked to each other and the way the internal storage is it's actually a really interesting read if you are interested um in learning more about how different meshes can be about how meshes excuse me can be represented in different ways and we can actually even look at the code so if we go to the source code you can see that inside of mesh there is the mesh3 class and you can see that it's actually quite some quite a code base of almost 2000 lines of code more than 2000 lines of code on how to represent meshes so it's actually this is the goodness this is all the power that we're drawing from bringing this library into rhino into our grasshopper plugin and and all the power that we're gaining the problem is that because rhino meshes are different than g3 meshes there's going to be a process of conversion that we're going to have to do ourselves so let's first create a component that is going to take any rhino mesh or grasshopper mesh and it's going to convert it into a d-mesh three the ones that are used the one that is used by g3 because we will need that to plug those meshes into any other component that we write that makes mesh operations so how are we going to do that so i'm going to open the the mesh components i'm going to drop here an empty mesh parameter i'm going to set this mesh here okay and then i'm going to write a c-sharp script component that is going to take any mesh sorry sorry for shouting it's going to take any mesh and it's going to split out a d match 3. okay so then i'm going to plug this in here i'm going to make sure that this mesh is actually a mesh so oh you can see it i'm clicking on mesh so the input is a fully qualified grasshopper mesh and then i'm going to write my code here first of all the first thing i need to do is i need to remember to load my assembly so i'm going to load my app i'm going to load my geometry 3 library here i'm going to load that assembly okay and then the next thing that i'm going to do is that i need to load that assembly into my code i need to do that by namespace so if i didn't know what the namespace was i can look at the source code and i can see that the namespace is g3 so that's what i'm going to do i'm going to say using g3 all right and then for conversion what we need to do is we need to take this mesh and we need to convert it into a d mesh three object so i have d mesh three right dms three object so what i could say is i could create a uh dms3 variable i'm going to call it d mesh and that could be a direct cast from the from the mesh that is coming in into the d mesh object i might feel inclined to do that this is what we did in the previous video as an example but if i do this i'm going to get an error which is that the computer doesn't really know how to convert from a rhino.geometry mesh so that is the type of the object that is coming from the input and the g3.d mesh three which is the target mesh that we're going to be using in g3 it turns out that because it's not a type that is derived from one another they're just so different from each other that the computer doesn't really know how to cast one from the other so that's a little bit of a problem but fortunately because meshes are meshes what we will be able to do in this case is that we will be able to actually do that conversion ourselves the conversion is going to be just as simple as creating a empty d-mesh3 object and then taking all the vertices from the original mesh and copying it to the d-mesh and then taking all the faces of the original mesh and copying them to the target mesh we're going to have to write a little bit of an algorithm to make that operation but it's going to be actually very very easy so let me show you how to do that so i'm going to say this is my algorithm all right and what the first thing that i would like to do is i would like to create an empty d mesh the way to do that is creating an empty d mesh three and then i open parenthesis and you can see that i get a bunch of options do you want normals you want colors uvs three groups i want everything so i'm going to say true true and true also by the way when you're when you're working with a new library you don't really need to know all of this how would you know the way to know about all of this is that you have to read the documentation you have to check some tutorials in order to understand how the author what kind of methods what kind of patterns they give you to work with and i know that i have to do true true true because i actually spent a full live stream researching for this video and trying things out running into problems and i would like to very very strongly credit victor lin who is part of the community who was on that live stream he was helping me real time and then took the file and gave it a second check whatever and it was super helpful to make this happen so thanks to you victor who are who might be watching this video right now so all of the things that i'm going to be showing i don't know them off the top of my head i know them because i've done some research i've looked through the documentation and i've tried things out okay so don't freak out if you take a new library and all of a sudden you don't know how to use it that's actually the norm not the exception so i'm going to create an empty create nt mpd mesh 3 all right and then once i have the empty dms 3 what i would like to do is i'm going to copy all the vertices from the original from the original mesh to the d mesh one so copy all vertices so what i'm going to do is i'm going to write a for loop and i'm going to say for i equals zero i is less than the amount of vertices in the original mesh so mesh dot vertices dot count right and then i plus plus what i'm going to do is i'm going to go over each one of those vertices i'm going to copy it and i'm going to add it to my d mesh alright how does that look like i'm going to create a 0.3 f object called vertex and that's going to be the vertex that i'm going to take from the list so from sorry from the mesh from from the original mesh from the vertices list i'm going to take one at a time and then what i'm going to do is that to my d mesh so dm which is empty right now i'm going to append you can see that i have two options a pen triangle per vertex you probably know how that we're going to be using append triangles as well very soon right i'm going to append a vertex and you can see that it asks me for a vector 3d but that's not going to be a rhino vector 3d is going to be a um is going to be damn it it's going to be a a a g3 vector 3d or is asking me for um four coordinates so what i can do is v dot x v dot y and v dot z okay the only thing to keep in mind here that i'm using 0.3 f just because vertices are 0.3s but also because append vertex takes floats and not doubles it's just something to keep in mind let's see if this works so far something is not working no overload append vertex takes in three arguments interesting that's not how it works oh wait wait wait wait wait oh that's true i actually did change the code when i was researching this hold on let me let me let me let me take a quick look at this hold up victor did we change the source code because in my example in my example we have append vertex and we have three flows here huh did we change the source code i believe we did let me see uh geometry sharp master so if i open this i think this is the one that you're using the mesh dms3 append vertex dot vertex dot yes we did [Music] interesting so we did extend the library now should we do that here should we extend the library here or should i just use a vector 3d a g3 dot vector 3 d and create a new g3 vector 3d so this would work right x v y and then this would work correct e3 and then this will be okay this works so what do we do now what do we do now oh no um would it what is more or less confusing um i'm going to change the code why not i'm going to change the code and vertex and where is this okay so let's just let's let's do it then okay okay okay sorry for the introduction for the in interruption and so it turns out that i had forgotten when i was doing this research i did actually extend the original library to accept three doubles as an input for app and append vertex because otherwise if you do pm dot append vertex the four overloads that we have is either a vector 3d which is not a rhino vector3d it's a g3 vector3d or two new vertex infos or like a mesh and the id whatever and it just just feels convenient to have these three these three inputs right the alternative would be if we were to not extend the library what we need what we would need to do is to say vector 3d v3 is equals to a new vector 3d and then all these parameters here however this is not going to work well actually it does work well it doesn't work well because there is an ambiguous reference exactly so vector 3d now now that i have included g3 it turns out that both rhino and g3 have a class that is called vector3d so now the name vector2d is ambiguous the computer doesn't know if this is if this is rhino or if it's g3 so we could solve this here by saying g3 and then g3 dot vector blah blah blah and then use this and now this works fine but i kind of like the possibility of having three doubles as an input so why not just do a small modification systems open source we can extend the library and then just add more methods to ourselves so i'm i think that's an interesting exercise so we're going to do it so i'm going to undo all of this and i would like to go to the original library to add a new method up and vertex that takes three doubles just because it's convenient for us so let's do that so what i'm going to do is i'm going to go to the original this is my original visual studio project the source code that i downloaded i'm going to go to the d3 mesh class and i'm going to try to find the append vertex method which is right here and if i press f12 you can see that i go to where this method is defined it turns out that we saw before that there's four overloads so there's a pendant vertex another append vertex here and there's probably more uh on top append vertex here and append you see this is the vector3d from g3 okay so how about we extend the library here and we say and we say i'm going to extend the library with a new overload to accept three doubles so that's going to be public integer append vertex and this is returning an integer just because all the other overloads are so i want to stick to the convention so double x double y and double z i do that and then what i can do now is here i can create a vector3d v it's going to be equal to a new vector3d with the x and y and the c properties all right and then what i'm going to do is i'm going to use this vector to pass it on to this append vertex here so what i'm going to do is i'm going to say integer result is going to be equal to attend vertex with this vector that i just created and then i'm going to return that result because this append vertex gives me an integer back which is probably either the id of the vertex or some integer flagging whether if the operation went fine or not and actually what i can do is i can shorthand this a little and then just say can you just return whatever you are getting out from append vertex okay so by doing this i have just extended the library i created a new method that simply gives me a new interface three numbers to an operation that was is basically saving me some code to write some code on on grasshopper by embedding this code inside of the library so now it's just going to be as simple as building the solution the solution gets compiled i get a new dll file and that new dll file should be somewhere here so this is my desktop uh bean debug geometry 3d from the this timestamp so that work that looks good and then what i'm going to do is i'm going to put this back i'm going to overwrite this one i'm going to delete this one which i cannot because it's probably been used by grasshopper so i'm going to save this i'm going to shut everything down shut rhino down i'm going to try to delete now and now it's good i couldn't delete it before because it was being used by rhino so i'm going to place here the new version all right and i'm going to start things again so i'm going to open rhino oopsies sorry i opened the wrong right now no okay so i'm going to open mesh components and i'm going to open my new file and i can see that oh and now it's working now it's working because it's picking up the new dll and this append vertex actually works now and if i do dm append append vertex you can see that i have now five overloads the first one is xyz then the vector then the tuning vertex info and the mesh and the blah blah so nice that was a way to learn how to extend the library that was actually pretty cool i think i'm going to give myself a pad in the back all right so we have the we had the library with we had the component sorry let me recap so we had the d mesh that was empty we have copied all the vertices from the original one to the target one okay so now what i would like to do is i would like to do something similar where i'm going to copy all the faces all the faces and i actually forget if i also extended the library for this so we may have to do it again i don't know for in i equals 0 is i'm going to iterate over all the faces faces.count up count basis.triangle count we're going to do triangle count because um we're only going to copy the vertices that are try the faces that are triangles because d mesh doesn't take quad faces but rhino accepts faces that have four vertices so we're only going to copy the triangle ones and then i plus plus and then what we're going to do here is we're going to say first let me take the mesh face that is going to be at mesh dot basis that give me the face that is at position i all right and then if that face if yeah actually i think this code doesn't so let me try with all of them i get the face and then if mf dot is triangle then what we do is we say dm dot append triangle and then this one actually has indices so i don't need to i don't need to and then i can do mf.a m f dot b and m f dot z remember that triangles are typically defined by the ids of the vertices that the triangle is joining so if the triangle is joining vertices three five and seven so that is the order in which you need to plug them so that's typically integers all right beautiful and then with this i think we should be good output so that's going to be d mesh 3 is going to be equal to this object that we just created the m is that true i'm going to run this code it looks like it works and i got an object of the type g3.dmesh3 which i think it's looking okay to me all right now one thing that i'm going to do is because this idea of converting from a i i'm not gonna do that i'm just gonna i'm just gonna keep it here or not i'm i'm going to do it sorry we're learning tutorials so because this idea of converting from one object to the other might be something that i might do a lot over the course of this plugin development why not just abstract all of this into a function so why not create a function here i'm going to create a public function that returns a dmesh3 object and that is going to be called convert mesh it's going to take us an input a regular rhino mesh okay and then what i'm going to do is i'm going to copy all of this here so inside of the function giving any mesh i'm going to take that mesh and i'm going to create a new empty mesh copy all the vertices copy all the firsts and then return that object if that is the case then what's nice about this is that i can delete all of this and then the main algorithm is just as simple as converting the original mesh into a d3 mesh all right the code is a little cleaner it's more elegant and then i can also now copy this function and copy it to a different component and then reuse my code things are nicer more encapsulated etc all right beautiful what are we going to do next i think the next thing that we're going to do now is we're going to take we're going to do a little bit of deconstruction and then we're going to write a component that takes a d mesh 3 and prints out some properties so the amount of faces the amount of triangles etc just some information okay let's let's take a look at that hey chandra how are you doing could you hear the background noise because my neighbor is mowing the lawn that's very nice all right all right beautiful so what are we going to do the next thing we're going to do is let me just do this and then the outputs are going to be i have i have my cheat sheet here on the side the outputs are going to be whether it's valid whether is the vertex count what is the triangle count now we're going to learn the minimum edge then and uh what is it going to be average edge length and then this is this one okay all right beautiful i've gone ahead and created this c-sharp script component that is taken in a d-mesh three and that is going to output a bunch of properties that we can learn from the mesh three objects this is going to be super interesting so the first thing we're going to do is i need to type this input so remember i need to right click here and say that the type has to be of some kind but we have the problem we discussed in the previous video we don't have d mesh three here because it's not part of the rhino common or the grasshopper framework so we're gonna have to rely on conversions so i'm going to choose here the system object just because it's the root of that all objects inherent from and then i'm going to double click here and um and start doing some so first of all i'm going to write my algorithm here and the first thing that i would like to do is i would like to take this generic object and cast it into a d mesh3 object so how is how we're going to do this well because it's coming from a d mesh three we already know that this data is correct so the only thing that we need to do is we just need to cast it so that it's properly typed here in our algorithm the way we're going to do this is by saying d mesh 3 dm is going to be whatever is coming in from the component which i'm going to force i'm going to cast to an object of the type d mesh 3. however this is not going to change to to work because i have forgotten to reference the assembly and all the things that i should have done so i'm going to right click here manage assemblies i'm going to drop here my geometry 3 library that i have it here and the recent so i don't even need to look for it in my on my system and i need to remember to say here using g3 all right and as soon as i do that then this works and then this algorith this is already uh picking it up all right so um what is next well the next thing that we like to do is i would like to do some queries here so what i would like to do is i would like to say well first of all the output is valid it's probably something that i can read from that mesh in itself so i'm going to make this a little bigger so if i have my d mesh and i type dot you can you should be able to see i don't know why we're not seeing this but you should be able to see like a list of all the different properties that i can read from the object all right so if you check the documentation it turns out that there's this function called check validity which given it takes a false and it takes a failed void return only and if this works yes so i'm not sure i'm not free i'm not sure why the autocomplete is not working oh that's probably because when i loaded the ide because i loaded the reference but i didn't refresh this so let me try this again dm exactly the autocomplete was not working because i loaded the assembly and i loaded this but when this script editor opened it didn't load the assembly so i didn't have it in memory so i can now say you can see that i can do check validity and then i can allow non-manifold vertices so i don't want to allow that and i want the failed mode if it's not valid to just to tell me that it's not valid i don't want to throw an error i don't want to use any debug assistant so that's what i'm going to do and if i do that you can see that now it is valid all right another thing that i probably want to check out is vertex count there has to be something dm.vertex count is there something like that vertex yes vertex count so i can see how many vertices there are right i can say triangle count dm dot triangle count let me run this i'm going to run this and you can see 500 and we can also add here edge count no edge count what if we do that so i'm going to say this this this this this this and this and i'm going to load this again and here under edge bound the m dot edge count all right and this tells me that this mesh has 1500 edges which is kind of cool all right now what about edge length edge length the average etc etc well it turns out that dm the meshes they have this thing called the edge no sorry i'm running too fast it turns out that the g3 library has a method that can give me statistics about a particular mesh and it does so because those statistics are not so the way this works is that i can say mesh queries this is a class that lives inside of g3 mesh queries dot edge length stats this is a function that takes in a particular mesh so that's going to be dm and it returns at as outputs it returns computation statistics about the different lengths of the edges why is this like this why not just dm minimum edge maximum edge etc well that's probably because the designer of this library thought that perhaps performing those computations was uh expensive and that it would only be worth if the user actually needs to know them but embedding them by default in a mesh was probably too much of an overhead so they probably thought well people who want to know the length the average length of the edges is probably going to be like a not a very popular thing so why waste resources and memory on that so if people want to know that they should just ask for that information right away so explicitly so you can see that we're in order to get that information we need we have out parameters so i'm going to have to define a priori minimum length average length and maximum length and then here i'm going to say out minimum length out average length i think the order is not correct it's maximum length and then out average length okay and with that i might be able to say minimum edge length oh i'm very sloppy with the typing today minimum length and then let's see if this works yes the minimum length for my mesh is 0.06 units whatever that is so i'm going to copy paste this and say um average length and then maximum length and then that's going to be average length and then maximum i do this i press this and you can see that i have some additional stats related to my mesh okay beautiful what's to remember about this i had to load my assembly so that both components had access to the same dmesh3 structure and i had to remember to cast this structure to cast this object this generic object to a dmh3 so that i could access its properties all right beautiful so now i have a way of constructing d mesh threes and have a way of retrieving information for them so i think it's right we're right there it's the right time to now start using all the powerful goodies in the library to start doing things such as remeshing vertex reduction and all the cool stuff all they could all the cool mesh manipulation stuff let's take a look at that [Music] how are we doing over there okay it's gonna go longer than i thought but it's fine um okay the mystery analysis okay [Music] and then i'm going to take this and the mesh three bracket vertices and that's going to be for example and that's going to be i'm going to delete all of this and then it's going to be um and then ux vertex count and final birthday [Music] there's going to be reduce vertices then here what are we going to do i'm going to show the triangle the tutorial remission and mesh constraints this is where i learned this from i forget mesh simplification with okay i think it was this one as i mentioned before one of the big one of the big one of the most powerful things about this library is that it has a lot of functions and a lot of methods to perform topological changes to to meshes that means changing the shape changing the amount of vertices triangles with different optimizations reductions targets remeshing is actually quite quite interesting and very powerful if you want to learn more about what's possible you can go to the tutorials and for example we're going to do an example right now that is derived from mesh simplification so just simply removing vertices in a strategic way and we will also do a few more examples about remeshing for example so what we're going to do now is we're going to write a component that takes a mesh a d mesh and then given a an amount of target vertices it tries to reduce that mesh to that many vertices so for example we can see that the head that i have here has um 502 vertices and if we wanted to reduce it and make it more low poly for example to 100 we could write we could use this component that i'm about to write right now so um so how does this work um all right so the way we're going to do that is by i have created this c-sharp script component that is taking a d mesh it takes an amount of target vertices and an integer and then going it's going to spit out this mesh the d mesh and it's going to also tell me the amount of vertices that it had before and the amount of vertices that it ends up after the simplification okay just to verify the way we're going to do that is i'm going to open my editor here and then i'm going to start with my algorithm as i typically do so what i'm going to do is i'm going to say i'm going to say algorithm and then i'm going to say what i'm going to do is first of all i have the d mesh that is coming in okay what i would like to do is first of all i need to cast that d mesh to uh uh an object because as we said before this is a generic object i need to cast it to a d mesh structure now the second thing that i'm going to do is i'm going to clone the d mesh all right i'm going to clone it because since i'm going to modify it what i may not want to do is to modify the original d mesh that is coming in from the grasshopper component it turns out that grasshopper typically doesn't do this it doesn't modify things that are coming from the inputs because grasshopper has a way of creating clones and making sure that you're not referencing original objects but it only does that with rhino and with grasshopper types if you have your own custom types it doesn't do that so that's why what i need to do is i need to make a clone of this to make sure that the modifications and the rematchings are happening on the clone and not on the original mesh that is coming from in from before the input so the way to do that is i'm going to create another variable d mesh 3 i'm going to call it um actually i'm going to call this one the cast and i'm going to call this one dm and that's going to be a new d mesh 3 object and if you start looking down you can see that actually there is an overload for the constructor that takes a copy and allows you to create an empty one as a copy of a different one so i'm going to use this i'm going to say here cast and then true i want all of this yes i want all of this and now i have a new object that is a copy of the previous one that i had that's pretty cool okay now again how do i know this i know this because i've done some homework i did some research i went to the documentation and i found that there was this method and i also went through some trial and error and and i found out that if you make changes on the original copy then you would make changes to the previous object which led to some so you don't need to do this you don't need to know this out of the box and any new library that you start working with you will need to get familiar with how the library works the documentation et cetera et cetera to make sure that you're using it correctly okay so there's always like a little bit of a learning curve when it comes to working with new code that someone else is giving you all right now what i could do now is before i do anything what i can do is i can make sure that i output how many vertices this mesh has just before i make any changes to it so in my previous vertex count output i'm going to output vm dot vertex count so whatever it is right now i'm going to output it and if i run this code this should give me 502 like it did before all right cool so what i'm going to do now is i'm going to reduce the mesh the way this is done in g3 is that you create an object called a reducer and i'm going to call this r and i'm going to be equal to a new reducer object that needs a d3 mesh as an input okay and then once i have created this reducer object loaded with the mesh then to this reducer object i can ask many things many ways of doing reductions and if you're curious you can see fast collapse blah blah reduce to edge length triangle count etc etc and what i am going to use for this one is to reduce this to a particular target vertex count so that's going to be whatever is coming from target vertices from the input again how do i know this because i went through tutorials and i found out that this is how it works all right beautiful and then the outputs the outputs are going to be the mesh out it's going to be this object that i have reduced the m and final vertex count is going to be dm vertex count all right and if i do this and i run this code you can see that i get the d mesh out i get the previous vertex and i get the final vertex count which is now 100 all right so can we check this out i'm going to hide the original mesh and i'm going to make sure that in the preview i can preview the mesh edges so that i can see those triangles i'm going to hide this one i'm going to add this one this one and i'm going to i'm not getting a pre visualization that is weird let me make sure i'm going to plug in here a mesh and i'm going to plug it into the d mesh out oh but i get an error what is going on here well it turns out that grasshopper cannot visualize the mesh that we have reduced why it cannot for the same reasons that we had here it turns out that d mesh is such a different structure that that grasshopper has no default methods or no default knowledge of how to take something that is given from a third party and turn it into a mesh that is renderable by rhino that's why we cannot really see it here in the viewport right now so what is the solution to that we need to do the opposite process that we did here just like we had a mesh 2d mesh converter we're going to have to write a component that does d mesh 3 to rhino mesh converter okay just as simple as that and then if once we have that conversion working we will be able to plug in here a d mesh 3 to rhino mesh component and be able to visualize that okay all right shall we get to that i think that's actually going to be quite easy so let's write a dmesh2 mesh converter all right okay um i have now created this c subscript component that takes in a d mesh in and i'm going to make sure that this is on this type system object and it's going to spit out a regular mesh and i already have a mesh component here and a panel just ready for whenever this works and for the time being i'm going to plug this into directly to the original conversion to make sure that if we get the original head converted back to a mesh then that probably means that the conversion happened correctly so how about we now write some code to go from a d mesh three into a regular mesh so as we typically do i'm going to cast the object vm is going to be equal to v mesh three from the match three and i forgot to add the library so i'm going to have to do using three and i'm going to add here the assembly which i forgot to do and this now works and now here what i would like to do is the opposite process so i'm going to create a new mesh and i'm going to i'm going to create a new empty rhino mesh i'm going to copy all the vertices i'm going to copy all the faces and then i'm going to speed that out through the component all right so i'm going to create a new mesh copy empty rhino mesh so that's going to be a new mesh like this all right i'm going to copy all the vertices so that's going to be that's going to be for in i equals zero i is less than vm that vertex count i plus plus and then what i probably want to do is i probably want to say if dm dot is vertex so this is a check that we were doing because we were getting some problems with some uh vertices that were not uh correctly copied so this is just a check to make sure that the vertex is valid all right uh it's a g it's a it's a it's a g3 it's a d mesh thing so what i'm going to do is i'm going to copy uh the vector so dm dot get vertex i'm going to get the vertex at position get vertex at position i and you can see how the return type is a vector 3d but remember it's a g3 back to 3d not a rhino common one all right and then what i need to do now is to the original mesh m to vertices i want to add a vertex at coordinates x y c so that's going to be v dot x v dot y and for the mv dot z and you can see that for the g3 vector 3d class is not uppercase but it's lowercase all right all right so i have copied all the vertices now i can just copy all the faces so the same thing for i and i equals 0 i is less than vm triangle triangle count i plus plus and then this is going to be equal and then if vm is triangle just checking in checking in and actually this is probably parenthesis your product parenthesis is dm if this is a triangle then what i'm going to do is i'm going to i'm going to retrieve the index of the triangle so i'm going to say vm dot get triangle at position i but you can see that the return type is this weird thing called index 3i index 3i is basically a collection of three integers imagine a vector that instead of doubles had integers is the same thing it's a g3 structure that contains three integers that represent the ids of the three vertices so and again all of these things i know because i i was reading the documentation so i'm going to create a variable of the type index 3i which i'm going to call t or triangle and then what i'm going to do is to divert to the mesh to the faces i'm going to add a phase that is going to have three indices and the indices are going to be t dot a e dot b and d dot c all right all right and just some sanity when we create meshes from scratch all the normals the normals don't are not there the norms are not calculated dynamically and that's not good because it then we visualize the mesh we're not going to get like nice shading the shading depends on the normals so what's interesting to do is to make sure whenever we create meshes from scratch in rhino to make sure that after we've done everything we rebuild all the normals so that they get nicely rendered in so now the outputs we're ready so mesh the output is going to be this object m that we just created and things are looking good so you can see that for this one i am getting a visualization actually i can i don't even need this because this is the main output so i can i'm getting a visualization of a rhino mesh that has been converted from the d3 mesh that i had here all right so this is great so we're ready then to now take this and see what the effect of the reducing the vertices what the effect wash was so now i'm going to just plug this in here and what we're going to see is that something happened and it's not working something is not working here and this was actually kind of one of the big problems that we faced when we were doing research for this video and again victor lin actually helped me a lot to figure this out for some reason we are not entirely sure why for some reason it turns out that when you make a reduction to the mesh with the d with the g3 library there is something about the structure of the vertices in the faces that happens internally that keeps that mesh valid within g3 but it doesn't it becomes an invalid mesh before um for rhino turns we're not sure what's going on but what we found through doing some research is that if we actually took the reduced mesh and we create and we created a new clone of that mesh then all the invalidity and all the misreferences and whatever was going on actually went away so what we did here was and i'm going to copy this paste here for some reason the reduced mesh had invalid vertices after the reduction and this gets solved by recreating that mesh and making a copy of that reduced mission again we don't really know uh why this is going on but we found that this was a solution if ryan smith is watching this and he wants to chip in i would be super happy to to hear what's going on and then what i'm going to output is instead of this is copy all right we're not going to output the reduce mesh but that copy that we made from the reduce mesh beautiful all right so then but that's true then it turns out that now i am perfectly reducing that mesh and that mesh gets converted into a native rhino mesh that i can now see reduced and check this out so now more vertices all the way to the top and now less vertices less vertices all the way to even just like a super super low poly and 17 vertices kind of head all right how cool is this huh all right again this is very cool again thanks to ryan schmidt's word work from gradient space which made all of this possible all right beautiful so we have a component that reduces a mesh to a particular target amount of vertices turns out that the g3 library allows us gives us method to reduce meshes also for target faces and for other measures do you want to take a look at how that works let's implement more of this um okay um we're going to do reduced triangles um uh okay we're gonna get back to it very soon okay these ones i'm not gonna walk through them because it's basically the same thing so to this example i have added two more components that i did offline and because they're so similar to the triangle one i'm just going to i'm just going to show them how it works one of them is a mesh reduced triangle so this one is the same as the vertices but instead of target vertices what we get is how many triangles do we want to end up with and remember this mesh right now has a thousand triangles but if i reduce the count of triangles you can see how all of a sudden i start getting a very similar effect i get a low polygon version of the face right all the way down to four triangles or even three triangles and zero triangles so the minimum is basically these four triangles is the most oversimplified version of my head really which is kind of cool and you can see that the code is the exact same thing so we're casting we are avoiding we we're cloning the objects so that we avoid changes to the original one we reduce it but instead of using vertices we use triangles and then we clone the object again to avoid invalid vertices all right and that's the one that i'm plugging in here and there's a similar one that is called mesh reduce edges and the idea is that you can create a very similar reduction where what you do set is the minimum edge length so what you're basically saying is i'm going to keep all the triangles whose edge is longer than a particular value so i'm going to plug this in here in the visualizer and then you can see that right now because i have zero i am not really cutting out any any vertex but as i start growing you can see that all the edges that are short are start disappearing and then my head only remains with very large triangles all right so that could be also an interesting operation if you are interested in that okay so these are three different ways of reducing the mesh now when i say reducing i mean reduction because what these three components are doing so the algorithms that are fueling these three components what is happening real really underneath is that the the actual topology well topology might not be the right word but um the mesh in itself when it gets reduced the only thing that these components are doing when reducing the mesh is removing elements from the mesh so it's either removing vertices or removing faces or removing edges but anything that remains after the reduction is actually not changed from the original so when you reduce vertices what you do is you keep original vertices but you're not moving those vertices around to reshape the to reshape the mesh so for example you're not really redistributing the meshes so that the triangles are more homogeneous or something like that it's more just a simple culling if you will which is good because it's a very fast operation but if we actually want it to be to make more drastic changes in the meshes so for example redistribute the vertices so that they look more homogeneous so you can see that in this mesh some triangles are really big here and some triangles are very small here so maybe we want to come up with ways of remeshing things in a way that makes the distribution of triangles more homogeneous so that's so g3 the library gives us also ways of doing that so the last component that we're going to write is going to be a remesher and that is going to accept some targets and then it's going to basically change the whole topology of the mesh for to adapt to those targets let me show let me show you what that's going to look like um um so in order to not make this video 100 ridiculously long i've also copy pasted some code that i did offline while doing my research and i created this component that is called mesh remesher as usual it's also used in the geometry 3 library it takes in a d mesh input right and then the the what it takes us also as an input in order to work is basically a target edge length and then how many passes do we want to do in terms of refinement what this component will try to do is it will try to take your original mesh and it will try to redistribute and i'm not even sure if it creates more or less vertices i'm actually not sure about that but what we will try to do is redistribute all those vertices so that the the length of the edges of the the faces is as homogeneous as possible the result of this is that we will have a mesh that will look like all the triangles are almost the same size more or less but it's a it's actually a really really nice practice especially if you're going to be using these things for like 3d printing etc etc the target length is how big those lengths are going to try to to be for the edges and if we're setting the edge length i don't think about it it's probably going to need to add more vertices for sure so that's uh and the amount of passes is how many iterations of this how many iterations of this calculation of this um of this remeshing the component is going to do because it turns out that it cannot calculate this thing uh just in one operation so the more passes you do the more the solution converges to this target edge length that we are setting here so how does that code look like very very similar to everything that we've done before we cast the object from a general object we copy it to avoid making changes to the mesh that is coming from the previous component and then we remesh it and here is where the difference is before we were using a reducer class that was loaded with the mesh in this case we're using a remesher class that is also loaded with the mesh what how what happens internally why they're different i'm gonna let you check the open source code uh but long story short there are a few parameters that you can tweak so you can choose whether if you want to prevent flipping in the normals and whether if the target is an edge length the amount of vertices whatever that is here i'm going to be setting the edge length as the target and then with a simple for loop what i'm going to do is i'm going to run a remeshing pass as many times as the input here so it's just a simple loop that is calling basic remesh a bunch of times and after that just like we had before i am cloning i'm copying that mesh again because we were having the problems of the invalid of the invalid uh of the invalid vertices okay and it gets output so let me show you how this looks so if i get passes zero you can see that the mesh doesn't really change but if i start cranking this up one mesh one over one two three four five six seven 8 9 10. you can see how the triangles in my head start becoming very homogeneous even though also my face is kind of let me bake this to make sure can we bake this yes i'm going to bake this this is my remeshed head and this is my original head which i'm going to copy somewhere here all right can you see and the difference between the both of them this my original one has triangles all over the place and this one has triangles that are fairly homogeneous more or less i'm losing resolution on my nose i'm losing resolution on my ears but so it's implicitly it has like a kind of a smoothing effect that could also be interesting depending on what you are trying to do all right but the more passes the better and then in to make sure that this target length is correct something that i can do is i can i can analyze my mesh with the component that i created before and you can see that the minimum edge length in this case is 0.1 the average is 0.14 which is pretty close to the target that we set that's great and the maximum is 34. so the range is pretty small too and you can see that the amount of vertices and triangles and edges has increased from the original one which is also kind of interesting so this is giving us an algorithm that is changing drastically the topology of that mesh all right beautiful and i think with that uh this is probably enough for this video the whole purpose of this video was to illustrate the idea of taking a an assembly taking a repository in a bunch of code that has been provided to us as an assembly from open source or from maybe a library that we license and we pay for it for commercial use whatever that's coming from but being able to import that library and use it to our advantage in uh in some other platform you can see that because it's c-sharp it's very easy to to bring in and to use we just need to make to be worried that for example in the case of meshes we needed to do translations between rhino meshes and d3 meshes in both ways right and we also needed to be wary that there are certain ways the third party works so we need to read the tutorials we need to read documentation to make sure that we know what we're doing kind of um but that was pretty much it i did not want to get into how mesh amplification mesh reduction or mesh remashing actually works that's a whole other beast okay then people smarter than me like like ryan schmitz can could probably talk much better about that so beautiful so that was it for today i hope this was fun and uh i hope you found this interesting and now my invitation to you is to go out there and check out in the wild what libraries for c-sharp are available out there that you think could be interesting to wrap up into your own plugins your own components bring into grasshopper use them etc etc always remember that people who are putting effort in making open source contributions are humans so credit if they require it is a very good thing to give them uh even if they ask you to not use their code for commercial purposes and license it that's please also use fair practices for that all those things are very important to keep in mind okay and with that this video is done thank you very much for being here if you thought the video was useful maybe consider subscribing to the channel maybe liking the video maybe turning on notifications you know all those modern youtube things that we do these days thank you very much and see you on the next video bye bye um all right so now we need to record the introduction okay and with that that's probably enough for today and what am i going to say in the introduction all right hello this is jose luis here at parametric camp and welcome to a new hands-on video in this series advanced development in grasshopper in this video we're going to continue developing this prototype of the parametric camp grasshopper plugin or whatever we're calling this and we're going to continue with the work that we've done in previous exercises but for this one in particular we're going to focus on creating a collection of components that are going to perform operations on meshes however i would like to keep in mind that the purpose of this exercise is not to learn mesh manipulation algorithms for mesh reduction remeshing none of that the goal of this exercise is to illustrate the previous video in this series where i was talking about how to use external libraries how to bring them into your code and how to use code that someone else has provided for you so what i would like to do in this exercise is use a very popular and super powerful library called uh i'm going to where is this that is called geometry 3 sharp that comes with a lot of really powerful mesh reduction and mesh remeshing operations as what i would like to teach you in this video is how to download that library how to compile it into how to download the source code compile it into a library and bring it into your custom c-sharp script components and create your own components that perform mesh manipulations so for example examples of that is this head that is the mesh that i'm working with has a particular topology of meshes and vertices but what i can do for example is i can perform an operation of reducing the amount of vertices to create a low poly version of this head so that's one thing we're going to try and another thing that we're going to try is called remeshing remeshing is the operation by which we redistribute the triangles the vertices etc so that they become more homogeneous along the mesh so you can see that i'm going to set for example a target length for the edges of this face and the more passes i do in refining this mesh the closer i get to a target where all the triangles have roughly a edge length of whatever number i have set here that implicitly comes with a sort of smoothing of the mesh you can see that i'm losing resolution here on my nose i'm losing resolution on my ears they have kind of disappeared right but it's implicit in the process all right what's interesting is that we're going to learn a lot about using this library called g3 that comes with these objects called the mesh three that contain all these powerful ways of remeshing and reducing themselves again not about the actual algorithms i'm not going to get into that so with that um i think we are ready to start however if you actually want to learn about meshes and how meshes are defined with vertices and faces i have a different video i have a video on my introduction to parametric modeling where i touch specifically mesh mesh topology and how to create them from scratch so if you're interested in that you probably want to check out the other video first before going into this one probably a link will be popping up somewhere on a card or the link will also be in the description of this video alright beautiful so with that how about we go and we start taking a look first at where to find that library how to compile it how to bring it into grasshopper and how to build components using the power that that library is giving us let's take a look at how that works all right that was a lot two and a half hours i can barely speak all right let me save this let me save that that save changes to mesh components yes and all of this uh and then i'm going to write tests okay how's everyone doing huh are you as tired as i am oh you can barely talk excuse me okay okay so let me clear a couple things out okay and then so that's going to be done all right so i think with this we're done thank you very much to everyone for being here um i appreciate that uh we're not going to live stream this afternoon because i have work to do for tomorrow but it was a pleasure and we will continue next time we meet probably next week we're going to take a look at using visual studio to develop grasshopper script components we're going to take a look at the grasshopper sdk we're going to take a look at a bunch of a bunch of things okay so it's it's going to be interesting we're going to keep we're going to keep working at it all right thanks a lot and see you in the next one bye bye
Info
Channel: ParametricCamp
Views: 416
Rating: undefined out of 5
Keywords:
Id: 87Gyz0fMwHg
Channel Id: undefined
Length: 162min 48sec (9768 seconds)
Published: Wed Nov 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.