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 }
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 }
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]) } } }