<s> from __future__ import division <EOL> from . core import Mesh <EOL> import random <EOL> class Vector ( object ) : <EOL> def __init__ ( self , x , y , z ) : <EOL> self . x = x <EOL> self . y = y <EOL> self . z = z <EOL> def get_tuple ( self ) : <EOL> return ( self . x , self . y , self . z ) <EOL> def clone ( self ) : <EOL> return Vector ( self . x , self . y , self . z ) <EOL> def negate ( self ) : <EOL> return Vector ( - self . x , - self . y , - self . z ) <EOL> def add ( self , a ) : <EOL> return Vector ( self . x + a . x , self . y + a . y , self . z + a . z ) <EOL> def subtract ( self , a ) : <EOL> return Vector ( self . x - a . x , self . y - a . y , self . z - a . z ) <EOL> def multiply ( self , a ) : <EOL> return Vector ( self . x * a , self . y * a , self . z * a ) <EOL> def divide ( self , a ) : <EOL> return Vector ( self . x / a , self . y / a , self . z / a ) <EOL> def length ( self ) : <EOL> return self . dot ( self ) ** <NUM_LIT:0.5> <EOL> def dot ( self , a ) : <EOL> return self . x * a . x + self . y * a . y + self . z * a . z <EOL> def cross ( self , a ) : <EOL> return Vector ( <EOL> self . y * a . z - self . z * a . y , <EOL> self . z * a . x - self . x * a . z , <EOL> self . x * a . y - self . y * a . x ) <EOL> def normalize ( self ) : <EOL> return self . divide ( self . length ( ) ) ; <EOL> def interpolate ( self , a , t ) : <EOL> return self . add ( a . subtract ( self ) . multiply ( t ) ) <EOL> class Vertex ( object ) : <EOL> def __init__ ( self , position , normal , uv ) : <EOL> self . position = position <EOL> self . normal = normal <EOL> self . uv = uv <EOL> def clone ( self ) : <EOL> return Vertex ( <EOL> self . position . clone ( ) , self . normal . clone ( ) , self . uv . clone ( ) ) <EOL> def flip ( self ) : <EOL> self . normal = self . normal . negate ( ) <EOL> def interpolate ( self , a , t ) : <EOL> return Vertex ( <EOL> self . position . interpolate ( a . position , t ) , <EOL> self . normal . interpolate ( a . normal , t ) , <EOL> self . uv . interpolate ( a . uv , t ) ) <EOL> class Plane ( object ) : <EOL> @ staticmethod <EOL> def from_points ( a , b , c ) : <EOL> normal = b . subtract ( a ) . cross ( c . subtract ( a ) ) . normalize ( ) <EOL> return Plane ( normal , normal . dot ( a ) ) <EOL> def __init__ ( self , normal , w ) : <EOL> self . normal = normal <EOL> self . w = w <EOL> def clone ( self ) : <EOL> return Plane ( self . normal . clone ( ) , self . w ) <EOL> def flip ( self ) : <EOL> self . normal = self . normal . negate ( ) <EOL> self . w = - self . w <EOL> def split ( self , polygon , co_front , co_back , front , back ) : <EOL> COPLANAR = <NUM_LIT:0> <EOL> FRONT = <NUM_LIT:1> <EOL> BACK = <NUM_LIT:2> <EOL> BOTH = <NUM_LIT:3> <EOL> EPS = <NUM_LIT> <EOL> polygon_type = <NUM_LIT:0> <EOL> vertex_types = [ ] <EOL> for vertex in polygon . vertices : <EOL> w = self . normal . dot ( vertex . position ) - self . w <EOL> t = COPLANAR <EOL> if w < - EPS : <EOL> t = BACK <EOL> if w > EPS : <EOL> t = FRONT <EOL> polygon_type |= t <EOL> vertex_types . append ( t ) <EOL> if polygon_type == COPLANAR : <EOL> if self . normal . dot ( polygon . plane . normal ) > <NUM_LIT:0> : <EOL> co_front . append ( polygon ) <EOL> else : <EOL> co_back . append ( polygon ) <EOL> elif polygon_type == FRONT : <EOL> front . append ( polygon ) <EOL> elif polygon_type == BACK : <EOL> back . append ( polygon ) <EOL> else : <EOL> f = [ ] <EOL> b = [ ] <EOL> for i in xrange ( len ( polygon . vertices ) ) : <EOL> j = ( i + <NUM_LIT:1> ) % len ( polygon . vertices ) <EOL> v1 = polygon . vertices [ i ] <EOL> v2 = polygon . vertices [ j ] <EOL> t1 = vertex_types [ i ] <EOL> t2 = vertex_types [ j ] <EOL> if t1 != BACK : <EOL> f . append ( v1 ) <EOL> if t1 != FRONT : <EOL> if t1 != BACK : <EOL> b . append ( v1 . clone ( ) ) <EOL> else : <EOL> b . append ( v1 ) <EOL> if ( t1 | t2 ) == BOTH : <EOL> n = self . w - self . normal . dot ( v1 . position ) <EOL> d = self . normal . dot ( v2 . position . subtract ( v1 . position ) ) <EOL> v = v1 . interpolate ( v2 , n / d ) <EOL> f . append ( v ) <EOL> b . append ( v . clone ( ) ) <EOL> if len ( f ) >= <NUM_LIT:3> : <EOL> front . append ( Polygon ( f , polygon . shared ) ) <EOL> if len ( b ) >= <NUM_LIT:3> : <EOL> back . append ( Polygon ( b , polygon . shared ) ) <EOL> class Polygon ( object ) : <EOL> def __init__ ( self , vertices , shared ) : <EOL> self . vertices = vertices <EOL> self . shared = shared <EOL> self . plane = Plane . from_points ( * [ a . position for a in vertices [ : <NUM_LIT:3> ] ] ) <EOL> def clone ( self ) : <EOL> vertices = [ a . clone ( ) for a in self . vertices ] <EOL> return Polygon ( vertices , self . shared ) <EOL> def flip ( self ) : <EOL> self . vertices . reverse ( ) <EOL> for vertex in self . vertices : <EOL> vertex . flip ( ) <EOL> self . plane . flip ( ) <EOL> class Node ( object ) : <EOL> def __init__ ( self , polygons = None ) : <EOL> self . plane = None <EOL> self . front = None <EOL> self . back = None <EOL> self . polygons = [ ] <EOL> if polygons : <EOL> self . build ( polygons ) <EOL> def clone ( self ) : <EOL> node = Node ( ) <EOL> if self . plane : <EOL> node . plane = self . plane . clone ( ) <EOL> if self . front : <EOL> node . front = self . front . clone ( ) <EOL> if self . back : <EOL> node . back = self . back . clone ( ) <EOL> node . polygons = [ a . clone ( ) for a in self . polygons ] <EOL> return node <EOL> def invert ( self ) : <EOL> for polygon in self . polygons : <EOL> polygon . flip ( ) <EOL> self . plane . flip ( ) <EOL> if self . front : <EOL> self . front . invert ( ) <EOL> if self . back : <EOL> self . back . invert ( ) <EOL> self . front , self . back = self . back , self . front <EOL> def clip_polygons ( self , polygons ) : <EOL> if not self . plane : <EOL> return list ( polygons ) <EOL> front = [ ] <EOL> back = [ ] <EOL> for polygon in polygons : <EOL> self . plane . split ( polygon , front , back , front , back ) <EOL> if self . front : <EOL> front = self . front . clip_polygons ( front ) <EOL> if self . back : <EOL> back = self . back . clip_polygons ( back ) <EOL> else : <EOL> back = [ ] <EOL> return front + back <EOL> def clip_to ( self , node ) : <EOL> self . polygons = node . clip_polygons ( self . polygons ) <EOL> if self . front : <EOL> self . front . clip_to ( node ) <EOL> if self . back : <EOL> self . back . clip_to ( node ) <EOL> def get_polygons ( self ) : <EOL> result = list ( self . polygons ) <EOL> if self . front : <EOL> result . extend ( self . front . get_polygons ( ) ) <EOL> if self . back : <EOL> result . extend ( self . back . get_polygons ( ) ) <EOL> return result <EOL> def build ( self , polygons ) : <EOL> if not polygons : <EOL> return <EOL> self . plane = self . plane or random . choice ( polygons ) . plane . clone ( ) <EOL> front = [ ] <EOL> back = [ ] <EOL> for polygon in polygons : <EOL> self . plane . split ( polygon , self . polygons , self . polygons , front , back ) <EOL> if front : <EOL> self . front = self . front or Node ( ) <EOL> self . front . build ( front ) <EOL> if back : <EOL> self . back = self . back or Node ( ) <EOL> self . back . build ( back ) <EOL> class Model ( object ) : <EOL> def __init__ ( self , polygons = None ) : <EOL> self . polygons = polygons or [ ] <EOL> def clone ( self ) : <EOL> return Model ( [ a . clone ( ) for a in self . polygons ] ) <EOL> def get_polygons ( self ) : <EOL> return self . polygons <EOL> def __or__ ( self , other ) : <EOL> return self . union ( other ) <EOL> def __and__ ( self , other ) : <EOL> return self . intersection ( other ) <EOL> def __sub__ ( self , other ) : <EOL> return self . difference ( other ) <EOL> def __invert__ ( self ) : <EOL> return self . inverse ( ) <EOL> def union ( self , other ) : <EOL> a = Node ( self . clone ( ) . polygons ) <EOL> b = Node ( other . clone ( ) . polygons ) <EOL> a . clip_to ( b ) <EOL> b . clip_to ( a ) <EOL> b . invert ( ) <EOL> b . clip_to ( a ) <EOL> b . invert ( ) <EOL> a . build ( b . get_polygons ( ) ) <EOL> return Model ( a . get_polygons ( ) ) <EOL> def difference ( self , other ) : <EOL> a = Node ( self . clone ( ) . polygons ) <EOL> b = Node ( other . clone ( ) . polygons ) <EOL> a . invert ( ) <EOL> a . clip_to ( b ) <EOL> b . clip_to ( a ) <EOL> b . invert ( ) <EOL> b . clip_to ( a ) <EOL> b . invert ( ) <EOL> a . build ( b . get_polygons ( ) ) <EOL> a . invert ( ) <EOL> return Model ( a . get_polygons ( ) ) <EOL> def intersection ( self , other ) : <EOL> a = Node ( self . clone ( ) . polygons ) <EOL> b = Node ( other . clone ( ) . polygons ) <EOL> a . invert ( ) <EOL> b . clip_to ( a ) <EOL> b . invert ( ) <EOL> a . clip_to ( b ) <EOL> b . clip_to ( a ) <EOL> a . build ( b . get_polygons ( ) ) <EOL> a . invert ( ) <EOL> return Model ( a . get_polygons ( ) ) <EOL> def inverse ( self ) : <EOL> polygons = [ a . clone ( ) for a in self . polygons ] <EOL> for polygon in polygons : <EOL> polygon . flip ( ) <EOL> return Model ( polygons ) <EOL> def mesh ( self ) : <EOL> positions = [ ] <EOL> normals = [ ] <EOL> uvs = [ ] <EOL> for polygon in self . get_polygons ( ) : <EOL> for i in xrange ( <NUM_LIT:2> , len ( polygon . vertices ) ) : <EOL> a = polygon . vertices [ <NUM_LIT:0> ] <EOL> b = polygon . vertices [ i - <NUM_LIT:1> ] <EOL> c = polygon . vertices [ i ] <EOL> positions . append ( a . position . get_tuple ( ) ) <EOL> positions . append ( b . position . get_tuple ( ) ) <EOL> positions . append ( c . position . get_tuple ( ) ) <EOL> normals . append ( a . normal . get_tuple ( ) ) <EOL> normals . append ( b . normal . get_tuple ( ) ) <EOL> normals . append ( c . normal . get_tuple ( ) ) <EOL> uvs . append ( a . uv . get_tuple ( ) [ : <NUM_LIT:2> ] ) <EOL> uvs . append ( b . uv . get_tuple ( ) [ : <NUM_LIT:2> ] ) <EOL> uvs . append ( c . uv . get_tuple ( ) [ : <NUM_LIT:2> ] ) <EOL> return Mesh ( positions , normals , uvs ) <EOL> class Solid ( Model ) : <EOL> def __init__ ( self , shape ) : <EOL> polygons = [ ] <EOL> for i in xrange ( <NUM_LIT:0> , len ( shape . positions ) , <NUM_LIT:3> ) : <EOL> positions = shape . positions [ i : i + <NUM_LIT:3> ] <EOL> normals = shape . normals [ i : i + <NUM_LIT:3> ] <EOL> uvs = shape . uvs [ i : i + <NUM_LIT:3> ] <EOL> vertices = [ Vertex ( Vector ( * a ) , Vector ( * b ) , Vector ( c [ <NUM_LIT:0> ] , c [ <NUM_LIT:1> ] , <NUM_LIT:0> ) ) <EOL> for a , b , c in zip ( positions , normals , uvs ) ] <EOL> polygon = Polygon ( vertices , None ) <EOL> polygons . append ( polygon ) <EOL> super ( Solid , self ) . __init__ ( polygons ) </s>
