-
-
Save thomthom/312b87cd4c6bb636347124ea3b02c28f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#------------------------------------------------------------------------------- | |
# | |
# Thomas Thomassen | |
# thomas[at]thomthom[dot]net | |
# | |
#------------------------------------------------------------------------------- | |
module ShadingExperiment | |
Light = Struct.new(:color, :direction, :intensity) | |
class SubDivisionPreview | |
def initialize(subdivisions, transformation) | |
@subdivisions = subdivisions | |
@transformation = transformation | |
@edges = [] | |
@outlines = [] | |
@quads = {} | |
@tris = {} | |
sun_direction = Sketchup.active_model.shadow_info['SunDirection'] | |
sun_color = Sketchup::Color.new(255, 255, 255) | |
colors = [ | |
Sketchup::Color.new(255, 0, 0), | |
Sketchup::Color.new( 0, 255, 0), | |
Sketchup::Color.new( 0, 0, 255) | |
] | |
axes_light_intensity = 0.3 | |
@lights = [ | |
Light.new(colors.x, X_AXIS, axes_light_intensity), | |
Light.new(colors.y, Y_AXIS, axes_light_intensity), | |
Light.new(colors.z, Z_AXIS, axes_light_intensity), | |
Light.new(colors.x, X_AXIS.reverse, axes_light_intensity), | |
Light.new(colors.y, Y_AXIS.reverse, axes_light_intensity), | |
Light.new(colors.z, Z_AXIS.reverse, axes_light_intensity), | |
Light.new(sun_color, sun_direction, 0.8) | |
] | |
@lights = [ | |
Light.new(sun_color, sun_direction, 1.0) | |
] | |
end | |
# http://www.gamedev.net/topic/494068-flat-shading-with-multiple-light-sources/ | |
def face_shading( face, ambient = 0.0 ) | |
face_vector = face.normal | |
r = g = b = ambient | |
for light in @lights | |
weight = light.direction % face_vector | |
weight = [weight, 0.0].max * light.intensity | |
light_color = light.color | |
r += ( weight * (light_color.red / 255.0) ) | |
g += ( weight * (light_color.green / 255.0) ) | |
b += ( weight * (light_color.blue / 255.0) ) | |
end | |
model = Sketchup.active_model | |
default_material = model.rendering_options['FaceFrontColor'] | |
color = ( face.material ) ? face.material.color : default_material | |
#p [r,g,b] | |
r = [(color.red * r).to_i, 255].min | |
g = [(color.green * g).to_i, 255].min | |
b = [(color.blue * b).to_i, 255].min | |
Sketchup::Color.new( r, g, b ) | |
end | |
def get_ambient | |
shadow_dark = Sketchup.active_model.shadow_info['Dark'] / 100.0 | |
ambient = ( 0.2 + ( 0.8 * shadow_dark ) ).to_f | |
ambient | |
end | |
def update( subdivisions = nil ) | |
@subdivisions = subdivisions if subdivisions | |
model = Sketchup.active_model | |
tr = @transformation | |
# Reset. | |
@edges.clear | |
@outlines.clear | |
@quads.clear | |
@tris.clear | |
# Edges | |
direction = model.active_view.camera.direction | |
for edge in @subdivisions.edges | |
edge_points = edge.vertices.map { |v| v.position.transform(tr) } | |
@edges.concat( edge_points ) | |
if edge.faces.size < 2 | |
@outlines.concat( edge_points ) | |
else | |
dots = edge.faces.map { |face| direction % face.normal < 0 } | |
if !dots.all? | |
@outlines.concat( edge_points ) | |
end | |
end | |
end | |
# Faces | |
ambient = get_ambient() | |
for face in @subdivisions.faces | |
points = face.vertices.map { |v| v.position.transform(tr) } | |
color = face_shading( face, ambient ) | |
if face.vertices.size == 4 | |
@quads[ color ] ||= [] | |
@quads[ color ].concat( points ) | |
else | |
@tris[ color ] ||= [] | |
@tris[ color ].concat( points ) | |
end | |
end | |
end | |
def update_outlines | |
model = Sketchup.active_model | |
tr = @transformation | |
@outlines.clear | |
# Edges | |
direction = model.active_view.camera.direction | |
for edge in @subdivisions.edges | |
edge_points = edge.vertices.map { |v| v.position.transform(tr) } | |
if edge.faces.size < 2 | |
@outlines.concat( edge_points ) | |
next | |
end | |
dots = edge.faces.map { |face| direction % face.normal < 0 } | |
if !dots.all? | |
@outlines.concat( edge_points ) | |
end | |
end | |
end | |
def draw(view) | |
# Quads | |
for color, points in @quads | |
view.drawing_color = color | |
view.draw( GL_QUADS, points ) | |
end | |
# Triangles | |
for color, points in @tris | |
view.drawing_color = color | |
view.draw( GL_TRIANGLES, points ) | |
end | |
# Edges | |
rendering_options = view.model.rendering_options | |
if rendering_options['EdgeDisplayMode'] > 0 | |
# Ensure edges are properly visible by offsetting them slightly towards | |
# the camera. | |
offset_vector = view.camera.direction.reverse | |
minimum_offset = 0.001 | |
offset_edges = @edges.map { |point| | |
pixel_offset = view.pixels_to_model( 1, point ) | |
offset_vector.length = [pixel_offset, minimum_offset].max | |
point.offset(offset_vector) | |
} | |
view.line_stipple = '' | |
view.line_width = 1 | |
view.drawing_color = rendering_options['ForegroundColor'] | |
view.draw( GL_LINES, offset_edges ) | |
end | |
# Outlines | |
if rendering_options['DrawSilhouettes'] | |
# Ensure edges are properly visible by offsetting them slightly towards | |
# the camera. | |
offset_vector = view.camera.direction.reverse | |
minimum_offset = 0.001 | |
offset_edges = @outlines.map { |point| | |
pixel_offset = view.pixels_to_model( 1, point ) | |
offset_vector.length = [pixel_offset, minimum_offset].max | |
point.offset(offset_vector) | |
} | |
view.line_stipple = '' | |
view.line_width = rendering_options['SilhouetteWidth'] | |
view.drawing_color = rendering_options['ForegroundColor'] | |
view.draw( GL_LINES, offset_edges ) | |
end | |
end | |
end # class | |
end # module |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment