Creating mesh (vertex buffer) at runtime

Hi!
Is it possible to define vertices via script and render them with particular material (shaders) ?
-thanks!

Not at the moment.

So what is the best way to implement something like this?

using predefined collada model with a custom shader?

I would say use a collada model for the springy waves and the builtin particle system for the droplets (could also be done with models of course). I was really inspired by this earlier this summer and wanted to try it out in Defold when I was on vacation. I ended up using a massive collada mesh (generated it in python) to get the quads and then did all of the sim in shaders. Because of GLES I had to do some work of squashing floats into the 8-bit color channels, but it was ok. It didn’t look anything like the link above, but it was cool to see 150k particles spraying at 60 fps in the browser. :slight_smile:

4 Likes

Cool.
Could you share the script to generate collada model please?

1 Like

Sure! Can’t upload the python file for some reason, but this is the code. It’s a little hard coded with paths, you might want to change that.

import sys

template = """<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
  <asset><contributor><author></author><authoring_tool>FBX COLLADA exporter</authoring_tool><comments></comments></contributor><created>2012-10-10T12:34:45Z</created><keywords></keywords><modified>2012-10-10T12:34:45Z</modified><revision></revision><subject></subject><title></title><unit meter="1.000000" name="centimeter"></unit><up_axis>Y_UP</up_axis></asset>
  <library_geometries>
    <geometry id="pPlane1-lib" name="pPlane1Mesh">
      <mesh>
        <source id="pPlane1-POSITION">
          <float_array id="pPlane1-POSITION-array" count="{vertex_elem_count}">
            {positions}
          </float_array>
          <technique_common>
            <accessor source="#pPlane1-POSITION-array" count="{vertex_count}" stride="3">
              <param name="X" type="float"/>
              <param name="Y" type="float"/>
              <param name="Z" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <source id="pPlane1-Normal0">
          <float_array id="pPlane1-Normal0-array" count="{vertex_elem_count}">
            {normals}
          </float_array>
          <technique_common>
            <accessor source="#pPlane1-Normal0-array" count="{vertex_count}" stride="3">
              <param name="X" type="float"/>
              <param name="Y" type="float"/>
              <param name="Z" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <source id="pPlane1-UV0">
          <float_array id="pPlane1-UV0-array" count="{uv_elem_count}">
            {uvs}
          </float_array>
          <technique_common>
            <accessor source="#pPlane1-UV0-array" count="{uv_count}" stride="2">
              <param name="S" type="float"/>
              <param name="T" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <vertices id="pPlane1-VERTEX">
          <input semantic="POSITION" source="#pPlane1-POSITION"/>
          <input semantic="NORMAL" source="#pPlane1-Normal0"/>
        </vertices>
        <triangles count="{tri_count}" material="lambert1">
          <input semantic="VERTEX" offset="0" source="#pPlane1-VERTEX"/>
          <input semantic="TEXCOORD" offset="1" set="0" source="#pPlane1-UV0"/>
          <p> {indices}</p></triangles>
      </mesh>
    </geometry>
  </library_geometries>
  <scene>
    <instance_visual_scene url="#"></instance_visual_scene>
  </scene>
</COLLADA>
"""

def flatten(x):
    return [v for sub in x for v in sub]

def gen_model(width, height, filename):
    quads = [[x, y] for x in range(width) for y in range(height)]
    positions = ([[x, y, 0, (x+1), y, 0, x, (y+1), 0, (x+1), (y+1), 0] for x,y in quads])
    positions = flatten(positions)
    vertex_elem_count = len(positions)
    vertex_count = vertex_elem_count / 3
    tri_count = len(quads)*2
    normals = ([[(x+0.5)/width, (y+0.5)/height, (x+(y*width))/float(width*height)] for x,y in quads for i in range(4)])
    normals = flatten(normals)
    uvs = [0.000000, 0.000000,
           1.000000, 0.000000,
           0.000000, 1.000000,
           1.000000, 1.000000]
    indices = [3, 2, 0, 3, 0, 1]
    indices = [[(i + q*4), i] for q in range(len(quads)) for i in indices]
    indices = flatten(indices)
    with open(filename, "w") as f:
        f.write(template.format(positions = " ".join(map(str, positions)),
            normals = " ".join(map(str, normals)),
            uvs = " ".join(map(str, uvs)),
            vertex_elem_count = vertex_elem_count,
            vertex_count = vertex_count,
            uv_elem_count = str(8),
            uv_count = str(4),
            indices = " ".join(map(str, indices)),
            tri_count = tri_count))

def main():
    width = int(sys.argv[1])
    height = int(sys.argv[2])
    filename = "models/grid_{}_{}.dae".format(width, height)
    gen_model(width, height, filename)

if __name__ == "__main__":
    main()

3 Likes

Awesome, thanks!

2 Likes

I enabled file uploads of any file type into the forum.

EDIT: Enabled for python files, and some other types. It did not like * it seems.

2 Likes

@Ragnar_Svensson Don’t you think it could be a useful feature - the simplest collada grid generator in editor? E.g. New -> Mesh -> … and let define size and uv dimensions. It can be used to make full-screen quads also.

Absolutely! Another idea could be to have a mode in the mesh where you don’t define a file, but rather the generational properties. So there is never a source file on disk, but there will be a compiled model for the game runtime. What do you think about that? It’s a small difference in UX, but conceptually it’s quite big and powerful.

Yes, this approach is even better!

@Ragnar_Svensson, was this ever added as a feature request? Ping @Bjorn_Ritzl as well :slight_smile:

We have tasks in the backlog that covers this, but it’s hadn’t been given top priority I’m afraid.

What about vertex texture fetch? Also known as texture fetch in the vertex shader.
As far as I understand, this option should be supported by default in GLES.