-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathtriangle.py
77 lines (54 loc) · 2.66 KB
/
triangle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import numpy as np
from ..utils.constants import *
from ..utils.vector3 import vec3
from ..geometry.primitive import Primitive
from ..geometry.collider import Collider
class Triangle(Primitive):
def __init__(self,center, material, p1 , p2, p3, max_ray_depth,shadow = True):
super().__init__(center, material, max_ray_depth, shadow = shadow)
self.collider_list += [Triangle_Collider(assigned_surface = self, p1 =p1, p2 = p2, p3 = p3)]
def get_uv(self, M, collider):
return collider.get_uv(M)
class Triangle_Collider(Collider):
def __init__(self,assigned_surface, p1, p2, p3):
self.assigned_primitive = assigned_surface
self.p1 = p1
self.p2 = p2
self.p3 = p3
self.normal = ((self.p2 - self.p1).cross( self.p3 - self.p1)).normalize()
self.centroid = (self.p1 + self.p2 + self.p3)/3 #one possible definition of center. Used for intersect().
self.n31 = (self.p3 - self.p1).cross(self.normal)
self.n12 = (self.p1- self.p2).cross(self.normal)
self.n23 = (self.p2 - self.p3).cross(self.normal)
def intersect(self, O, D):
N = self.normal
NdotD = N.dot(D)
NdotD = np.where(NdotD == 0., NdotD + 0.0001, NdotD) #avoid zero division
NdotC_O = N.dot(self.centroid - O)
d = D * NdotC_O / NdotD
M = O + d # intersection point
dis = d.length()
M_C = M - self.centroid
hit_inside = (self.n31.dot(M-self.p1) >= 0) & (self.n12.dot(M-self.p2) >= 0)& (self.n23.dot(M-self.p3) >= 0) & (NdotC_O * NdotD > 0)
hit_UPWARDS = (NdotD < 0)
hit_UPDOWN = np.logical_not(hit_UPWARDS)
pred1 = hit_inside & hit_UPWARDS
pred2 = hit_inside & hit_UPDOWN
pred3 = True
return np.select([pred1,pred2,pred3] , [[dis, np.tile(UPWARDS, dis.shape) ], [dis,np.tile(UPDOWN, dis.shape)], FARAWAY])
def rotate(self,M, center):
self.p1 = center + (self.p1 -center).matmul(M)
self.p2 = center + (self.p2 -center).matmul(M)
self.p3 = center + (self.p3 -center).matmul(M)
self.n31 = self.n31.matmul(M)
self.n12 = self.n12.matmul(M)
self.n23 = self.n23.matmul(M)
self.normal = self.normal.matmul(M)
self.centroid = center + (self.centroid-center).matmul(M)
def get_uv(self, hit):
M_C = hit.point - self.center
u = ((self.pu.dot(M_C)/self.w + 1 ) /2 + self.uv_shift[0])
v = ((self.pv.dot(M_C)/self.h + 1 ) /2 + self.uv_shift[1])
return u,v
def get_Normal(self, hit):
return self.normal