Header

Rhino.Python – Tessellation and Subdivision – first version

subdivision02 subdivision06 Description: Using recursive loop and drawing to tessellate and subdivide surfaces. Warning: This is only the rough first version so contain lots of problems and bugs. Use it carefully, otherwise it will crash your computer. A lot of problem need to be solved. Problem: The dirction and orientation of subdivision faces should be organized. Using surface is not an efficient way. Should turn surfaces into meshes. process Diagram: diagram Code
"""
####################################################################
Computational Design Assignment 04
Tessellation and Subdivision

Written by:
Gene Ting-Chun Kao

This is only the rough first version so contain lots of problems and bugs.
Use it carefully, otherwise it will crash your computer.

problem:
The dirction and orientation of subdivision faces should be organized.
Using surface is not a good way. Should turn surfaces into meshes.

####################################################################
"""

import rhinoscriptsyntax as rs
import Rhino as rh
import math
import Rhino.Geometry as rg
from scriptcontext import escape_test
from scriptcontext import doc
from random import *

def DivideSrfUV(srf, dividU, dividV):
    """
    Divid surface method
    return: uv vector
    uv position using vector, so uv can be calculate later.
    """
    domainU = rs.SurfaceDomain(srf, 0)
    domainV = rs.SurfaceDomain(srf, 1)
    uStep = (domainU[1]-domainU[0])/dividU
    vStep = (domainV[1]-domainV[0])/dividV

    uvList = []
    for i in range(dividU+1):
        u0 = domainU[0] + uStep*i
        if i < (dividU):
            u1 = domainU[0] + uStep*(i+1)
            for j in range(dividV+1):
                v0 = domainV[0] + vStep*j
                if j < (dividV):
                    v1 = domainV[0] + vStep*(j+1)
                    vec00 = rg.Vector3d(u0,v0,0)
                    vec01 = rg.Vector3d(u1,v0,0)
                    vec02 = rg.Vector3d(u1,v1,0)
                    vec03 = rg.Vector3d(u0,v1,0)
                    uvList.append( [ vec00, vec01, vec02, vec03 ] )
    return uvList

def subdivision(srf, uvList, iteration):

    newSrf = []

    count = 0
    ratio = 0.2

    for panelUV in uvList:
        if count%2 == 1:
            midPt00 = vecRatio(panelUV[0], panelUV[1], ratio)
            midPt01 = vecRatio(panelUV[1], panelUV[2], ratio)
            midPt02 = vecRatio(panelUV[2], panelUV[3], ratio)
            midPt03 = vecRatio(panelUV[3], panelUV[0], ratio)
        else:
            midPt00 = vecRatio(panelUV[0], panelUV[1], ratio, True)
            midPt01 = vecRatio(panelUV[1], panelUV[2], ratio, True)
            midPt02 = vecRatio(panelUV[2], panelUV[3], ratio, True)
            midPt03 = vecRatio(panelUV[3], panelUV[0], ratio, True)

        midPts = [ midPt00, midPt01, midPt02, midPt03 ]
        centerPt = vecAverage(midPts)
        #centerPt = vecAverage(panelUV)

        pt0 = rs.EvaluateSurface(srf, panelUV[0][0], panelUV[0][1])
        pt1 = rs.EvaluateSurface(srf, midPt00[0], midPt00[1])
        pt2 = rs.EvaluateSurface(srf, panelUV[1][0], panelUV[1][1])
        pt3 = rs.EvaluateSurface(srf, midPt03[0], midPt03[1])
        pt4 = rs.EvaluateSurface(srf, centerPt[0], centerPt[1])
        pt5 = rs.EvaluateSurface(srf, midPt01[0], midPt01[1])
        pt6 = rs.EvaluateSurface(srf, panelUV[3][0], panelUV[3][1])
        pt7 = rs.EvaluateSurface(srf, midPt02[0], midPt02[1])
        pt8 = rs.EvaluateSurface(srf, panelUV[2][0], panelUV[2][1])

        centerNormal = rs.SurfaceNormal( srf, pt4 )
        centerPtExtrude = vecExtrude(pt4, centerNormal, iteration*3 + 0.4)
        pt4 = centerPtExtrude

        s0 = rs.AddSrfPt([pt0,pt1,pt4,pt3])
        s1 = rs.AddSrfPt([pt1,pt2,pt5,pt4])
        s2 = rs.AddSrfPt([pt4,pt5,pt8,pt7])
        s3 = rs.AddSrfPt([pt3,pt4,pt7,pt6])

        newSrf.append(s0)
        newSrf.append(s1)
        newSrf.append(s2)
        newSrf.append(s3)

        count += 1

    escape_test()

    for s in newSrf:
        if iteration > 0:
            uv = DivideSrfUV(s, 1, 1)
            subdivision(s, uv, iteration-1)
            rs.DeleteObject(s)
        else:
            break

    return newSrf

def vecAverage(vecList):
    preVec = rg.Vector3d(0,0,0)
    for vec in vecList:
        preVec = rg.Vector3d.Add(preVec, vec)
    return rg.Vector3d.Divide(preVec, len(vecList))

def vecRatio(vecA, vecB, r = 0.5, rotation = False):
    if rotation == False:
        if r > 1:
            r = 1
        elif r < 0:
            r = 0
        else:
            r = r
    else:
        if r > 1:
            r = 0
        elif r < 0:
            r = 1
        else:
            r = 1 - r

    vecBA = rg.Vector3d.Subtract(vecA, vecB)
    rVec = rg.Vector3d.Multiply(r, vecBA) + vecB

    return rVec

def vecExtrude(vec, normal, s = 1):
    normal = rs.VectorScale(normal, s)
    extrudePt = rs.VectorAdd(vec, normal)
    return extrudePt

def main():
    surface = rs.GetObject("pick a surface.", rs.filter.surface)

    rs.EnableRedraw(False)

    uv = DivideSrfUV(surface, 3, 3)
    subdivision(surface, uv, 2)
    rs.EnableRedraw(True)

if __name__ == "__main__":
    main()

,

No comments yet.

Leave a Reply

(Psalm 111:10)