Пример #1
0
func LoadSceneAsModel(filename string) (*Model, error) {
	doc, err := collada.LoadDocument(filename)
	if err != nil {
		return nil, err
	}
	index, err := NewIndex(doc)
	if err != nil {
		return nil, err
	}
	model := EmptyModel("scene")
	switch doc.Asset.UpAxis {
	case collada.Xup:
	case collada.Yup:
	case collada.Zup:
		model.Transform = glm.HomogRotate3DXd(-90).Mul4(glm.HomogRotate3DZd(90))
	}

	geometryTemplates := make(map[collada.Id][]*Geometry)
	for id, mesh := range index.Mesh {
		geoms := make([]*Geometry, 0)
		for _, pl := range mesh.Polylist {
			elements := make([]*DrawElements, 0)
			drawElements := NewDrawElements(pl.TriangleElements, gl.TRIANGLES)
			if drawElements != nil {
				elements = append(elements, drawElements)
			}
			geometry := NewGeometry(string(id), pl.VertexData, pl.NormalData, elements)
			geoms = append(geoms, geometry)
		}
		if len(geoms) > 0 {
			geometryTemplates[id] = geoms
		}
	}
	for _, node := range index.VisualScene.Node {
		child, ok := LoadModel(index, node, geometryTemplates)
		if ok {
			model.AddChild(child)
		}
	}
	return model, nil
}
Пример #2
0
func (car *Car) Simulate(controls Controls, timestep float64) {
	p := car.Center
	v := car.Velocity
	u := car.Direction
	at := car.TransientAcceleration
	rwav := car.RearWheelAngularVelocity
	m := car.Profile.Mass
	d := car.Profile.Drag
	rr := car.Profile.RollingResistance
	h := car.Profile.CenterOfGravityHeight
	fl := car.Profile.FrontAxelDisplacement
	rl := car.Profile.RearAxelDisplacement
	xg := car.Profile.GearRatio
	xd := car.Profile.DifferentialRatio
	te := car.Profile.TransmissionEfficiency
	wr := car.Profile.WheelRadius
	wm := car.Profile.WheelMass
	bmax := car.Profile.BreakingPower
	bmaxToruqe := bmax / wr
	mu := car.Profile.TyreFrictionMu
	tc := car.Profile.TyreTractionConstant
	g := Gravity
	dt := timestep
	vmag := v.Len()

	staticWeight := g * m
	axelDisplacement := fl + rl

	// maxFrontTyreTraction := rl / axelDisplacement * weight - (h-wr)/axelLength * m * at.Dot(u)
	dynamicWeight := (h - wr) / axelDisplacement * m * at.Dot(u)
	weight := fl/axelDisplacement*staticWeight + dynamicWeight
	maxRearTyreTraction := mu * weight

	freeRollingAV := v.Dot(u) / wr
	rwav = freeRollingAV
	slipRatio := 0.0
	if !IsZero(v) {
		slipRatio = (rwav*wr - v.Dot(u)) / vmag
	}
	//  else {
	//    // slipRatio = rwav * wr //-rwav * wr
	// }
	tractionForce := math.Min(tc*slipRatio, maxRearTyreTraction)
	tractionTorque := tractionForce * wr
	// fmt.Println("tyre traction force", tractionForce)

	vn := glm.Vec4d{}
	if !IsZero(v) {
		vn = v.Normalize()
	}

	brakeTorque := bmaxToruqe * vn.Dot(u) * controls.BreakPedal

	rpm := freeRollingAV * xg * xd * 60 / (2 * math.Pi)
	engineTorque := car.Profile.Engine.Torque(rpm)

	appliedTorque := engineTorque * controls.FuelPedal
	driveTorque := appliedTorque * xg * xd * te
	driveForce := driveTorque / wr

	totalTorque := driveTorque - 2*tractionTorque - brakeTorque

	// fmt.Println("wrav", rwav)
	// fmt.Println("driveTorque", driveTorque)
	// fmt.Println("tractionTorque", tractionTorque)
	// fmt.Println("brakeTorque", brakeTorque)
	// fmt.Println("totalTorque", totalTorque)

	b := bmax * controls.BreakPedal

	rearForceTraction := math.Copysign(math.Min(math.Abs(driveForce), maxRearTyreTraction), driveForce)
	forceTraction := u.Mul(rearForceTraction)

	forceBreaking := u.Mul(-b * vn.Dot(u))
	forceDrag := v.Mul(-d * vmag)
	forceRollingResistance := v.Mul(-rr)

	force := forceTraction.Add(forceDrag).Add(forceRollingResistance).Add(forceBreaking)

	rearWheelInertia := wm * wr * wr / 2
	wheelAcceleration := totalTorque / rearWheelInertia
	drwav := wheelAcceleration * dt

	a := force.Mul(1.0 / m)
	dv := a.Mul(dt)
	dp := v.Mul(dt).Add(a.Mul(dt * dt * 0.5))
	if v.Len() < forceBreaking.Len()*dt/m {
		dv = v.Mul(-1)
	}

	// fmt.Println(rwav, dv)

	p = p.Add(dp)
	v = v.Add(dv)
	rwav = rwav + drwav

	rwav = v.Dot(u) / wr

	car.FrontWheelO = car.FrontWheelO + controls.WheelAngularVelocity*dt
	car.FrontWheelO = math.Copysign(math.Min(math.Abs(car.FrontWheelO), car.Profile.MaxStreeringAngle), car.FrontWheelO)
	if math.Abs(car.FrontWheelO) > 0.0001 {
		turningRadius := axelDisplacement / math.Sin(car.FrontWheelO)
		angularVelocity := v.Dot(u) / turningRadius
		rotation := dt * angularVelocity
		m := glm.HomogRotate3DZd(-rotation * 180 / math.Pi)
		u = m.Mul4x1(u)
		v = m.Mul4x1(v)
	}

	car.Center = p
	car.Velocity = v
	car.TransientAcceleration = a
	car.RearWheelAngularVelocity = rwav
	car.Direction = u
	car.FrontWheelAngularDeviation += freeRollingAV * dt
	car.RearWheelAngularDeviation += car.RearWheelAngularVelocity * dt
}
Пример #3
0
func (r *Receiver) LoadScene(filename string) {
	doc, err := collada.LoadDocument(filename)
	panicOnErr(err)
	index, err := gtk.NewIndex(doc)
	panicOnErr(err)
	r.SceneIndex = index

	model := gtk.EmptyModel("scene")
	switch doc.Asset.UpAxis {
	case collada.Xup:
	case collada.Yup:
	case collada.Zup:
		model.Transform = glm.HomogRotate3DXd(-90).Mul4(glm.HomogRotate3DZd(90))
	}

	portalPattern, _ := regexp.Compile("^Portal_(\\d+)_(\\d+)")

	geometryTemplates := make(map[collada.Id][]*gtk.Geometry)
	for id, mesh := range r.SceneIndex.Mesh {
		geoms := make([]*gtk.Geometry, 0)
		for _, pl := range mesh.Polylist {
			matches := portalPattern.FindStringSubmatch(mesh.VerticesId)
			if matches == nil {
				elements := make([]*gtk.DrawElements, 0)
				drawElements := gtk.NewDrawElements(pl.TriangleElements, gl.TRIANGLES)
				if drawElements != nil {
					elements = append(elements, drawElements)
				}
				geometry := gtk.NewGeometry(string(id), pl.VertexData, pl.NormalData, elements)
				geoms = append(geoms, geometry)
			} else {
				fmt.Println("ignoring Portal")
			}
		}
		if len(geoms) > 0 {
			geometryTemplates[id] = geoms
		}
	}

	portalLink := map[int]int{}
	portals := map[int]portal.Quad{}
	for _, node := range r.SceneIndex.VisualScene.Node {
		matches := portalPattern.FindStringSubmatch(node.Name)
		transform := r.SceneIndex.Transforms[node.Id]
		if matches == nil {
			geoms := make([]*gtk.Geometry, 0)
			for _, geoinstance := range node.InstanceGeometry {
				geoid, _ := geoinstance.Url.Id()
				geoms = append(geoms, geometryTemplates[geoid]...)
			}
			if len(geoms) > 0 {
				child := gtk.NewModel(node.Name, []*gtk.Model{}, geoms, transform)
				model.AddChild(child)
			}
		} else {
			index, err := strconv.Atoi(matches[1])
			if err != nil {
				panic(err)
			}
			exit, err := strconv.Atoi(matches[2])
			if err != nil {
				panic(err)
			}

			mt := model.Transform.Mul4(transform)
			center := mt.Mul4x1(glm.Vec4d{0, 0, 0, 1})
			normal := mt.Mul4x1(glm.Vec4d{0, 0, 1, 0}).Normalize()
			planev := mt.Mul4x1(glm.Vec4d{1, 0, 0, 0}).Normalize()
			scale := glm.Vec4d{}
			n := 0
			for i := 0; i < 3; i++ {
				sum := 0.0
				for j := 0; j < 3; j++ {
					sum += float64(mt[n] * mt[n])
					n++
				}
				n++
				scale[i] = math.Sqrt(sum)
			}

			quad := portal.Quad{
				center,
				normal,
				planev,
				scale,
			}
			portalLink[index] = exit
			portals[index] = quad
			// fmt.Println("portal node", node.Name, quad)
		}
	}
	r.Data.Scene.AddChild(model)

	for id, quad := range portals {
		exit, ok := portals[portalLink[id]]
		if ok {
			up := portal.Cross3D(exit.Normal, exit.PlaneV)
			// fmt.Println("pre ",exit)
			exit = exit.Apply(glm.HomogRotate3Dd(math.Pi, up))
			// fmt.Println("post",exit)
			_, inverse, pva, _ := portal.PortalTransform(quad, exit)
			portal := portal.Portal{quad, inverse, pva}
			r.Portals = append(r.Portals, portal)
		} else {
			fmt.Println("no exit for portal", id, portalLink[id])
		}
	}
}