Skip to content

Commit

Permalink
edge sharpness (creasing) for smooth-subdiv-mesh
Browse files Browse the repository at this point in the history
  • Loading branch information
kaveh808 committed Sep 12, 2023
1 parent 504c7ca commit 299ed61
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 85 deletions.
2 changes: 1 addition & 1 deletion src/graphics/opengl/opengl.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@
(if highlight?
(progn
(gl-set-sel-color)
(gl:line-width (* 2 (line-thickness *drawing-settings*))))
(gl:line-width (* 3 (line-thickness *drawing-settings*))))
(progn
(gl-set-fg-color)
(gl:line-width (line-thickness *drawing-settings*))))
Expand Down
117 changes: 85 additions & 32 deletions src/plugins/smooth-subdiv-mesh.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@

;;; subclass of subdiv-mesh which does smooth mesh refinement
;;; smoothing based on https://onrendering.com/data/papers/catmark/HalfedgeCatmullClark.pdf
;;; edge sharpness based on https://graphics.pixar.com/library/Geri/paper.pdf

(defclass-kons-9 smooth-subdiv-mesh (subdiv-mesh)
())

(defmethod compute-subdiv-points ((mesh smooth-subdiv-mesh) (subdiv smooth-subdiv-mesh))
(set-smooth-face-vertex-points mesh subdiv)
(set-smooth-edge-vertex-points mesh subdiv)
(set-smooth-vertex-vertex-points mesh subdiv))
;; TODO - sharp creases
;; (set-subdiv-edge-vertex-crease-points mesh subdiv)
;; (set-subdiv-vertex-vertex-crease-points mesh subdiv)
;; (set-subdiv-edge-sharpness mesh subdiv)
(set-smooth-vertex-vertex-points mesh subdiv)
;; TODO - sharp creases
(set-smooth-edge-vertex-crease-points mesh subdiv)
(set-smooth-vertex-vertex-crease-points mesh subdiv)
(set-smooth-subdiv-edge-sharpness mesh subdiv)
)

(defun set-smooth-face-vertex-points (mesh subdiv)
(do-array (x h (sm-half-edges mesh))
Expand Down Expand Up @@ -45,19 +47,27 @@
(point (sm-nth-vertex subdiv i)))
4)))))))

;;; TODO - sharp creases
;; (defun set-smooth-edge-vertex-crease-points (mesh subdiv)
;; (do-array (x h (sm-half-edges mesh))
;; (when (> (sharpness (sm-nth-edge mesh (edge h))) 0)
;; (let ((v0 (vertex h))
;; (v1 (vertex (sm-nth-half-edge mesh (next-half-edge h))))
;; (j (+ (length (sm-vertices mesh)) (length (sm-faces mesh)) (edge h))))
;; (setf (point (sm-nth-vertex subdiv j))
;; (p:lerp (point (sm-nth-vertex subdiv j))
;; (p/ (p+ (point (sm-nth-vertex mesh v0))
;; (point (sm-nth-vertex mesh v1)))
;; 2)
;; (sharpness (sm-nth-edge mesh (edge h)))))))))
;;; sharp creases

(defun smooth-edge-vertex-crease-point (mesh half-edge)
(let ((v0 (vertex half-edge))
(v1 (vertex (sm-nth-half-edge mesh (next-half-edge half-edge)))))
(p/ (p+ (point (sm-nth-vertex mesh v0))
(point (sm-nth-vertex mesh v1)))
2)))

(defun set-smooth-edge-vertex-crease-points (mesh subdiv)
(do-array (x h (sm-half-edges mesh))
(let ((sharpness (sharpness (sm-nth-edge mesh (edge h))))
(crease-point (smooth-edge-vertex-crease-point mesh h))
(j (+ (length (sm-vertices mesh)) (length (sm-faces mesh)) (edge h))))
(cond ((>= sharpness 1.0) ;same as boundary case, set to crease point
(setf (point (sm-nth-vertex subdiv j)) crease-point))
((> sharpness 0.0) ;lerp smooth and crease points
(setf (point (sm-nth-vertex subdiv j))
(p:lerp (point (sm-nth-vertex subdiv j))
crease-point
sharpness)))))))

(defun set-smooth-vertex-vertex-points (mesh subdiv)
(do-array (x h (sm-half-edges mesh))
Expand All @@ -75,20 +85,63 @@
(p* (point (sm-nth-vertex mesh v)) (- n 3)))
(* n n)))))))))

;;; TODO - sharp creases
;; (defun set-smooth-vertex-vertex-crease-points (mesh subdiv)
;; (do-array (x h (sm-half-edges mesh))
;; (let* ((v (vertex h))
;; (sharpness (sm-vertex-sharpness mesh v)))
;; (when (> sharpness 0)
;; (setf (point (sm-nth-vertex subdiv v))
;; (p:lerp (point (sm-nth-vertex subdiv v))
;; (point (sm-nth-vertex mesh v))
;; sharpness))))))
;;; sharp creases
(defun smooth-vertex-vertex-crease-point (mesh half-edge)
(let* ((v (vertex half-edge))
(vtx (sm-nth-vertex mesh v))
(crease-edges (sm-vertex-crease-edges mesh v)))
(cond ((> (length crease-edges) 2) ;corner vertex
(p:copy (point vtx)))
((= (length crease-edges) 2) ;vertex on crease
(let ((edge-point-0 (point (sm-edge-other-vertex mesh (elt crease-edges 0) vtx)))
(edge-point-1 (point (sm-edge-other-vertex mesh (elt crease-edges 1) vtx))))
;; equation 9 in Pixar paper
(p/ (p+ (p+ (p* (point vtx) 6) edge-point-0) edge-point-1) 8.0)))
(t nil)))) ;return nil and do nothing, use smoothed vertex

(defun set-smooth-vertex-vertex-crease-points (mesh subdiv)
(do-array (x h (sm-half-edges mesh))
(let* ((sharpness (sharpness (sm-nth-edge mesh (edge h))))
(crease-point (smooth-vertex-vertex-crease-point mesh h))
(v (vertex h)))
(when crease-point
(cond ((>= sharpness 1.0) ;same as boundary case, set to crease point
(setf (point (sm-nth-vertex subdiv v)) crease-point))
((> sharpness 0.0) ;lerp smooth and crease points
(setf (point (sm-nth-vertex subdiv v))
(p:lerp (point (sm-nth-vertex subdiv v))
crease-point
sharpness))))))))

(defun set-smooth-vertex-vertex-crease-points-SAV (mesh subdiv)
(do-array (x h (sm-half-edges mesh))
(let* ((v (vertex h))
(vtx (sm-nth-vertex mesh v))
(crease-edges (sm-vertex-crease-edges mesh v)))
(cond ((> (length crease-edges) 2) ;corner vertex
(setf (point (sm-nth-vertex subdiv v))
(p:copy (point vtx))))
((= (length crease-edges) 2) ;vertex on crease
(let ((edge-point-0 (point (sm-edge-other-vertex mesh (elt crease-edges 0) vtx)))
(edge-point-1 (point (sm-edge-other-vertex mesh (elt crease-edges 1) vtx))))
;; equation 9 in Pixar paper
(setf (point (sm-nth-vertex subdiv v))
(p/ (p+ (p+ (p* (point vtx) 6)
edge-point-0)
edge-point-1)
8.0))))
(t nil)))))
(defmethod sm-edge-other-vertex ((mesh subdiv-mesh) (edge sm-edge) (vertex sm-vertex))
(let* ((vertices (sm-edge-vertices mesh edge)))
(cond ((eq vertex (elt vertices 0))
(elt vertices 1))
((eq vertex (elt vertices 1))
(elt vertices 0))
(t (error "Vertex ~a is not on edge ~a" vertex edge)))))

;;; TODO - sharp creases
;; (defun set-smooth-edge-sharpness (mesh subdiv)
;; (do-array (i e (sm-edges mesh))
;; (setf (sharpness (sm-nth-edge subdiv (* 2 i))) (sharpness e))
;; (setf (sharpness (sm-nth-edge subdiv (+ (* 2 i) 1))) (sharpness e))))
(defun set-smooth-subdiv-edge-sharpness (mesh subdiv)
(do-array (i e (sm-edges mesh))
(setf (sharpness (sm-nth-edge subdiv (* 2 i))) (1- (sharpness e)))
(setf (sharpness (sm-nth-edge subdiv (+ (* 2 i) 1))) (1- (sharpness e)))))

139 changes: 93 additions & 46 deletions src/plugins/subdiv-mesh.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
(selected? nil)))

(defclass-kons-9 sm-edge ()
(;(sharpness 0);;; TODO - sharp creases
(is-boundary-edge? nil)))
((sm-half-edge nil)
(sharpness 0)
(is-boundary-edge? nil)
(selected? nil)))

(defclass-kons-9 sm-half-edge ()
((mesh nil)
Expand All @@ -29,8 +31,7 @@
(edge nil)
(next-half-edge nil)
(prev-half-edge nil)
(pair-half-edge -1) ;no pair
(selected? nil)))
(pair-half-edge -1))) ;no pair

(defclass-kons-9 subdiv-mesh (polyhedron)
((sm-vertices (make-array 0 :adjustable t :fill-pointer t))
Expand Down Expand Up @@ -72,19 +73,36 @@
(defmethod sm-vertex-half-edges ((mesh subdiv-mesh) v)
(let* ((e0 (sm-half-edge (sm-nth-vertex mesh v)))
(e e0))
(loop :do (setf e (prev-half-edge (sm-nth-half-edge mesh (pair-half-edge (sm-nth-half-edge mesh e)))))
(loop :do (setf e (next-half-edge (sm-nth-half-edge mesh (pair-half-edge (sm-nth-half-edge mesh e)))))
;; (loop :do (setf e (prev-half-edge (sm-nth-half-edge mesh (pair-half-edge (sm-nth-half-edge mesh e)))))
:collect (sm-nth-half-edge mesh e)
:while (not (= e e0)))))

(defmethod sm-vertex-half-edges-indices ((mesh subdiv-mesh) v)
(let* ((e0 (sm-half-edge (sm-nth-vertex mesh v)))
(e e0))
(loop :do (setf e (next-half-edge (sm-nth-half-edge mesh (pair-half-edge (sm-nth-half-edge mesh e)))))
;; (loop :do (setf e (prev-half-edge (sm-nth-half-edge mesh (pair-half-edge (sm-nth-half-edge mesh e)))))
:collect e
:while (not (= e e0)))))

(defmethod sm-vertex-edges ((mesh subdiv-mesh) v)
(mapcar (lambda (e) (sm-nth-edge mesh (edge e)))
(sm-vertex-half-edges mesh v)))

(defmethod sm-vertex-edges-indices ((mesh subdiv-mesh) v)
(mapcar (lambda (e) (edge e))
(sm-vertex-half-edges mesh v)))

;;; TODO - sharp creases
;; (defmethod sm-vertex-sharpness ((mesh subdiv-mesh) v)
;; (let ((edge-sharpness-list (mapcar #'sharpness (sm-vertex-edges mesh v))))
;; (/ (reduce #'+ edge-sharpness-list) (length edge-sharpness-list))))

(defmethod sm-vertex-crease-edges ((mesh subdiv-mesh) v)
(remove-if (lambda (e) (<= (sharpness e) 0.0)) (sm-vertex-edges mesh v)))


(defmethod sm-vertex-vertices ((mesh subdiv-mesh) v)
(mapcar (lambda (e) (sm-nth-vertex mesh (vertex e)))
(sm-vertex-half-edges mesh v)))
Expand All @@ -104,6 +122,19 @@
;; :collect (face (sm-nth-half-edge mesh e))
;; :while (not (eq e e0)))))

(defmethod sm-edge-vertices ((mesh subdiv-mesh) e)
(let* ((h0 (sm-half-edge e))
(h1 (next-half-edge (sm-nth-half-edge mesh h0))))
;; (print (list e h0 h1 (vertex (sm-nth-half-edge mesh h0)) (vertex (sm-nth-half-edge mesh h1))))
(list (sm-nth-vertex mesh (vertex (sm-nth-half-edge mesh h0)))
(sm-nth-vertex mesh (vertex (sm-nth-half-edge mesh h1))))))

(defmethod sm-edge-vertices-index ((mesh subdiv-mesh) e)
(let* ((h0 (sm-half-edge e))
(h1 (next-half-edge (sm-nth-half-edge mesh h0))))
(list (vertex (sm-nth-half-edge mesh h0))
(vertex (sm-nth-half-edge mesh h1)))))

;; (defmethod sm-half-edge-faces ((edge sm-half-edge))
;; (list (face edge) (face (pair-half-edge edge))))

Expand Down Expand Up @@ -167,7 +198,8 @@
(loop for i from 0 below (length (sm-half-edges mesh))
do (let* ((half-edge-1 (aref (sm-half-edges mesh) i))
(new-edge (if (null (edge half-edge-1))
(make-instance 'sm-edge :is-boundary-edge? t) ;unset boundary below
(make-instance 'sm-edge :sm-half-edge i
:is-boundary-edge? t) ;unset boundary below
nil)))
(when new-edge
(add-edge mesh new-edge)
Expand Down Expand Up @@ -199,13 +231,13 @@
(format t "~%")
(format t "Vertices:~%")
(do-array (i v (sm-vertices mesh))
(format t " ~d: ~a ~a ~a~%" i (sm-half-edge v) (vertex-type v) (point v)))
(format t " ~d: ~a ~a ~a he ~a e ~a~%" i (sm-half-edge v) (vertex-type v) (point v) (sm-vertex-half-edges-indices mesh i) (sm-vertex-edges-indices mesh i)))
(format t "Faces:~%")
(do-array (i f (sm-faces mesh))
(format t " ~d: ~a~%" i (sm-half-edge f)))
(format t "Edges:~%")
(do-array (i e (sm-edges mesh))
(format t " ~d: ~a~%" i (is-boundary-edge? e)))
(format t " ~d: ~a ~a ~a v ~a~%" i (sm-half-edge e) (is-boundary-edge? e) (selected? e) (sm-edge-vertices-index mesh e)))
(format t "Half-edges:~%")
(do-array (i e (sm-half-edges mesh))
(format t " ~d: v ~a f ~a e ~a n ~a p ~a t ~a~%" i (vertex e) (face e) (edge e) (next-half-edge e) (prev-half-edge e) (pair-half-edge e))))
Expand Down Expand Up @@ -340,11 +372,18 @@
(setf (sm-half-edge (sm-nth-face subdiv h)) (* 4 h)) ;set face half-edge
))

;; set edge and vertex boundary flags
;; set edge half-edge, and edge and vertex boundary flags
(do-array (i e (sm-half-edges subdiv))
(setf (sm-half-edge (sm-nth-edge subdiv (edge e))) i)
(when (= -1 (pair-half-edge e))
(setf (is-boundary-edge? (sm-nth-edge subdiv (edge e))) t)
(setf (is-boundary-vertex? (sm-nth-vertex subdiv (vertex e))) t)))

;; set edge selection flags
(do-array (i e (sm-edges mesh))
(setf (selected? (sm-nth-edge subdiv (* 2 i))) (selected? e))
(setf (selected? (sm-nth-edge subdiv (+ (* 2 i) 1))) (selected? e)))

subdiv)

(defmethod build-polyhedron-faces ((mesh subdiv-mesh))
Expand Down Expand Up @@ -381,6 +420,51 @@
n))


(defmethod select-vertex ((mesh subdiv-mesh) i)
(setf (selected? (aref (sm-vertices mesh) i)) t))

(defmethod select-face ((mesh subdiv-mesh) i)
(setf (selected? (aref (sm-faces mesh) i)) t))

(defmethod select-edge ((mesh subdiv-mesh) i)
(setf (selected? (aref (sm-edges mesh) i)) t))

(defmethod select-edges ((mesh subdiv-mesh) edges)
(map 'vector (lambda (e) (select-edge mesh e)) edges))

(defmethod selected-edges ((mesh subdiv-mesh))
(remove-if (lambda (e) (not (selected? e))) (sm-edges mesh)))


(defmethod draw ((mesh subdiv-mesh))
; (print-topology mesh)
(call-next-method)
(when (is-visible? mesh)
(draw-selected-faces mesh)
(draw-selected-edges mesh)
(draw-selected-points mesh)))

(defmethod draw-selected-faces ((mesh subdiv-mesh))
(3d-draw-highlighted-polygons (points mesh) (faces mesh) (face-normals mesh) (point-normals mesh)
(map 'vector (lambda (f) (selected? f)) (sm-faces mesh))))

(defmethod draw-selected-edges ((mesh subdiv-mesh))
(let ((selected-edges ()))
(do-array (i edge (sm-edges mesh))
(when (selected? edge)
(let ((vertices (sm-edge-vertices mesh edge)))
(push (point (elt vertices 0)) selected-edges)
(push (point (elt vertices 1)) selected-edges))))
(3d-draw-lines selected-edges :highlight? t)))

(defmethod draw-selected-points ((mesh subdiv-mesh))
(let ((selected-points ()))
(dotimes (i (length (points mesh)))
(when (selected? (aref (sm-vertices mesh) i))
(push (aref (points mesh) i) selected-points)))
(3d-draw-points (coerce selected-points 'vector) nil :highlight? t)))


#|
(defmethod verify-topology ((mesh subdiv-mesh))
;; vertices
Expand Down Expand Up @@ -414,43 +498,6 @@
(when (not (eq edge (pair-half-edge (pair-half-edge edge))))
(error "VERIFY-TOPOLOGY -- pair-half-edge mismatch ~a ~a" edge (pair-half-edge edge))))
t)
(defmethod select-vertex ((mesh subdiv-mesh) i)
(setf (selected? (aref (sm-vertices mesh) i)) t))
(defmethod select-face ((mesh subdiv-mesh) i)
(setf (selected? (aref (sm-faces mesh) i)) t))
(defmethod select-edge ((mesh subdiv-mesh) i)
(setf (selected? (aref (sm-half-edges mesh) i)) t))
(defmethod draw ((mesh subdiv-mesh))
(call-next-method)
(draw-selected-faces mesh)
(draw-selected-edges mesh)
(draw-selected-points mesh))
(defmethod draw-selected-faces ((mesh subdiv-mesh))
(3d-draw-highlighted-polygons (points mesh) (faces mesh) (face-normals mesh) (point-normals mesh)
(map 'vector (lambda (f) (selected? f)) (sm-faces mesh))))
(defmethod draw-selected-edges ((mesh subdiv-mesh))
(let ((selected-edges ()))
(dotimes (i (length (sm-half-edges mesh)))
(let ((edge (aref (sm-half-edges mesh) i)))
(when (selected? edge)
(let ((p0 (point (vertex edge)))
(p1 (point (vertex (prev-edge edge)))))
(push p0 selected-edges)
(push p1 selected-edges)))))
(3d-draw-lines selected-edges :highlight? t)))
(defmethod draw-selected-points ((mesh subdiv-mesh))
(let ((selected-points ()))
(dotimes (i (length (points mesh)))
(when (selected? (aref (sm-vertices mesh) i))
(push (aref (points mesh) i) selected-points)))
(3d-draw-points (coerce selected-points 'vector) nil :highlight? t)))
|#

;;; print topology
Expand Down
Loading

0 comments on commit 299ed61

Please sign in to comment.