3ds max – Use the Particle-Flow Lock/Bond test to have particles move on a surface in

Software:
3ds max 2019

The Lock/Bond Particle Flow test can be used to have particle movement restricted to a surface.

lock_bond.gif

This example shows a simple setup in which the particle teapots have a Speed operator set to Random 3D mode that causes them to move in random directions,
While at the same time the Lock/Bond test forces them to ‘stick’ to the surface:

Untitled-1

 

Advertisements

UE4 – Python – Importing assets

Software:
Unreal Engine 4.20

Untitled-1

Importing assets into a project is done using the import_asset_tasks() function which is a member of the unreal.AssetTools class.
A reference to the AssetTools class is created by calling the get_asset_tools() function which is a member of the unreal.AssetToolHelpers class.
The import_asset_tasks() function requires a list of unreal.AssetImportTask objects as an argument, each unreal.AssetImportTask object in the supplied list represents the import action of a single asset, and contains properties needed for the import operation.
Asset import properties are set using the set_editor_property() function which is called through the AssetImportTask object.
Available asset import properties are listed here:
https://api.unrealengine.com/INT/PythonAPI/class/AssetImportTask.html

In the following example a specified texture file is imported into the project and stored in the Content(Game) > Textures folder.
* If the folder doesn’t exist it will be created.

import unreal
AssetTools = unreal.AssetToolsHelpers.get_asset_tools()
AssetImportTask = unreal.AssetImportTask()
AssetImportTask.set_editor_property('filename', "D:\Wood_Red_A.jpg")
AssetImportTask.set_editor_property('destination_path', '/Game/Textures')
AssetTools.import_asset_tasks([AssetImportTask])

The following example imports all the JPG files from folder: D:\ into the project, stores the new assets in Content(Game)\Textures folder and saves them:

from os import listdir
from os.path import isfile, join
import unreal
dir = "D:\\"
files = [f for f in listdir(dir) if isfile(join(dir, f)) and f[-3:]=='jpg']
AssetTools = unreal.AssetToolsHelpers.get_asset_tools()

import_tasks = []
for f in files:
     print join(dir, f)
     AssetImportTask = unreal.AssetImportTask()
     AssetImportTask.set_editor_property('filename', join(dir, f))
     AssetImportTask.set_editor_property('destination_path', '/Game/Textures')
     AssetImportTask.set_editor_property('save', True)
     import_tasks.append(AssetImportTask)

AssetTools.import_asset_tasks(import_tasks)

* note that when copying and pasting a script from this example, the indentation may not be pasted correctly.

Get started with Python in UE4

Python – Listing the files in a directory

Language:
Python 2.7

The following example uses functions from the os library to list the files in a given directory:

from os import listdir
from os.path import isfile, join
dir = "D:\\"
files = [f for f in listdir(dir) if isfile(join(dir, f))]
for f in files:
	print join(dir, f)

In the next example the script has been modified to list only files with the name extension ‘jpg’:

from os import listdir
from os.path import isfile, join
dir = "D:\\"
files = [f for f in listdir(dir) if isfile(join(dir, f)) and f[-3:]=='jpg']
for f in files:
	print join(dir, f)

 

* note that when copying and pasting a script from this example, the indentation may not be pasted correctly.

UE4 – Python Scripting – how to start

Software:
Unreal Engine 4.20

  1. Go to:
    Edit > Plugins > Scripting
    And enable the Python Editor Script Plugin.
    * also recommended to enable Editor Scripting Utilities,
    And Sequencer Scripting plugins
    Untitled-2
  2. Restart the UE4 Editor.
  3. Open:
    Window > Developer Tools > Output Log
    Untitled-1
  4. Switch the command-line mode from Cmd to Python, write Python commands and press Enter to execute them:
    Untitled-3
  5. Or in Cmd mode, write ‘py‘ with a path to a Python script file, and hit Enter to execute the script:
    Untitled-4.jpg

 

Links:

  1. Scripting the Editor using Python:
    https://docs.unrealengine.com/en-us/Editor/ScriptingAndAutomation/Python
  2. UE4 Python API reference:
    https://api.unrealengine.com/INT/PythonAPI/

Python for 3ds max – list scene objects

Software:
3ds max 2019

Iterating through a list of all of an object’s hierarchy or all of the objects in the scene is a very common requirement for scripted tools and utilities in 3D animation software.
Coming from a MaxScript background, I was used to just have to write the word ‘objects‘ to reference a list of all of the objects in the scene.

Unless I’m missing something obvious,
There isn’t a shortcut like this available in the 3ds max Python API.

In order to list all the objects in the scene you need to use a recursive function that will return a list of all of a node’s children, and children’s children, etc.

In the following example, the function ‘list_children()’ will return a list all of the objects in the supplied node’s hierarchy, and when given the scene’s root node via MaxPlus.Core.GetRootNode() it will return a list of all the objects in the scene.
Wrapping ‘list_children()’ within the ‘scene_objects()’ function, provides a convenient way get a list of all the objects in the scene just by calling ‘scene_objects()’.

def scene_objects():
    def list_children(node):
       list = []
       for c in node.Children:
           list.append(c)
           list = list + list_children(c)
       return list
    return list_children(MaxPlus.Core.GetRootNode())


for o in scene_objects():
    print o.Name

* note that when copying and pasting a script from this example, the indentation may not be pasted correctly.

Python for 3ds max – Animated Mesh

Software:
3ds max 2019

This is an example of procedurally animating a mesh’s vertices via Python script.

Vert_Anim.gif

Notes:
1. The model has to be converted to Editable Mesh before the script is run.
* unless the scrip will be extended to do it.
2. The model must be selected for the script to work.

import MaxPlus
import math
from MaxPlus import INode
from MaxPlus import TriObject
from MaxPlus import SelectionManager
from MaxPlus import Factory
from MaxPlus import Animation
from MaxPlus import Point3
from MaxPlus import Control

ticks_frame = 160

#Selection
sel = []
for n in SelectionManager.Nodes:
    sel.append(n)
node = sel[0]

#Setup Controllers
obj = node.GetObject()
Tri = TriObject._CastFrom(obj)
mesh = Tri.GetMesh()
num_verts = mesh.GetNumVertices()
mesh_anim = obj.GetSubAnim(0)
pnt_ctrl = Factory.CreateDefaultMasterPointController()
node.AssignController(pnt_ctrl,1)
for i in range(num_verts):
    bezp3 = Factory.CreateDefaultPoint3Controller()
    bezp3.SetPoint3Value(mesh.GetVertex(i))
    mesh_anim.AssignController(bezp3,i)

#Animation
Animation.SetAnimateButtonState(True)
for t in range(100):
    time = t * ticks_frame
    Animation.SetTime(time)
    mesh_anim.AddNewKey(time,0)
    for i in range(num_verts):
        vert_anim = mesh_anim.GetSubAnim(i)
        vert_ctrl = Control._CastFrom(vert_anim)
        vert_val = mesh.GetVertex(i)
        vert_val.SetZ(vert_val.GetZ() + math.sin(((Animation.GetTime()*0.5)/(ticks_frame))+i))
        vert_ctrl.SetPoint3Value(vert_val)
Animation.SetAnimateButtonState(False)

* note that when copying and pasting a script from this example, the indentation may not be pasted correctly.

Related:
Python for 3ds max – Mesh manipulation

Python for 3ds max – Create Objects

Software:
3ds Max 2019

Untitled-1.jpg

from MaxPlus import ClassIds
from MaxPlus import Point3
import random

# Define Sphere geometry object:
sphere_obj = Factory.CreateGeomObject(ClassIds.Sphere)
sphere_obj.ParameterBlock.Radius.Value = 5
sphere_obj.ParameterBlock.Segs.Value = 64

# Create a list of 10 sphere instanced objects:
spheres = []
for i in range(10):
    spheres.append(Factory.CreateNode(sphere_obj))

# Move spheres to random positions
for s in spheres:
    s.SetLocalPosition(Point3( random.randint(-50,50),
                               random.randint(-50,50),
                               random.randint(-50,50)))
    scale = 5.0 * (random.randint(30,100)/100.0)
    s.SetLocalScale(Point3(scale,scale,scale))

* note that when copying and pasting a script from this example, the indentation may not be pasted correctly.