Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Python code to Unity-compatible C# and Compute Shaders for generating brushstrokes. #1

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

e2b-for-github[bot]
Copy link

@e2b-for-github e2b-for-github bot commented Aug 9, 2023

New Brushstrokes

Convert the following Python code into Unity compatible C# and Unity compatible Compute Shaders:
import trimesh

import pymeshlab as ml

import numpy as np

import latk

from scipy.spatial.distance import cdist

from sklearn.cluster import DBSCAN

from scipy.interpolate import splprep, splev

import sys

def distance(point1, point2):

point1 = np.array(point1)

point2 = np.array(point2)

return np.linalg.norm(point1 - point2)

def map(value, inMin, inMax, outMin, outMax):

return outMin + (((value - inMin) / (inMax - inMin)) \* (outMax - outMin))

def normalizeMesh(vertices):

magnitudes = np.linalg.norm(vertices, axis=1)

return vertices / magnitudes\[:, np.newaxis\]

def loadMesh(inputUrl):

mesh = trimesh.load(inputUrl)

try:

    print("Found mesh with " + str(len(mesh.faces)) + " faces.")

except:

    print("Meshing pointcloud with 0 faces.")

    ms = ml.MeshSet()

    ms.load_new_mesh(inputUrl)

    ms.generate_surface_reconstruction_ball_pivoting()

    #ms.transfer_attributes_per_vertex(sourcemesh=0, targetmesh=1)

    ms.save_current_mesh("temp.ply", save_vertex_color=True)

    mesh = trimesh.load("temp.ply")

return mesh

def getBounds(mesh):

bounds = distance(mesh.bounds\[0\], mesh.bounds\[1\])

print("Bounds: " + str(bounds))

return bounds

def dbscanLines(points, eps=0.1, min_samples=5):

returns = \[\]

dbscan = DBSCAN(eps=eps, min_samples=min_samples)

dbscan.fit(points)

labels = dbscan.labels\_

for label in labels:

    if label == -1: # skip points that belong to no cluster

        continue

    cluster_points = points\[labels == label\]

    tck, u = splprep(cluster_points.T, s=0)

    new_points = splev(np.linspace(0, 1, 100), tck)

    returns.append(new_points)

return returns

def voxelize(mesh, dim=128):

dims = (dim, dim, dim)

grid = np.zeros(dims)



for point in mesh.vertices:

    x, y, z = point

    ix, iy, iz = int(x / dim), int(y / dim), int(z / dim)

    grid\[ix, iy, iz\] = 1

return grid

argv = sys.argv[sys.argv.index("--") + 1:] # get all args after "--"

inputPath = argv[0]

la = latk.Latk(init=True)

ms = ml.MeshSet()

ms.load_new_mesh(inputPath)

mesh = ms.current_mesh()

bounds = mesh.bounding_box().diagonal()

samplePercentage = 1.0

searchRadius = bounds * 0.05

minPointsCount = 5

newSampleNum = int(mesh.vertex_number() * samplePercentage)

if (newSampleNum < 1):

newSampleNum = 1

try:

ms.transfer_texture_to_color_per_vertex(sourcemesh=0, targetmesh=0)     

print("Found texture, converting to vertex color.")

except:

print("No texture found.")

# The resample method can subtract points from an unstructured point cloud,

# but needs connection information to add them.

if (samplePercentage > 1.0):

if (mesh.edge_number() == 0 and mesh.face_number() == 0):

    ms.generate_surface_reconstruction_ball_pivoting()

ms.generate_sampling_poisson_disk(samplenum=newSampleNum, subsample=False)

ms.transfer_attributes_per_vertex(sourcemesh=0, targetmesh=1)

else:

ms.generate_sampling_poisson_disk(samplenum=newSampleNum, subsample=True)

mesh = ms.current_mesh()

print("Search radius: " + str(searchRadius) + ", Min points per stroke: " + str(minPointsCount))

def group_points_into_strokes(points, radius):

strokes = \[\]

unassigned_points = set(range(len(points)))

while len(unassigned_points) &gt; 0:

    stroke = \[next(iter(unassigned_points))\]

    unassigned_points.remove(stroke\[0\])

    for i in range(len(points)):

        if i in unassigned_points and cdist(\[points\[i\]\], \[points\[stroke\[-1\]\]\])\[0\]\[0\] &lt; radius:

            stroke.append(i)

            unassigned_points.remove(i)

    if (len(stroke) &gt;= minPointsCount):

    	strokes.append(stroke)

    print("Found " + str(len(strokes)) + " strokes, " + str(len(unassigned_points)) + " points remaining.")

return strokes

strokes = group_points_into_strokes(mesh.vertex_matrix(), searchRadius)

for stroke in strokes:

la_stroke = latk.LatkStroke()

for index in stroke:

	vert = mesh.vertex_matrix()\[index\]

	la_point = latk.LatkPoint(co=(vert\[0\], vert\[2\], vert\[1\]))

	la_stroke.points.append(la_point)

la.layers\[0\].frames\[0\].strokes.append(la_stroke)

if (len(la.layers[0].frames[0].strokes) > 0):

la.normalize()

la.write("output.latk")

else:

print("No strokes generated.")

Tech stack

  • Unity
  • C#
  • Compute Shaders
  • Unity Shaders
  • All scripts, code and Compute Shaders must be Unity compatible.

Trigger the agent again by adding instructions in a new PR comment or by editing existing instructions.

Powered by e2b

@e2b-for-github
Copy link
Author

e2b-for-github bot commented Aug 9, 2023

Started smol developer agent run.

@e2b-for-github
Copy link
Author

e2b-for-github bot commented Aug 9, 2023

Finished smol developer agent run.

Trigger the agent again by adding instructions in a new PR comment or by editing existing instructions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants