# Vector Math to Determine Gravity Path

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.

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.

Thanks!

• 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? – atomicbezierslinger May 3 '19 at 16:44
• The resulting function will be part of an add-on, as is made relatively obvious by the question's tags. – D. Waschow May 3 '19 at 17:04

## 1 Answer

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

bpy.ops.mesh.primitive_circle_add(fill_type='NGON')
ob = bpy.context.object
ob.rotation_euler = Vector(random() for axis in 'xyz')
z = Vector((0, 0, 1))
bpy.context.scene.update()
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())

• 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! – D. Waschow May 3 '19 at 19:47