I need to code a function that basically traces the path a sphere would roll when placed on a triangulated terrain. The image below shows the problem, but I haven't got a clue how to work with vectors in order to find a solution.

Gravity Trace Illustration

Pseudocode-wise, I'm looking for:

def gravity_trace(face_ABC, point_D):
    return X

I honestly don't know how difficult it will be to fill in the ... above. I'd appreciate any and all help I can get. My math skills are terribly rusty and I have never worked with vector math before.


  • $\begingroup$ Physics Simulation provided by Blender can be investigated by you. It is not clear this is a Blender Question. It might just be mathematics such as Gradient. There is a difference between giving abstract coordinates for a math test and concrete values for a simulation. Are your values concrete or abstract? Will the result be displayed in Blender or not? $\endgroup$ May 3, 2019 at 16:44
  • $\begingroup$ The resulting function will be part of an add-on, as is made relatively obvious by the question's tags. $\endgroup$
    – D. Waschow
    May 3, 2019 at 17:04

1 Answer 1


Project plane normal in z direction onto plane.

Here is a test script. Adds a randomly (random 0 to 1 radian rotation on x, y, z) rotated unit circle ngon at cursor, and places an empty on global edge low point.

  • The normal of the plane is its local z axis.
  • Global -z axis is considered down.
  • Find The vector intersection of the line from tip of normal in -z direction to the plane. Used mathutils.geometry.intersect_line_plane(...)
  • Result is the "downhill" vector.

    • lowest point on circle edge will be centre plus the normalized (unit length) downhill vector.

Test script:

import bpy
from random import random
from mathutils import Vector
from mathutils.geometry import intersect_line_plane as ipp

ob = bpy.context.object
ob.rotation_euler = Vector(random() for axis in 'xyz')
z = Vector((0, 0, 1))
mw = ob.matrix_world

n = (mw.to_3x3() @ z).normalized()
p = mw.translation
v = ipp(p + n, p + n - z, p, n)
bpy.ops.object.empty_add(location=p + (v - p).normalized())
  • $\begingroup$ That should get me most of the way there! I'm going to have to pluck apart what's going on in your solution, but I think I should be able to take what you've given me as a starting point to finding the location on the triangle edge. Thank you! $\endgroup$
    – D. Waschow
    May 3, 2019 at 19:47

You must log in to answer this question.

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