func (this *Camera) RotateX(angle Double) { const limitAngle = 0.05 upAngle := this.Up.Angle(this.Dir) if upAngle < limitAngle && angle < 0.0 { return } if (math.Pi-upAngle) < limitAngle && angle > 0.0 { return } xaxis := this.Dir.Cross(this.Up) mrot := mat4.RotationAxis(xaxis, angle) this.Dir = mrot.Mulv(this.Dir) }
func RenderArrow(pos, dir *Vec3) { const tolerance = 0.0001 arrow := Get("arrow") l := dir.Length() d0 := dir.Unit() zaxis := V3(0, 0, 1) arrow.Mat = mat4.Scaling(V3(.1*l, .1*l, .5*l)) angle := zaxis.Angle(d0) if angle > tolerance && math.Pi-angle > tolerance { arrow.Mat = arrow.Mat.Mul(mat4.RotationAxis(zaxis.Add(d0).Unit(), math.Pi)) } else if math.Pi-angle <= tolerance { arrow.Mat = arrow.Mat.Mul(mat4.Scaling(V3(1, 1, -1))) } arrow.Mat = arrow.Mat.Mul(mat4.Translation(pos.Add(dir.Muls(.5)))) arrow.Render() }
func (this *Camera) RotateY(angle Double) { yaxis := this.Up mrot := mat4.RotationAxis(yaxis, angle) this.Dir = mrot.Mulv(this.Dir) }
func (s *Spline) CreateVbo_(nsteps, ncorners int, radius Double, usetex bool, tex1, tex2 *Vec2) { if ncorners < 3 { panic("too few corners") } nump := (ncorners + 1) * (nsteps + 1) numn := nump numt := nump p := make([]*Vec3, 0, nump) n := make([]*Vec3, 0, numn) var t, tcircle []*Vec2 if usetex { t = make([]*Vec2, 0, numt) tcircle = make([]*Vec2, 0, ncorners) } fixedaxis := V3(0.00001, 1.0, -.00002).Unit() angle := -2.0 * math.Pi / Double(ncorners) lastDir0, lastPos := V3(1, 0, 0), V3(0, 0, 0) processCircle := func(pos, normal *Vec3, step int) { dir0 := normal.Perp(fixedaxis) //correct axis swift: shortest distance between this circle's dir0 and the last circle's if step > 0 { dir0 = plane.ByPointAndNormal(pos, normal).NearestPoint(lastPos.Add(lastDir0)).Sub(pos).Unit() } lastDir0 = dir0 lastPos = pos texy := (tex2.Y-tex1.Y)*Double(step)/Double(nsteps) + tex1.Y for i := 0; i < ncorners+1; i++ { mrot := mat4.RotationAxis(normal, Double(i)*angle) dir := mrot.Mulv(dir0) p = append(p, pos.Add(dir.Muls(radius))) n = append(n, dir) if usetex { texx := (tex2.X-tex1.X)*Double(i)/Double(ncorners) + tex1.X t = append(t, V2(texx, texy)) } } } t1, t2 := s.StartTime(), s.EndTime() dt := t2 - t1 part := dt / Double(nsteps) time := t1 for i := 0; i < nsteps+1; i++ { pos := s.At(time) vel := s.AtD1(time) processCircle(pos, vel.Unit(), i) time += part } //front/back texCoords: if usetex { clockhand := V3(0, 1, 0) for i := 0; i < ncorners; i++ { mrot := mat4.RotationAxis(V3(0, 0, -1), Double(i)*angle) dir := mrot.Mulv(clockhand) tcircle = append(tcircle, V2(dir.X, dir.Y).Add(V2(1, 1)).Muls(0.5)) } } //filling vbo: s.vbo = vbo.New() v := s.vbo numi := (2 * 3 * nsteps * (ncorners + 1)) + 2*(ncorners-2) v.P = make([]*Vec3, 0, numi) v.N = make([]*Vec3, 0, numi) if usetex { v.T = make([]*Vec2, 0, numi) } //front + back fillVboWithCircle := func(index int, ccw bool) { normal := s.AtD1(t1).Muls(-1.0) //front face normal if !ccw { normal = s.AtD1(t2).Muls(1.0) //back face normal } doIndex := func(i1, i2 int) { v.P = append(v.P, p[index], p[index+i1], p[index+i2]) v.N = append(v.N, normal, normal, normal) if usetex { v.T = append(v.T, tcircle[0], tcircle[i1], tcircle[i2]) } } for i := 1; i < ncorners-1; i++ { if ccw { doIndex(i+1, i) } else { doIndex(i, i+1) } } } fillVboWithCircle(0, true) fillVboWithCircle(len(p)-(ncorners+1), false) appendVertexTriangle := func(a, b, c int) { v.P = append(v.P, p[a], p[b], p[c]) v.N = append(v.N, n[a], n[b], n[c]) if usetex { v.T = append(v.T, t[a], t[b], t[c]) } } fillVboWithCylinder := func(index int) { for i := 0; i < ncorners-1; i++ { appendVertexTriangle(index+i+0, index+i+1, index+i+0+ncorners+1) appendVertexTriangle(index+i+1+ncorners+1, index+i+0+ncorners+1, index+i+1) } //last, closing rectangle appendVertexTriangle(index+ncorners-1, index+ncorners+0, index+2*ncorners+0) appendVertexTriangle(index+2*ncorners+1, index+2*ncorners+0, index+ncorners+0) } for i := 0; i < nsteps; i++ { fillVboWithCylinder(i * (ncorners + 1)) } s.vbo.Create(gl.STATIC_DRAW) }