31 | function ArticulatedAxis:loadArticulatedAxis(xmlFile) |
32 | local index = getXMLInt(xmlFile, "vehicle.articulatedAxis#componentJointIndex"); |
33 | if index ~= nil then |
34 | local componentJoint = self.componentJoints[index+1]; |
35 | local rotSpeed = getXMLFloat(xmlFile, "vehicle.articulatedAxis#rotSpeed"); |
36 | local rotMax = getXMLFloat(xmlFile, "vehicle.articulatedAxis#rotMax"); |
37 | local rotMin = getXMLFloat(xmlFile, "vehicle.articulatedAxis#rotMin"); |
38 | if componentJoint ~= nil and rotSpeed ~= nil and rotMax ~= nil and rotMin ~= nil then |
39 | rotSpeed = math.rad(rotSpeed); |
40 | rotMax = math.rad(rotMax); |
41 | rotMin = math.rad(rotMin); |
42 | local entry = {}; |
43 | |
44 | entry.componentJoint = componentJoint; |
45 | entry.anchorActor = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.articulatedAxis#anchorActor"), 0); |
46 | entry.rotNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.articulatedAxis#rotNode")); |
47 | entry.rotMax = rotMax; |
48 | entry.rotMin = rotMin; |
49 | entry.rotSpeed = rotSpeed; |
50 | |
51 | local maxRotTime = rotMax/rotSpeed; |
52 | local minRotTime = rotMin/rotSpeed; |
53 | if minRotTime > maxRotTime then |
54 | local temp = minRotTime; |
55 | minRotTime = maxRotTime; |
56 | maxRotTime = temp; |
57 | end; |
58 | if maxRotTime > self.maxRotTime then |
59 | self.maxRotTime = maxRotTime; |
60 | end; |
61 | if minRotTime < self.minRotTime then |
62 | self.minRotTime = minRotTime; |
63 | end; |
64 | |
65 | entry.curRot = 0; |
66 | |
67 | local aiReverserNodeString = getXMLString(self.xmlFile, "vehicle.articulatedAxis#aiRevereserNode"); |
68 | if aiReverserNodeString ~= nil then |
69 | entry.aiRevereserNode = Utils.indexToObject(self.components, aiReverserNodeString); |
70 | end |
71 | |
72 | -- adjust variables used by AIVehicleUtil |
73 | local maxTurningRadius = 0; |
74 | |
75 | for i=1,2 do |
76 | local rootNode = self.components[componentJoint.componentIndices[i]].node; |
77 | |
78 | for _, wheel in ipairs(self.wheels) do |
79 | if self:getParentComponent(wheel.repr) == rootNode then |
80 | |
81 | local wx,_,wz = localToLocal(wheel.driveNode, rootNode, 0,0,0); |
82 | local dx1 = 1; |
83 | if wx < 0 then |
84 | dx1 = -1; |
85 | end |
86 | local dz1 = math.tan( math.max(wheel.rotMin, wheel.rotMax) ); |
87 | if wz > 0 then |
88 | dz1 = -dz1; |
89 | end |
90 | |
91 | local x2, z2 = 0, 0; |
92 | local dx2 = 1; |
93 | if wx < 0 then |
94 | dx2 = -1; |
95 | end |
96 | local dz2 = math.tan( math.max(rotMin, rotMax) ); |
97 | if wz < 0 then |
98 | dz2 = -dz2; |
99 | end |
100 | |
101 | -- normalize directions |
102 | local l1 = Utils.vector2Length(dx1, dz1); |
103 | dx1, dz1 = dx1 / l1, dz1 / l1; |
104 | |
105 | local l2 = Utils.vector2Length(dx2, dz2); |
106 | dx2, dz2 = dx2 / l2, dz2 / l2; |
107 | |
108 | local intersect, _, f2 = Utils.getLineLineIntersection2D(wx,wz, dx1,dz1, x2,z2, dx2,dz2); |
109 | if intersect then |
110 | local radius = math.abs(f2); |
111 | maxTurningRadius = math.max(maxTurningRadius, radius); |
112 | end |
113 | end |
114 | end |
115 | end |
116 | |
117 | if maxTurningRadius ~= 0 then |
118 | self.maxTurningRadius = maxTurningRadius; |
119 | end |
120 | |
121 | |
122 | self.wheelSteeringDuration = rotMax / rotSpeed; |
123 | self.maxRotation = rotMax; |
124 | |
125 | self.wheelSteeringDuration = Utils.sign(rotSpeed) * rotMax / rotSpeed; |
126 | |
127 | local i = 0; |
128 | entry.rotatingParts = {}; |
129 | while true do |
130 | local node = Utils.indexToObject(self.components, getXMLString(xmlFile, string.format("vehicle.articulatedAxis.rotatingPart(%d)#index", i))); |
131 | if node == nil then |
132 | break; |
133 | end; |
134 | local rotatingPart = {}; |
135 | rotatingPart.node = node; |
136 | local rx, ry, rz = getRotation(node); |
137 | rotatingPart.defRot = {rx, ry, rz}; |
138 | rotatingPart.posRot = Utils.getRadiansFromString(getXMLString(xmlFile, string.format("vehicle.articulatedAxis.rotatingPart(%d)#posRot", i)), 3); |
139 | rotatingPart.negRot = Utils.getRadiansFromString(getXMLString(xmlFile, string.format("vehicle.articulatedAxis.rotatingPart(%d)#negRot", i)), 3); |
140 | rotatingPart.negRotFactor = Utils.getNoNil(getXMLFloat(xmlFile, string.format("vehicle.articulatedAxis.rotatingPart(%d)#negRotFactor", i)), 1); |
141 | rotatingPart.posRotFactor = Utils.getNoNil(getXMLFloat(xmlFile, string.format("vehicle.articulatedAxis.rotatingPart(%d)#posRotFactor", i)), 1); |
142 | rotatingPart.invertSteeringAngle = Utils.getNoNil(getXMLBool(xmlFile, string.format("vehicle.articulatedAxis.rotatingPart(%d)#invertSteeringAngle", i)), false); |
143 | table.insert(entry.rotatingParts, rotatingPart); |
144 | i = i + 1; |
145 | end; |
146 | |
147 | self.articulatedAxis = entry; |
148 | end; |
149 | end; |
150 | |
151 | self.interpolatedRotatedTime = 0; |
152 | end; |
166 | function ArticulatedAxis:update(dt) |
167 | if self:getIsActive() then |
168 | if self.articulatedAxis ~= nil then |
169 | |
170 | local curRot = self.articulatedAxis.curRot; |
171 | if self.interpolatedRotatedTime < self.rotatedTime then |
172 | self.interpolatedRotatedTime = math.min(self.rotatedTime, self.interpolatedRotatedTime + math.abs(self.articulatedAxis.rotSpeed) * dt/500); |
173 | elseif self.interpolatedRotatedTime > self.rotatedTime then |
174 | self.interpolatedRotatedTime = math.max(self.rotatedTime, self.interpolatedRotatedTime - math.abs(self.articulatedAxis.rotSpeed) * dt/500); |
175 | end; |
176 | |
177 | --local steeringAngle = Utils.clamp(self.interpolatedRotatedTime * self.articulatedAxis.rotSpeed, self.articulatedAxis.rotMin, self.articulatedAxis.rotMax); |
178 | local steeringAngle = Utils.clamp(self.rotatedTime * self.articulatedAxis.rotSpeed, self.articulatedAxis.rotMin, self.articulatedAxis.rotMax); |
179 | |
180 | if self.updateArticulatedAxisRotation ~= nil then |
181 | steeringAngle = self:updateArticulatedAxisRotation(steeringAngle, dt); |
182 | end; |
183 | |
184 | if math.abs(steeringAngle - curRot) > 0.000001 then |
185 | if self.isServer then |
186 | local rotNode = Utils.getNoNil(self.articulatedAxis.rotNode, self.articulatedAxis.componentJoint.jointNode); |
187 | setRotation(rotNode, 0, steeringAngle, 0); |
188 | self:setComponentJointFrame(self.articulatedAxis.componentJoint, self.articulatedAxis.anchorActor) |
189 | self.articulatedAxis.curRot = steeringAngle; |
190 | end; |
191 | |
192 | if self.isClient then |
193 | local percent = 0; |
194 | if steeringAngle > 0 then |
195 | percent = steeringAngle / self.articulatedAxis.rotMax; |
196 | elseif steeringAngle < 0 then |
197 | percent = steeringAngle / self.articulatedAxis.rotMin; |
198 | end; |
199 | for _,rotPart in pairs(self.articulatedAxis.rotatingParts) do |
200 | local rx,ry,rz; |
201 | if (steeringAngle > 0 and not rotPart.invertSteeringAngle) or (steeringAngle < 0 and rotPart.invertSteeringAngle) then |
202 | rx,ry,rz = Utils.vector3ArrayLerp(rotPart.defRot, rotPart.posRot, math.min(1,percent*rotPart.posRotFactor)); |
203 | else |
204 | rx,ry,rz = Utils.vector3ArrayLerp(rotPart.defRot, rotPart.negRot, math.min(1,percent*rotPart.negRotFactor)); |
205 | end; |
206 | setRotation(rotPart.node, rx,ry,rz); |
207 | if self.setMovingToolDirty ~= nil then |
208 | self:setMovingToolDirty(rotPart.node); |
209 | end; |
210 | end; |
211 | end; |
212 | end; |
213 | |
214 | end; |
215 | end; |
216 | end; |