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$
3
  • $\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
    Commented Sep 27, 2016 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$ Commented Sep 28, 2016 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
    Commented Sep 28, 2016 at 1:50

1 Answer 1

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$
1
  • $\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$ Commented Sep 27, 2016 at 21:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .