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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.