2
$\begingroup$

I've run into a few issues regarding a blender script I am working on to accompany another program I wrote that transforms analog sound into a data set representing the amplitudes of the frequencies in that sound sample over time. I now want to use blender to transform my data into a 3D model that would, effectively, be a 3D representation of music. It's my first time working with Blender/Python scripting, so your patience is appreciated!

Context From a conceptual standpoint, here is what the script should do:

  1. Create 513 (number of frequencies sampled) collinear vertices
  2. Connect the vertices with a line(face?)
  3. Set the z value of each vertex to the corresponding amplitude for that specific frequency at t=1 represented by the vertex (we now have a 2D jagged plane)
  4. Extrude the plane by delta time
  5. Adjust the new set of vertices for amps at t=2

...repeat this process of adjusting and extruding until all t values are exhausted

The issue I repeatedly encounter as I work on this code is referencing / selecting individual vertices. In the 3D editor, I can simply right click, or control right click, to select point(s), and that is basically the functionality I need to replicate at many steps in this process.

For example, to create the first row of vertices, I wrote the following code:

counter = 0
bpy.context.scene.cursor_location = (0.0, 0.0, 0.0)
for x in range (0,513):
    bpy.ops.mesh.primitive_vert_add()
    counter = counter - 0.1
    bpy.context.scene.cursor_location = (counter, 0.0, 0.0)

Then, to connect these collinear vertices, I have:

bpy.ops.mesh.select_all(action='TOGGLE')
bpy.ops.mesh.select_all(action='TOGGLE')
bpy.ops.mesh.edge_face_add() 

Now, though, I need to go back and start adjusting z value for each vertex I created in this line, and I do not know how to reference them. Ideally, I want to store them in an array at the time of creating them, but again, I am at a loss for associating these vertices with object references that can be operated upon.

I will also encounter an issue following the extrusion, where a new set of 513 vertices is formed. For those, I will only know their xyz location and will have had no opportunity to build references to them unless Blender already does that by storing references to all vertices in a mesh (I've read about it, but still cannot access that data set if it exists). When it is time to set z values for these points, I will not know how to reference them.

Question How do I reference individual vertices knowing only their xyz location in space and operate on them either individually (for z movements) or as a set (at extrusion time)?

Thank you for your help! I can't wait to finally see (or print!) my audio data set in three dimensional space.

$\endgroup$
  • $\begingroup$ Hi, are you after something akin to pasteall.org/pic/show.php?id=107175 which is a sound file cut to the 88 piano note frequencies using bake to fcurve. Image is a curve for of each fcurve, which can be filled to show what I'd call a "sound surface". $\endgroup$ – batFINGER Sep 27 '16 at 13:12
  • $\begingroup$ This is similar, and in many ways superior, to what my program does. Right now, I am generating a very accurate representation of the sound, but that means I have sharp peaks and a very jagged mesh. I may change some things around to smooth it out in a similar fashion to what was done in your link, so thank you for sharing! $\endgroup$ – KentAshfield Sep 28 '16 at 0:53
  • $\begingroup$ Been grinding on different methods to do this for a while blenderartists.org/forum/… using data to make a bump map. github.com/batFINGER/batFINGER-blender-addons/tree/… feel free to drop any ideas suggestions there using the "issues" tab. $\endgroup$ – batFINGER Sep 28 '16 at 1:50
2
$\begingroup$

An example

import bpy
import bmesh
from random import uniform

mesh  = bpy.data.meshes.new("Mesh")
obj   = bpy.data.objects.new("Mesh", mesh)
scene = bpy.context.scene
scene.objects.link(obj)

bm = bmesh.new()

verts_b = [bm.verts.new((i, 0.0,               0.0)) for i in range(20)]
verts_t = [bm.verts.new((i, 0.0, uniform(1.0, 3.0))) for i in range(20)]

# create edges
# for i in range(19):
#    bm.edges.new((verts_t[i], verts_t[i+1]))

faces = [
    bm.faces.new((
        verts_b[i]  , verts_b[i+1],
        verts_t[i+1], verts_t[i]
    ))
    for i in range(19)
]

result = bmesh.ops.extrude_discrete_faces(
    bm, faces=faces, use_select_history=False)

for f in result['faces']:
    amount = uniform(1.0, 2.0)
    for v in f.verts:
        v.co.y += -amount

bm.to_mesh(mesh)
bm.free()
$\endgroup$
  • $\begingroup$ Thank you for this. It got me on the right track for the kind of thinking required. I have finished the code and have a working system, which I will clean up and post here shortly. $\endgroup$ – KentAshfield Sep 27 '16 at 21:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.