Art with Math and Python (AMP)

Hey, I made this tiny script to display (parametric) math functions in Blender with Python. Perhaps people can use this to make other AMP’s or got idea’s for different AMP’s. :RocknRoll:

Here are some examples from me:




The code:

# Dune2k / Lars - 2012
# Parametric Functions into blocks on the z-axis

import bpy
from math import *

rows = 25 #amount of boxes, don't go too high
steps = 2/rows

x=0
y=0

for y in range(1,rows):
    
    for x in range(1,rows):
        
        ### setting up box stuff
        bpy.ops.mesh.primitive_cube_add(location= (x*steps,y*steps,0) )
        bpy.context.scene.cursor_location = bpy.context.active_object.location
        bpy.context.scene.cursor_location.z -= 1
        bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
        
        ### determining boxes
        bpy.context.active_object.scale.x = steps/2 # change for space between cubes
        bpy.context.active_object.scale.y = steps/2
        
        ## the formula:
        bpy.context.active_object.scale.z = (-(x*steps)**3-(y*steps)**3+20)*.1

Great idea for a thread, interested to see what others come up with. I’ll see if I can figure something out.

beautiful_.>>>… _

Great work! Although I think you just sank my productivity here at work…

Thanks for the nice compliments. :slight_smile: I personally really lover number 3 from my first post. It has so many elements in it.

Here is a new one, the noise is still a little too strong. Next time I will render it longer in Cycles.


The last one changed for the better - a bit more organic. :smiley:


@Dune2k,
These are great! As soon as I get a free minute I’m going to try to make a few my own, but slammed with work. For anyone looking at ideas for this, here’s a great resource: http://functions.wolfram.com/

I played around a bit with this but I got stuck on the materials. Are you applying materials to your objects or is everything being done though lighting? If you are using mats, how are you getting them all assigned to the cubes so you don’t have to do it 255 times? I looked briefly at scripting it but I’ve never messed around with adding mats though Python.

I know you can use some simple tricks with cycles nodes to give a similar effect for materials like this one using the “Layer Weight” node.


This probably needs to be updated for recent versions, but you can also use python to add the materials to each face. http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Cookbook/Materials/Multiple_Materials

Ahh, waiting for the wife to get home on Friday night so we can go out. Decided to see if I could do the material change. Threw this together really quick which assigns a random material to each polygon/face.

One weird thing, when switching in and out of edit mode and using a for loop to iterate through, the index would get all messed up if I switch mode_set from edit to object. Strange, but this code works.

import bpy, random

obj = bpy.context.object
polys = obj.data.polygons

def newMat():
    mat = bpy.data.materials.new("Mat1")
    mat.diffuse_color = (random.random(), random.random(), random.random())
    return mat

# Need this "X" for iterating through index
# i.index below not working correctly when switching object mode??
x=0
for i in polys:
    bpy.ops.object.material_slot_add()
    obj.material_slots[x].material = newMat()
    polys[x].select = True
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.object.material_slot_assign() 
    bpy.ops.mesh.select_all(action='DESELECT') 
    bpy.ops.object.mode_set(mode='OBJECT')
    x += 1

I used the lights for color effect and then edited it in Gimp for better contrast and stuff. Last render I used the “b” for box tool, selected all the objects and joined them with “ctrl+j”. Then I only had to add one material.

@crazycourier,
Thanks for the code, but it would nicer if I could change the material while in the “creating loop”. So that we can add different materials to different objects based also on a math formula. This way you get a z-axis based on a formula and the color. Double effect! The problem is, how do you change the material on a “bpy.context.active_object” ?

//edit: I found it. Just add this after the formula in the first python code. Where “pasta” is of course a previously made material.

            bpy.ops.object.material_slot_add()
            bpy.context.active_object.material_slots[0].material = bpy.data.materials["pasta"]

New code to add different materials called ‘pasta’ and ‘trico’ with checkerboard set-up. Code could perhaps be more pretty.

Example of effect:

rows = 12
steps = pi/rows

for y in range(0,rows):
    
    for x in range(0,rows):
        
        ### setting up box stuff
        bpy.ops.mesh.primitive_cube_add(location= (x*steps,y*steps,0) )
        bpy.context.scene.cursor_location = bpy.context.active_object.location
        bpy.context.scene.cursor_location.z -= 1
        bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
        
        ### determining boxes
        bpy.context.active_object.scale.x = steps/3 # change for space between cubes
        bpy.context.active_object.scale.y = steps/3
        
        ## the formula:
        bpy.context.active_object.scale.z = (exp((x*steps))+exp((y*steps)))*.1

        bpy.ops.object.material_slot_add()
        a = x
                  
        if (-1)**y <= 0:
            a += 1
        
        if (-1)**a <= 0:
            bpy.context.active_object.material_slots[0].material = bpy.data.materials["pasta"]
        else:
            bpy.context.active_object.material_slots[0].material = bpy.data.materials["trico"]
  
    

There is a command called “Copy Material to Others”. This copies the materials from the active object to all the selected objects.

I didn’t go so far as to assign materials or even give it a nice render for you guys. But I had some fun with this idea the other day and would like to share it here. It uses a quadratic equation to determine z scale, as it places boxes in all 8 portions of the grid.


# Drek: March the thirtieth twenty twelve
import bpy, math
layers = 128
for c in range (0,4):
  if c == 0:
    x = 1
    y = 1
  if c == 1:
    x = 1
    y = -1
  if c == 2:
    x = -1
    y = 1
  if c == 3:
    x = -1
    y = -1
  for m in range (0,2):
    if m == 0: 
      z = 1
    else:
      z = -1        
    for i in range(1,layers):
      bpy.ops.mesh.primitive_cube_add()
      bpy.context.active_object.location.x = (x*i)/2
      bpy.context.active_object.location.y = (y*i)/2
      bpy.context.active_object.location.z = (z*i)/2
      bpy.context.active_object.scale.x=1
      bpy.context.active_object.scale.y=1
      bpy.context.active_object.scale.z=((i)+(2*(i)**2)+(3*(i)**3))/100000

Very nice one, Drek! I made a render of it, I hope you like it, looks kinda spooky/alien. :slight_smile:


Awesome Dune2K, Thank you!! It does look more alive than mathematical, creepy!
This was a whole lot of fun for me, a great exercise for any level of coder.

http://www.infoocean.info/avatar3.jpgGreat idea for a thread, interested to see what others come up with.

Playing with even and uneven using different formula’s. Got some other good idea’s too, but will require more coding and experimenting. :rolleyes:



Playing with hexagons. :yes:



The code for the hexagon sea effect (other effect also possible, change z-formula). Make sure the object is called “six” or adjust the code. To make a hexagon, just use “add circle” and use 6 sides/vertices (+ fill).


# Select the "six" object and duplicate it like a formula!
# Dune2k / Lars 2012

import bpy
from math import *
tau = 2*pi
    
the_object = 'six' 
    
if bpy.data.objects[the_object].select:
    
    six_len = (3**.5)        # x-size of hexagon
    total = 20               # amount of steps (>40 will make PC crawl for a while)
    max_value = 2*tau        # max value for formula (>tau is sea effect)
    steps = max_value/total
    scaler = 1              # scale formula (not used)
    
    for q in range(0,total):
        
        bpy.ops.object.select_all()
        bpy.data.objects[the_object].select = True
                
        for i in range(0,total):
            
            bpy.ops.object.select_all()
            bpy.data.objects[the_object].select = True
            
            
            if (-1)**q < 0:
                x = six_len/2+six_len*i
                
            else:
                x = six_len*i 
                
            
            y = q*1.5
            z = sin(steps*i)+sin(steps*q)
            
            bpy.ops.object.duplicate_move(TRANSFORM_OT_translate={"value":(x,y,z)})
            

                

This is what I’m talking about: http://nightmares06.deviantart.com/gallery/419694

Gorgeous stuff!