func (self *SurfacePoint) NextDirection(r *rand.Rand, inDirection Vector3f, outDirection_o *Vector3f, colour *Vector3f) bool { reflectivityMean := self.Tri.Reflectivity.Dot(VECTOR_ONE) / 3.0 /* russian-roulette for reflectance 'magnitude' */ isAlive := r.Float32() < reflectivityMean if !isAlive { return false } /* cosine-weighted importance sample hemisphere */ _2pr1 := math32.Pi * 2.0 * r.Float32() sr2 := math32.Sqrt(r.Float32()) /* make coord frame coefficients (z in normal direction) */ x := math32.Cos(_2pr1) * sr2 y := math32.Sin(_2pr1) * sr2 z := math32.Sqrt(1.0 - (sr2 * sr2)) /* make coord frame */ t := self.Tri.Tangent() n := self.Tri.Normal() var c Vector3f /* put normal on inward ray side of surface (preventing transmission) */ if n.Dot(inDirection) < 0.0 { n.Neg() } c = n.Cross(t) /* scale frame by coefficients */ tx := t.Mulf(x) cy := c.Mulf(y) nz := n.Mulf(z) /* make direction from sum of scaled components */ sum := tx.Add(cy) *outDirection_o = sum.Add(nz) /* make color by dividing-out mean from reflectivity */ *colour = self.Tri.Reflectivity.Mulf(1.0 / reflectivityMean) /* discluding degenerate result direction */ return isAlive && !outDirection_o.Is_Zero() }
func (self *Triangle) SamplePoint(r *rand.Rand) Vector3f { /* get two randoms */ sqr1 := math32.Sqrt(r.Float32()) r2 := r.Float32() /* make barycentric coords */ c0 := 1.0 - sqr1 c1 := (1.0 - r2) * sqr1 /* make barycentric axes */ a0 := self.Vertexs[1].Sub(self.Vertexs[0]) a1 := self.Vertexs[2].Sub(self.Vertexs[0]) /* scale axes by coords */ ac0 := a0.Mulf(c0) ac1 := a1.Mulf(c1) /* sum scaled components, and offset from corner */ sum := ac0.Add(ac1) return sum.Add(self.Vertexs[0]) }
func (self *Vector3f) Mag() float32 { return math32.Sqrt(self.X*self.X + self.Y*self.Y + self.Z*self.Z) }
func (self *Triangle) Area() float32 { /* half area of parallelogram (area = magnitude of cross of two edges) */ normalV := self.NormalV() return math32.Sqrt(normalV.Dot(normalV)) * 0.5 }