Skip to content

Commit

Permalink
Added support for face normals and bumped version to 0.1.6
Browse files Browse the repository at this point in the history
  • Loading branch information
ForestKatsch committed Feb 17, 2020
1 parent 7cd8618 commit fbc0276
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 38 deletions.
6 changes: 3 additions & 3 deletions ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

## P1
* [x] Take new screenshots of settings dialog (MUST BE COMPLETE BEFORE RELEASE)
* [*] Create a slide for performance, and how vertex colors can be faster and look better than baked AO
* [*] Add emphasis about how vertex color AO is much faster when dealing with lots of objects than AO
* [X] Download some models and bake AO on them for the gallery (At least one or two should be done by release.)
* [x] Create a slide for performance, and how vertex colors can be faster and look better than baked AO
* [x] Add emphasis about how vertex color AO is much faster when dealing with lots of objects than AO
* [x] Download some models and bake AO on them for the gallery (At least one or two should be done by release.)

## After release
* [ ] Backport documentation from Blender Market to GitHub (can be done after release)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ For a quick preview of vertex colors, you can also enter **Vertex Paint** mode (

# Changelog

## v0.1.6

* Added support for face normals; hard-surface ambient occlusion will be much improved. (Thanks to Joseph for reporting this issue!)

## v0.1.5

* Added "Ignore Small Objects" feature to speed up bakes that would otherwise have many small objects contributing
Expand Down
97 changes: 62 additions & 35 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"name": "Vertex Oven",
"description": "Bake ambient occlusion straight to vertex colors",
"author": "Forest Katsch",
"version": (0, 1, 5),
"version": (0, 1, 6),
"blender": (2, 80, 0),
"location": "3D View > Object > Vertex Oven",
"warning": "Warning: this addon is still young, and problems may occur. If you're concerned about this addon, make sure you've backed up your Blender file first.",
Expand Down Expand Up @@ -92,6 +92,14 @@ def get_valid_keys(self):
"ignore_small_objects",
"small_object_size",
]

class BakeVertexPoint:

def __init__(self, position, normal, vertex_index, loop_index):
self.position = position
self.normal = normal
self.vertex_index = vertex_index
self.loop_index = loop_index

# This never worked right.
#class ProgressWidget(object):
Expand Down Expand Up @@ -181,15 +189,15 @@ def __init__(self, options, context):
# The objects that contribute to ambient occlusion on the receiving objects
self.bake_cast_objects = []

# The vertex we're on. This goes up until it reaches `len(mesh.vertices)`.
self.last_vertex_index = 0
# The point we're on. This goes up until it reaches `len(self.points_to_bake)`.
self.last_point_index = 0

# self.ao_data is a dictionary of {vertex_index: ambient occlusion}
self.ao_data = {}
self.ao_data = []

# Returns a value within the range 0..100
def get_progress_percentage(self):
return (self.last_vertex_index / len(self.active_mesh.vertices)) * 100
return (self.last_point_index / len(self.points_to_bake)) * 100

@classmethod
def random_vector(cls):
Expand Down Expand Up @@ -277,18 +285,22 @@ def jitter_vertex(self, vertex, sample):
offset = (directions[0] * (np.random.uniform() * fraction)) + (directions[1] * (np.random.uniform() * fraction))

return vertex.co + offset

# Returns a hashable string type that uniquely identifies `vertex_index` and `loop_index`.
def get_vertex_loop_id(self, vertex_index, loop_index):
return str(vertex_index) + ":" + str(loop_index)

def calculate_vertex_ao(self, vertex):
def calculate_vertex_ao(self, position, normal):
"""
Returns a value, 0-1, of how occluded this `vertex` is. Samples are taken for each object; the count is
determined by `self.options.sample_count`.
"""
obj = self.active_object

normal = obj.matrix_world.to_3x3() @ vertex.normal
position = (obj.matrix_world @ vertex.co)
normal = obj.matrix_world.to_3x3() @ normal
position = (obj.matrix_world @ position)

offset = (normal * 0.0001)
offset = (normal * 0.00001)

occlusion = 0

Expand All @@ -315,7 +327,7 @@ def calculate_vertex_ao(self, vertex):
sample_position_object = sample_position - offset

sample_distance = self.distance_to_object(sample_position_object, direction, obj_cache[1], obj_cache[2], obj_cache[3])

if sample_distance >= 0:
distance = min(sample_distance, distance)

Expand Down Expand Up @@ -407,12 +419,14 @@ def get_vertex_group(self):
"""Returns Blender's `VertexGroup` object."""
obj = self.active_object
name = self.options.group_name

print(obj.vertex_groups)

if not obj.vertex_groups or name not in obj.vertex_groups:
group = obj.vertex_groups.new()
group.name = name

obj.vertex_groups.active = group
#obj.vertex_groups.active = group

group = obj.vertex_groups[name]

Expand All @@ -424,28 +438,25 @@ def apply_vertex_colors(self):
mesh = self.active_mesh
layer = self.get_vertex_color_layer()

for polygon in mesh.polygons:
for i, index in enumerate(polygon.vertices):
vertex = mesh.vertices[index]
brightness = self.ao_data[vertex.index]
for index, point in enumerate(self.points_to_bake):
brightness = self.ao_data[index]

if self.options.color_invert:
brightness = 1 - brightness
if self.options.color_invert:
brightness = 1 - brightness

loop_index = polygon.loop_indices[i]
layer.data[loop_index].color = (brightness, brightness, brightness, 1.0)
layer.data[point.loop_index].color = (brightness, brightness, brightness, 1.0)

def apply_vertex_groups(self):
"""Apply `self.ao_data` to the vertex group."""
group = self.get_vertex_group()

for vertex_index in self.ao_data:
weight = self.ao_data[vertex_index]
for index, point in enumerate(self.points_to_bake):
weight = self.ao_data[index]

if self.options.weight_invert:
weight = 1 - weight

group.add([vertex_index], weight, "REPLACE")
group.add([point.vertex_index], weight, "REPLACE")

def start(self):
print("Baking vertex AO...")
Expand Down Expand Up @@ -512,6 +523,23 @@ def start_object(self, obj):

# Make sure to set our seed here, too.
np.random.seed(self.options.seed)

self.points_to_bake = []

mesh = self.active_mesh
mesh.calc_tangents()
mesh.calc_normals_split()

print("Finding all points to be baked...")
for poly in mesh.polygons:

for poly_vertex_index in range(len(poly.vertices)):
vertex_index = poly.vertices[poly_vertex_index]
loop_index = poly.loop_indices[poly_vertex_index]

self.points_to_bake.append(BakeVertexPoint(mesh.vertices[vertex_index].co, mesh.loops[loop_index].normal, vertex_index, loop_index))

self.last_point_index = 0

return False

Expand All @@ -535,23 +563,22 @@ def bake(self, vertices=-1):
mesh = self.active_mesh

i = 0

for vertex in mesh.vertices[self.last_vertex_index:]:

ao_vertex = self.calculate_vertex_ao(vertex)

self.ao_data[vertex.index] = ao_vertex
while self.last_point_index < len(self.points_to_bake):

self.last_vertex_index += 1
point = self.points_to_bake[self.last_point_index]

i += 1
self.ao_data.append(self.calculate_vertex_ao(point.position, point.normal))

if vertices > 0 and i > vertices:
self.last_point_index += 1
i += 1

if i > vertices:
return False

self.finish_object()

self.last_vertex_index = 0
self.last_point_index = 0

return self.start_next_object()

Expand All @@ -569,7 +596,7 @@ def finish_object(self):

self.apply_vertex_groups()

self.ao_data = {}
self.ao_data = []

print("Bake completed on '{}'".format(self.active_object.name))

Expand Down

0 comments on commit fbc0276

Please sign in to comment.