Skip to content

Instantly share code, notes, and snippets.

@thomthom
Created November 7, 2017 10:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomthom/312b87cd4c6bb636347124ea3b02c28f to your computer and use it in GitHub Desktop.
Save thomthom/312b87cd4c6bb636347124ea3b02c28f to your computer and use it in GitHub Desktop.
#-------------------------------------------------------------------------------
#
# 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