[AddOn] Blendgraph 2.7 UPDATED (on hiatus)

Thanks, Atom, it’s working perfectly. If you think the screen recording might help me to learn the ropes for developing blendgraph nodes, then please put it up, I’ll definitely check it out.

I hope to be able to put some time into extending this node soon. In the other thread mentioned above, I already talked about switching which variables control which, eg, now we have z = f(r, a) (base shape: disc), but we could also have r = f(a, z) (base shape: cylinder) or a = f(r, z) (base shape: plane).

I’d also like to provide the 3 most common coordinate systems: cartesian (3 linear components), cylindrical (1 angular + 2 linear) and spherical (2 angular + 1 linear). I might use a dropdown list in the actual generator for this, or make a number of additional coordinate-systems-transform nodes, eg, CylindricalToCartesian. I think these would probably make sense as a general mathematical node (transform 1 vector), but I’m not sure it makes sense in the generator scenario (applied to a whole mesh).

Other possibilities would be to also provide a 1-D/curve version of this, so you would have 1 coordinate driving the other 2, instead of 2 driving the 3rd. Actually, come to think of it, it may be best to define some independent parameter (say s), and supply 3 separate function for each coordinate: x = X(s), y = Y(s) and z = Z(s). And I should obviously consider the same thing for the 2D-case, so x = X(s, t), y = Y(s, t) and z = Z(s, t). A 3D version might also be conceivable, where you define volumes. The function might generate points (particles) in a volume, or define some kind of weight at each location in space, or determine wheter or not this location lies inside the set we’re generating.

Finally, I was thinking that having your function defined inside a small one line text field probably limits the expressiveness (if that’s a word) of this node. Wouldn’t it be cool if you could reference a python file with predefined functions, and be able to select/use the functions it finds in there? These function would need to have a given signature, eg, def Calc(s, t) in the 2D case.

Phew, that’s quite the todo-list, I guess…

Wouldn’t it be cool if you could reference a python file with predefined functions, and be able to select/use the functions it finds in there?

That is what the File To List node can do for you. It will read a file then produce a list of entries that you connect to a List node. From there you could connect an Integer node to select which math expression in the list (assuming there is more than one in the file) to use. This would require adding a String Input socket to the Z Surface node. Then you could connect the result of the List node to the new String Input of the Z Surface node.

This way you are not “tightly” binding the file read inside the Z Surface node. It all remains a distributed architecture.

Pull down the latest version of the Blendgraph AddOn from post#1.

This node came about because of a C4D scene I saw posted on another site. The premise is that a single point bounces around inside a mesh leaving a trail of points that form a curve. This node attempts to emulate that functionality. It takes the name of a Mesh Object and the Scene as input then generates a Curve Object as it’s output. The parameters inside the node control how dense, random, or thick the resulting curve becomes. Liero wrote the internal bounce code so a big thanks there! A development thread can be found here.

You do have to install the Blendgraph AddOn for the attached file to work. Try it out on your own meshes! Type the name of your mesh into the String node.

Attachments



27_bg_fiber_mesh.blend (166 KB)

Wow you really got that to work. Another selling point for this addon

Thanx Atom, a example scene like for the Fiber helps a lot!

Thank you Atom!

bgFunctionSurface-20140330.zip (20 KB)

Cool fiber mesh node, Atom!

Meanwhile, I think I got my first (stub-) node ready for the mathematical generation of surfaces; code in attachment. Please note this is a stub only, so it doesn’t do anything yet. I’m mainly uploading this to check (if you have the time and would be so kind :)) if I’m on the right lines with it. Everything looks ok, but maybe I’ve missed a trick here or there.

With a bit of searching around in the code, I came to 3 (existing) files that needed adjustment for my new node (which is in bg_node_function_surface.py): init.py, utility.py and bg_frame_change.py. Some naming prefixes were added, some (un-) registering functions and some node updating calls. Here’s how it looks:


Some additional questions also came up:

  1. Can I have scientific (eg, greek) letters/symbols (like φ and θ) in the texts of my node? It seems to work here (on windows) if I set the encoding of my file to UTF-8 (instead of the default ANSI). Would that be allowed/wise? That’s not really a Blendgraph question, I guess.

  2. Can we have (blender-supplied) user presets on the nodes? Like you can have the ‘operator presets’ when implemented as a regular tool? I’d also like some built-in presets, like you have in the regular solids generator, so that shouldn’t be a problem.

Anyway, on to the real node implementation…

Hi Atom…thanks for your great AddOn.
But i have a question about the missiles node.
I use a simple scene 2 cubes (“laucher” / “target”) an a icosphere grouped in “Missile”

When i click on trace missilesi recive an error:




What is my mistake ? :frowning:

Pull down the latest version of the Blendgraph AddOn from post#1.

You did not really make any mistake. The problem is that the missiles node is more of a programmers node, not a causal users node. If you examine the code you will see my note that I have HARD CODED paths to the explosion animations that the missiles use.


                            # Pick a random explosion sequence. HARD CODED FILENAMES!
                            explosion_map_index = random.randint(0,5)
                            realpath = "E:\\Documents and Settings\\Admin\\My Documents\\Maps\\Animated\\fireball-3_large\\fireball-3_large_0001.png"
                            explosion_duration = 90     # Set length of image sequence, in frame, here.
                            if explosion_map_index == 1:
                                realpath = "E:\\Documents and Settings\\Admin\\My Documents\\Maps\\Animated\\explosion-5\\explosion-5_0001.tif"
                                explosion_duration = 64     # Set length of image sequence, in frame, here.
                            if explosion_map_index == 2:
                                realpath = "E:\\Documents and Settings\\Admin\\My Documents\\Maps\\Animated\\explosion-2_large\\explo-2_large_0001.png"
                                explosion_duration = 70     # Set length of image sequence, in frame, here.
                            if explosion_map_index == 3:
                                realpath = "E:\\Documents and Settings\\Admin\\My Documents\\Maps\\Animated\\explosion-1\\explosion-1_0001.tif"
                                explosion_duration = 69     # Set length of image sequence, in frame, here.
                            if explosion_map_index == 4:
                                realpath = "E:\\Documents and Settings\\Admin\\My Documents\\Maps\\Animated\\explosion_tripple\\explosion_tripple_0001.png"
                                explosion_duration = 120     # Set length of image sequence, in frame, here.
                            if explosion_map_index == 5:
                                realpath = "E:\\Documents and Settings\\Admin\\My Documents\\Maps\\Animated\\boom_blast-6\\boom_blast-6_0001.png"
                                explosion_duration = 260     # Set length of image sequence, in frame, here.
                            ex_dur_middle = int(explosion_duration/3)

You must supply your own paths to your own image sequences to use this node. If those paths fail then you end up with a None texture which does not have a use_alpha property.

Thanks for reporting the bug, I have put code in place that skips trying to load the HARD CODED images if they are not found. This will leave you with working explosion planes that have materials assigned. You can then browse to your own explosion image sequences in the usual Blender manner.

Ideally this node needs some kind of Texture input socket or maybe a list input to handle multiple paths.

How would you handle texture assignment in this case? And how would you handle supporting multiple render system such as Blender Internal, Cycles, Mitsuba, Lux, Yafaray, 3Delight (uhg the list goes on…)

Attachments

27_bg_missiles.blend (340 KB)


@Guy Lateur: I looked over your code and it looks fine. You made all the changes in the correct files. (init.py, utility.py and bg_frame_change.py.)

  1. Can we have (blender-supplied) user presets on the nodes? Like you can have the ‘operator presets’ when implemented as a regular tool? I’d also like some built-in presets, like you have in the regular solids generator, so that shouldn’t be a problem.

You can put whatever you like inside the node but remember that node.update() will run quite often.

One way to handle presets is to just make another update handler like property_update. All your properties do not have to use the same one. This allows Enum/Dropdowns to have their own coded functionality. Also, the update handler does not have to re-issue a self.update() unless it makes sense to do so.

Check out bg_node_parametric_beam.py for an example of how to include an operator inside your node. It is pretty straight forward just make sure to define a unique bl_idname for your operator.

bgFunctionSurface-20140331.zip (5.5 KB)

I’ve attached a first implementation of the ‘Function Surface’ node. The code only contains the (2) files relating to the node itself; I’m assuming the other (3 existing) files have already been updated.

Here are some screenshots of what it produces, for cartesian, cylindrical and spherical coordinates:


There are 3 example objects per coordinate system; from left tot right:

  1. the ‘base shape’ (plane, cylinder and sphere, respectively)
  2. a common use case for that coordinate system
  3. a more exotic example

I’d been struggling with the ‘closed’ properties, until I realised it’s better to use the number of segments along a given parameter (s and/or t), rather than the number of subdivisions (samples). So, instead of specifying how many vertices/samples you want along a parameter, you specify the number of faces/segments.

Eg, if you check ‘Closed’ for T, it is implied that your generating functions are periodic in T: F(minT) == F(maxT). If that’s the case, we can save ourselves some vertices (the last ‘row’ of vertices equals the first one). The number of faces/segments remains the same, though.

Slightly changed node interface (example properties produce a spherical base shape):


There are indeed some problems when you enter an invalid equation. If you observe that your mesh is no longer updating when you change the properties, try to delete the mesh and re-attach the scene-node. Or just try all over again…

Guy, thanks for the updated code, I have integrated it into Blendgraph and reposted the addon.

Pull down the latest version of the Blendgraph AddOn from post#1.

There are indeed some problems when you enter an invalid equation.

I think I tracked that down in your code. Around line #56 of bg_node_function_surface_util.py.


            try:
                currX = float(eval(*expr_argsX))
                currY = float(eval(*expr_argsY))
                currZ = float(eval(*expr_argsZ))
            except: 
                currX = 0.0
                currY = 0.0
                currZ = 0.0
                #raise Exception("??", "Can't evaluate equation x/y/z")

Basically we never want to raise an exception we always want to trap for an exception and provide a default. In this case I just set XYZ to 0.0 and let it go. This does produce an invisible mesh but it does not break the node. If you correct the equation the node starts working again and you don’t have to delete the old mesh and start over.

bgFunctionSurface-20140401.zip (5.27 KB)

Thanks, Atom. I’ve attached a minor (maintenance) update of the function surface node. This mainly involves making sure there are no exceptions thrown in my code, and some general code cleanup. I’ve also adjusted the default parameters. Btw, you may also want to remove the ‘z function polar surface’ node from your release, as that is just a special (obsolete) case of the function surface node.

Now I’d like to have a go at a 3D version of this ‘defined-by-equations’ approach. So instead of having 2 independant parameters (s and t), we’ll have 3 (s, t, u). And instead of generating a mesh, we’ll be calculating some set of locations were we want some object(s) to appear. You can think of the cartesian base shape/effect as a combination of 3 blender array modifiers, like so:


So it should produce something like this, but then analytically. This could give some cool effects in combination with volume shading, for instance.

My first contribution to blendgraph resulted in the ‘DropAndRoll’ layout mode in the object repeater node. It felt a bit weird that you’d need a particle system to set this up, as all you’re using from the particle system is the number of particles/circles.

Thinking about how to do a 3D version, however, made me realise the particle approach probably isn’t so weird after all. Since you already have the repeater node, you can easily reuse its object/scene management functions to allow for (re-)generating multiple meshes in the scene. Also, the items in the ListIn property (‘particle info’?) contain all basic transformations (loc, rot, scale) and some means of animating the generation/appearance (life). Which is nice.

So, putting 2 and 2 together, here’s my mockup for implementing the ‘function volume’ node in blendgraph:

  1. It would have 3 parameters: s, t and u.
  2. It would have an ‘Items’ output socket, just like the pSys node.
  3. This output would connect to a repeater node in standard (particle) layout mode.

Like this:


That’s the way to go, right?

I have integrated your new code into Blendgraph, thanks! (I also removed the first draft Z Function node from the SHIFT-A list).

To create a list output socket you need to import the list output type then create an output socket of that type inside the node init(). Inside of update() you fetch the value of the list, which is a collection and operate upon it as needed.(clear collection and then re-populate).


from .bg_socket_string import bgStringOutputSocket

    def init(self, context):
         self.outputs.new('bgListOutputSocketType', "myList") # Name as appropriate.       

    def update (self):
        # Populate the collection as you see fit.
        collection =  self.outputs["myList"].value
        collection.clear()
        for p in psys.particles:
            print("re-populating particle_list")
            collection.add()
            l = len(collection)
            collection[-1].name= ("%s_%0.5i" % (self.label[:12],l))
            collection[-1].value = "[%2f, %2f, %2f]%s[%2f, %2f, %2f]%s[%2f]%s[%2f, %2f, %2f]" % (p.location[0], p.location[1], p.location[2],SEPARATOR,p.rotation[0], p.rotation[1], p.rotation[2],SEPARATOR,p.size,SEPARATOR,p.birth_time, p.die_time, p.lifetime)
        self.outputs["myList"].index = 0

Your idea of emulating the particle system is a good one. If you populate your list output collection as shown above you could use the object repeater for deploying your results.

NOTE: Each list output collection also has a companion index associated with it. This is used by the List Node to determine which item in the list is actually selected. Setting it to zero is fine in most cases but it should not be set to a value greater than the list length.

bgFuncSurfVol-20140402.zip (28.6 KB)

Updated code in attachment. Changes:

  1. Optimisation and refactoring of function surface node. This leads to Math.py being updated. And both node files, of course.
  2. Addition of the first implementation of the function volume node. This adds 2 more node files, and an update of the 3 usual blendgraph files (init.py, utility.py and bg_frame_change.py).

Screenshot:


Example blendfile (uses function volume node with default properties) (+ object repeater node):

test-bg-FV-007.blend (610 KB)

Question: might there be a problem with the scene update of the object repeater node when the number of objects is decreased? It seems like, when a nrSegments is decreased, we’re left with some previously generated objects – which is confusing. Or is it just me?

Another question: it appears that the size/scale parameter in the ‘particle-info-list-output’ is restricted to 1 single scalar – contrary to the array[3] you might expect. This probably has to do with what you can get out of a blender particle. Still, I may want to use this scaling in a future version, so would it be possible to extend the signature of this socket to provide 3 values (x, y, z) for the scale? The pSys and repeater nodes could easily be modified to support this change. Some other nodes may be affected, too, though.

Question: might there be a problem with the scene update of the object repeater node when the number of objects is decreased?

Yes, there is. That is why I created the Select operator. If you want to decrease the count select all the objects first, delete them, then lower the count.

it appears that the size/scale parameter in the ‘particle-info-list-output’ is restricted to 1 single scalar

This is the way the particle system works. Particles are all scaled uniformly.

If you are planning on having your node produce non-unifomly scaled objects then you may need to extend the Object Repeater. Inside the code of the Object Repeater you will find that I detect where the list comes from based upon the item count in a list entry. So make your list entry have a different count and write specialized code to handle the prarameters inside the Object Repeater.

Ok, thanks for the info. Could you elaborate a little on why you have a layout mode in there? Wouldn’t that be a more suitable way of distinguishing between different types of input lists, rather than the length of the items in the list? Or does it serve another purpose I’m not getting yet?

Also, as it is now, in my function volume case, it generates quite some overhead, as I’m only using 30% of the data on the input (only location, so 3 floats out of 10). Maybe it would be helpful if I made an alternative object repeater node (hopefully one day to be merged with yours) that seperates the input sockets, eg, one for location, one for rotation and one for scale (basic object transformation parameters) (all float[3]). If, for example, scaling has no input attached to it, no scaling would occur. This separation would be great in combination with the volume node, since the scaling/rotating parameters will probably be most easily calculated by a separate node.

Anyway, I’ll think about it. I’d also like to have a go at the decreasing-the-count thing, btw, as it’s been driving me nuts, especially while debugging – I always immediately think something’s wrong with my code… :slight_smile:

Could you elaborate a little on why you have a layout mode in there? Wouldn’t that be a more suitable way of distinguishing between different types of input lists

This was to facilitate your first ‘DropAndroll’ circle code. I just plopped your code into the Object Repeater. It should be it’s own node generating a list that emulates the particle system.

Maybe it would be helpful if I made an alternative object repeater node

Feel free to clone the current Object Repeater and make your own. This way you don’t have to deal with my mess of code. As you are finding out it is not ideal programming. I just kind of got it working and released it so I could move on to the next node. I do certainly want to revisit it sometime.

. I’d also like to have a go at the decreasing-the-count thing,

The first thing that comes to mind is that the count needs to be saved upon generation. When update occurs, check old count against new count. If counts are different then a loop should be run that creates the names of the repeater objects. Those objects need to be unlinked from the scene and removed from memory to prevent memory leak. Then the new count needs to be created again and linked to the scene. I didn’t bother implementing it as I saw this AddOn more of a proof of concept rather than a work horse kind of tool. This will also impact performance as well, especially with large counts (i.e. unlinking and removing from memory 5,000 objects then creating and linking 5,001 all within a frame change or update). To optimize this you could make a difference between the two counts to determine what needs to be created, what can be re-used and what needs to be removed from scene and memory.

Any idea why get only one underscore when I try Font Repeater node? Blender 2.70 BuildBot OSX.

Attachments


the same issue
Sverchok have bakery node, soon will be able to cooperate with entire blender. So, blendgraph could be connected to sverchok and vice versa.