GE Lua Documentation

Press F to search!

dot

Definition


-- @/=[C]:-1
function dot(...)

Callers

@/lua/ge/extensions/core/quickAccess.lua
        local toWp = (marker.pos - vehPos):normalized()
        local dot = toWp:dot(vehFwd)
        -- If we have a previous dot product and this one is lower, we found our local maximum
@/lua/ge/map.lua
  for _, v in ipairs(currRoads) do
    local dirDot = math.abs(dir:dot((mapNodes[v[1]].pos - mapNodes[v[2]].pos):normalized()))
    if dirDot >= bestDot then -- best direction
            tmpVec:setSub2(position, n1Pos) -- node1ToPosVec
            local xnorm = min(1, max(0, edgeVec:dot(tmpVec) / (edgeVec:squaredLength() + 1e-30)))
            local key
  local vec1Sqlen, vec2Sqlen = vec1:squaredLength(), vec2:squaredLength()
  local dot12 = vec1:dot(vec2)
  local cos8sq = min(1, dot12 * dot12 / max(0, 1e-100 + vec1Sqlen * vec2Sqlen))
  local l1, l2 = v1:length(), v2:length()
  return 2 * math.acos(clamp(v1:dot(v2) / (l1 * l2), -1, 1)) / (l1 + l2)
end

    trajectory[i].radiusMult = (1 - nVec1:dot(nVec2) * 0.5) * normVecLen
    trajectory[i].halfWidth = trajectory[i].radius * trajectory[i].radiusMult
    if s.forceMag == 'angle' then
      nforce:setScaled(max(0, 1 - v1:dot(v2)) * s.forceMultiplier)
    elseif s.forceMag == 'curvature' then
    if not trajectory[i].fixed then
      local k = trajectory[i].normal:dot(trajectory[i].force)
      local forceDir = sign(k) * max(0, sign2(k * trajectory[i].prevFDir)) -- stop moving before switching direction (improves stability)
      --   -- trajectory[i].pos:setSub((p - trajectory[i].pos):normalized() * max(0, dist - min(dispFromCenter, min(0, halfWidth - s.distFromEdge)))) -- TODO: add distFromEdge limit here
      --   local dirSign = sign2((p - trajectory[i].pos):dot(trajectory[i].normalOrig))
      --   trajectory[i].pos:setSub(dirSign * trajectory[i].normalOrig * max(0, dist - min(dispFromCenter, min(0, halfWidth - s.distFromEdge))))
  local objVel = vec3(obj:getVelocity())
  local relativeSpeed = max(objVel:dot(relativePos / (relativePosLen + 1e-30)), 0)
  local ff = 0.5 * vecUp:dot(vec3(obj:getDirectionVectorUp())) -- frictionCoeff * Normal Force.
  local relativeSpeed = max(objVel:dot(relativePos / (relativePosLen + 1e-30)), 0)
  local ff = 0.5 * vecUp:dot(vec3(obj:getDirectionVectorUp())) -- frictionCoeff * Normal Force.
  local objDirVec = vec3(obj:getDirectionVector())
  local objDirVec = vec3(obj:getDirectionVector())
  local fw = vecUp:dot(sign(objVel:dot(objDirVec)) * objDirVec) -- road grade force
  local objDirVec = vec3(obj:getDirectionVector())
  local fw = vecUp:dot(sign(objVel:dot(objDirVec)) * objDirVec) -- road grade force
@/lua/vehicle/controller/playerController.lua

  local projectedVertical = (targetVector - targetVector:dot(normalLeft) * normalLeft):normalized()
  local projectedHorizontal = (targetVector - targetVector:dot(normalRight) * normalRight):normalized()
  local projectedVertical = (targetVector - targetVector:dot(normalLeft) * normalLeft):normalized()
  local projectedHorizontal = (targetVector - targetVector:dot(normalRight) * normalRight):normalized()

  local angleHorizontal = acos(min(max(vectorUp:dot(projectedVertical), -1), 1))
  local horizontalAngleSign = sign(normalLeft:dot(vectorUp:cross(projectedVertical)))
  local angleHorizontal = acos(min(max(vectorUp:dot(projectedVertical), -1), 1))
  local horizontalAngleSign = sign(normalLeft:dot(vectorUp:cross(projectedVertical)))
  local angleVertical = acos(min(max(vectorUp:dot(projectedHorizontal), -1), 1))
  local horizontalAngleSign = sign(normalLeft:dot(vectorUp:cross(projectedVertical)))
  local angleVertical = acos(min(max(vectorUp:dot(projectedHorizontal), -1), 1))
  local verticalAngleSign = sign(normalRight:dot(vectorUp:cross(projectedHorizontal)))
  local angleVertical = acos(min(max(vectorUp:dot(projectedHorizontal), -1), 1))
  local verticalAngleSign = sign(normalRight:dot(vectorUp:cross(projectedHorizontal)))
@/lua/ge/extensions/editor/slotTrafficEditor.lua
            while edgeProgress <= edgeLength do
              color = core_camera.getForward():dot(edgeDirVec) >= 0 and arrowBaseColor or arrowAltColor
              debugDrawer:drawSquarePrism((inNodePos + edgeProgress * edgeDirVec),
            local tempVec = focusPoint - n1.pos
            local dotProduct = linkVec:dot(tempVec)
            linkToSnapTo = selectedLink
@/lua/ge/extensions/editor/tech/roadArchitect/tunnelMesh.lua
        local dSq = tmp1:squaredDistanceToLineSegment(c1, c2)
        if (i < 5 and (tmp1 - cenS):dot(tanS) > 0.0) or (i > numRings - 5 and (tmp1 - cenE):dot(tanE) < 0.0) or (i > 4 and i < numRings - 4) then   -- At ends, use plane clipping.
          if dSq < rAvgSq then
        local dSq = tmp1:squaredDistanceToLineSegment(c1, c2)
        if (i < 5 and (tmp1 - cenS):dot(tanS) > 0.0) or (i > numRings - 5 and (tmp1 - cenE):dot(tanE) < 0.0) or (i > 4 and i < numRings - 4) then   -- At ends, use plane clipping.
          if dSq < rAvgSq then
        local dSq = tmp1:squaredDistanceToLineSegment(c1, c2)
        if (i < 5 and (tmp1 - cenS):dot(tanS) > 0.0) or (i > numRings - 5 and (tmp1 - cenE):dot(tanE) < 0.0) or (i > 4 and i < numRings - 4) then   -- At ends, use plane clipping.
          if dSq < rAvgSq then
        local dSq = tmp1:squaredDistanceToLineSegment(c1, c2)
        if (i < 5 and (tmp1 - cenS):dot(tanS) > 0.0) or (i > numRings - 5 and (tmp1 - cenE):dot(tanE) < 0.0) or (i > 4 and i < numRings - 4) then   -- At ends, use plane clipping.
          if dSq < rAvgSq then
        local dSq = tmp1:squaredDistanceToLineSegment(c1, c2)
        if (i < 5 and (tmp1 - cenS):dot(tanS) > 0.0) or (i > numRings - 5 and (tmp1 - cenE):dot(tanE) < 0.0) or (i > 4 and i < numRings - 4) then   -- At ends, use plane clipping.
          if dSq < rAvgSq then
        local dSq = tmp1:squaredDistanceToLineSegment(c1, c2)
        if (i < 5 and (tmp1 - cenS):dot(tanS) > 0.0) or (i > numRings - 5 and (tmp1 - cenE):dot(tanE) < 0.0) or (i > 4 and i < numRings - 4) then   -- At ends, use plane clipping.
          if dSq < rAvgSq then
        local dSq = tmp1:squaredDistanceToLineSegment(c1, c2)
        if (i < 5 and (tmp1 - cenS):dot(tanS) > 0.0) or (i > numRings - 5 and (tmp1 - cenE):dot(tanE) < 0.0) or (i > 4 and i < numRings - 4) then   -- At ends, use plane clipping.
          if dSq < rAvgSq then
        local dSq = tmp1:squaredDistanceToLineSegment(c1, c2)
        if (i < 5 and (tmp1 - cenS):dot(tanS) > 0.0) or (i > numRings - 5 and (tmp1 - cenE):dot(tanE) < 0.0) or (i > 4 and i < numRings - 4) then   -- At ends, use plane clipping.
          if dSq < rAvgSq then
@/lua/vehicle/extensions/dynamicVehicleData.lua
        local wheelVector = wheelNodePos - avgWheelPos --create a vector from our "center" to the wheel
        local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
        local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
        local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
        local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
@/lua/ge/extensions/gameplay/traffic/roles/standard.lua
    -- checks if target is visible, within distance, and in front of self
    if self:checkTargetVisible(targetId) and self.veh:getInteractiveDistance(targetVeh.pos, true) <= 3600 and self.veh.dirVec:dot(targetVeh.pos - self.veh.pos) > 0 then
      if self.driver.eventType ~= 'otherCollision' then
        if self.state == 'none' and driver.personality.bravery + driver.personality.patience >= 0.8
        and self.veh.driveVec:dot(targetVeh.pos - self.veh.pos) > 0 then
          actionType = 'crash'
@/lua/ge/extensions/gameplay/traffic/vehicle.lua
          collision.count = collision.count + 1
          collision.dot = self.driveVec:dot((veh.pos - self.pos):normalized())
          if self.enableTracking then self.tracking.collisions = self.tracking.collisions + 1 end
      end
    elseif dist > 2500 and self.speed > lowSpeed and self.driveVec:dot(self.pos - otherVeh.pos) > 0 then -- leaving site of collision
      collision.state = 'abandoned'
  local extraRadius = self.focus.dist + max(0, (1 - self.focus.dist / 5) * 80) -- larger extra radius if player is at a low speed
  extraRadius = extraRadius + max(0, self.focus.dirVec:dot(tempDirVec)) * 150 -- larger extra radius if focus direction to vehicle is straight ahead
    tempDirVec:setSub2(mapNodes[n2].pos, mapNodes[n1].pos)
    if (link.oneWay and link.inNode == n2) or (not link.oneWay and tempDirVec:dot(self.driveVec) < 0) then
      n1, n2 = n2, n1
    tempDirVec:normalize()
    self.tracking.alignment = self.driveVec:dot(tempDirVec) -- almost 1 if parallel to road
                  tempDirVec:normalize()
                  if self.driveVec:dot(tempDirVec) > 0 then
                    self.tracking.signalFault = instance.name
@/lua/ge/extensions/editor/gen/world.lua

	return vec3((p - orig):dot(un), (p - orig):dot(vn), 0)
end

	return vec3((p - orig):dot(un), (p - orig):dot(vn), 0)
end
	local t = ray.pos + d*ray.dir
	local pu = (t - p):dot(u:normalized())
	local pv = (t - p):dot(v:normalized())
	local pu = (t - p):dot(u:normalized())
	local pv = (t - p):dot(v:normalized())
					av[#av + 1] = p -- desc.pos
					auv[#auv + 1] = {u = p:dot(un), v = p:dot(vn)}
				end
					av[#av + 1] = p -- desc.pos
					auv[#auv + 1] = {u = p:dot(un), v = p:dot(vn)}
				end
					av[#av + 1] = p -- desc.pos
					auv[#auv + 1] = {u = p:dot(un), v = p:dot(vn)}
				end
					av[#av + 1] = p -- desc.pos
					auv[#auv + 1] = {u = p:dot(un), v = p:dot(vn)}
				end
			local p = base2world(adesc[id], ij)
			if w.u:cross(w.v):dot(p - core_camera.getPosition()) < 0 then
				pop = true
					av[#av+1] = b
					auv[#auv+1] = {u=(b-ref):dot(u), v=-(b-ref):dot(v)}
				end
					av[#av+1] = b
					auv[#auv+1] = {u=(b-ref):dot(u), v=-(b-ref):dot(v)}
				end
				end
				d.r = math.abs((d.av[1]-d.av[3]):dot((d.av[1]-d.av[4]):cross(vec3(0,0,1)):normalized()))
				local ctip = tip * d.r/7.
					av[#av+1] = b
					auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
				end
					av[#av+1] = b
					auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
				end
			--                        lo('?? match_wall:'..j..':'..k)
								local ds = (base[je]-f.base[j]):length()+dfpos:dot(un)
								if not we.arcext then
						av[#av+1] = b
						auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
					end
						av[#av+1] = b
						auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
					end
--						an = {f.awall[list.ind].u:cross(f.awall[list.ind].v)}
						if an[1]:dot(f.awall[list.ind].u:cross(f.awall[list.ind].v)) < 0 then
							M.flipSide(af,an)
			for i,uv in pairs(mesh.uvs) do
				uv.u = suvs[i].u + ds:dot(u)
				uv.v = suvs[i].v + ds:dot(v)
				uv.u = suvs[i].u + ds:dot(u)
				uv.v = suvs[i].v + ds:dot(v)
			end
--[[
		w.uv[1] = suv[n][1] - ds:dot(u)
		w.uv[3] = suv[n][3] - ds:dot(u)
		w.uv[1] = suv[n][1] - ds:dot(u)
		w.uv[3] = suv[n][3] - ds:dot(u)
		w.uv[2] = suv[n][2] - ds:dot(v)
		w.uv[3] = suv[n][3] - ds:dot(u)
		w.uv[2] = suv[n][2] - ds:dot(v)
		w.uv[4] = suv[n][4] - ds:dot(v)
		w.uv[2] = suv[n][2] - ds:dot(v)
		w.uv[4] = suv[n][4] - ds:dot(v)
--            U.dump(w.agrid, '?? for_AGRID:')
		end
--            lo('?? uv_MOVE:'..tostring(cds)..':'..tostring(cds:dot(u))..':'..tostring(suvs[1].u - cds:dot(u))..':'..tostring(suvs[1].v - cds:dot(v)))
--            lo('?? duvs:'..ij[1]..':'..ij[2]..' suvs:'..#suvs..' verts:'..#mesh.verts)
		end
--            lo('?? uv_MOVE:'..tostring(cds)..':'..tostring(cds:dot(u))..':'..tostring(suvs[1].u - cds:dot(u))..':'..tostring(suvs[1].v - cds:dot(v)))
--            lo('?? duvs:'..ij[1]..':'..ij[2]..' suvs:'..#suvs..' verts:'..#mesh.verts)
		end
--            lo('?? uv_MOVE:'..tostring(cds)..':'..tostring(cds:dot(u))..':'..tostring(suvs[1].u - cds:dot(u))..':'..tostring(suvs[1].v - cds:dot(v)))
--            lo('?? duvs:'..ij[1]..':'..ij[2]..' suvs:'..#suvs..' verts:'..#mesh.verts)
			auv[#auv+1] = {}
			auv[#auv].u = suvs[i].u + cds:dot(u)
			auv[#auv].v = suvs[i].v + cds:dot(v)
			auv[#auv].u = suvs[i].u + cds:dot(u)
			auv[#auv].v = suvs[i].v + cds:dot(v)
			w.uvref = {
			w.uvref = {
				cedit.cval['DragRef'][n][1]+cds:dot(u),
				cedit.cval['DragRef'][n][2]+cds:dot(v)
				cedit.cval['DragRef'][n][1]+cds:dot(u),
				cedit.cval['DragRef'][n][2]+cds:dot(v)
			} -- + {0,w.pos.z*(w.uvscale and w.uvscale[2] or 1)}
			if true or U._PRD == 0 then
				auv[#auv].v = suvs[i].v - ds:dot(v)
			else
			else
				auv[#auv].v = suvs[i].v + ds:dot(v)
			end
		for i = #ax*#ay-1,0,-1 do
			auv[#auv + 1] = {u = (av[#av - i] + orig):dot(u), v = -(av[#av - i] + orig):dot(v)}
		end
		for i = #ax*#ay-1,0,-1 do
			auv[#auv + 1] = {u = (av[#av - i] + orig):dot(u), v = -(av[#av - i] + orig):dot(v)}
		end
	if not desc.u or not desc.v then return end
	local x = v:dot(desc.u:normalized())/desc.u:length()
	local y = v:dot(desc.v:normalized())/desc.v:length()
	local x = v:dot(desc.u:normalized())/desc.u:length()
	local y = v:dot(desc.v:normalized())/desc.v:length()
--            lo('?? xy:'..x..':'..y)
	-- projections to view plane
	local up, vp = (u - u:dot(camDir)*camDir):normalized(), (v - v:dot(camDir)*camDir):normalized()
	-- edges projections in cam coords
	-- projections to view plane
	local up, vp = (u - u:dot(camDir)*camDir):normalized(), (v - v:dot(camDir)*camDir):normalized()
	-- edges projections in cam coords
	-- edges projections in cam coords
	local upcam = vec3(up:dot(cx), up:dot(cy), 0):normalized()
	local vpcam = vec3(vp:dot(cx), vp:dot(cy), 0):normalized()
	-- edges projections in cam coords
	local upcam = vec3(up:dot(cx), up:dot(cy), 0):normalized()
	local vpcam = vec3(vp:dot(cx), vp:dot(cy), 0):normalized()
	local upcam = vec3(up:dot(cx), up:dot(cy), 0):normalized()
	local vpcam = vec3(vp:dot(cx), vp:dot(cy), 0):normalized()
	local mcam = vec3(dwin[1], dwin[2], 0)
	local upcam = vec3(up:dot(cx), up:dot(cy), 0):normalized()
	local vpcam = vec3(vp:dot(cx), vp:dot(cy), 0):normalized()
	local mcam = vec3(dwin[1], dwin[2], 0)
--                        lo('?? uvm:'..tostring(upcam)..':'..tostring(vpcam)..':'..tostring(mcam))
--    return math.abs(mcam:dot(upcam)) > math.abs(mcam:dot(vpcam))
	local va, vn
--                        lo('?? uvm:'..tostring(upcam)..':'..tostring(vpcam)..':'..tostring(mcam))
--    return math.abs(mcam:dot(upcam)) > math.abs(mcam:dot(vpcam))
	local va, vn
	local isperp = false
	if math.abs(mcam:dot(upcam)) > math.abs(mcam:dot(vpcam)) then
--                        lo('?? ALONG')
	local isperp = false
	if math.abs(mcam:dot(upcam)) > math.abs(mcam:dot(vpcam)) then
--                        lo('?? ALONG')

	return dm:dot(va)*va, cmouse, isperp
--    return va, vn
				local function isIn(vert)
					local x,y,z = (vert - p):dot(un),(vert - p):dot(vn),(vert - p):dot(wn)
					return (0 < x and x < lx and 0 < y and y < ly and 0 < z and z < lz)
				local function isIn(vert)
					local x,y,z = (vert - p):dot(un),(vert - p):dot(vn),(vert - p):dot(wn)
					return (0 < x and x < lx and 0 < y and y < ly and 0 < z and z < lz)
				local function isIn(vert)
					local x,y,z = (vert - p):dot(un),(vert - p):dot(vn),(vert - p):dot(wn)
					return (0 < x and x < lx and 0 < y and y < ly and 0 < z and z < lz)
			if u then
				local db = (U.proj2D(rayCast.pos - base2world(desc, out.acorner[1].ij))):dot(u)
				for k,e in pairs(out.acorner) do
				if cedit.cval['DragPos'].inalong then
				db = cedit.cval['DragPos'].inalong*db:dot(cedit.cval['DragPos'].inalong)
					lo('?? ALONG:'..tostring(db))
				lo('?? Z_dragging:'..tostring(ds)) --..':'..tostring(cameraMouseRayCast(true).object.name), true)
			adesc[cedit.mesh].pos = cedit.cval['DragPos'].pos + ds:dot(vec3(0,0,1))*vec3(0,0,1)
			houseUp(adesc[cedit.mesh], cedit.mesh, true)
			local c2 = cameraMouseRayCast(true).pos --rayCast.pos
			local vz = (c2-c1):dot(vec3(0,0,1))*vec3(0,0,1)
			local vh = c2 - (c1 + vz)
			local vz = dirface:cross(vx)
			local w = math.min(math.abs(dr:dot(vx)),math.abs(dr:dot(vz)))*dirface:normalized()
			local vz = dirface:cross(vx)
			local w = math.min(math.abs(dr:dot(vx)),math.abs(dr:dot(vz)))*dirface:normalized()
	--        local vz = dirobj:cross(vx)
	--        local w = math.min(math.abs(dr:dot(vx)),math.abs(dr:dot(vz)))*dirobj:normalized()
			local frame = {cedit.cval['Drag_Z'].dragstart - w/2, dr:dot(vx)*vx, dr:dot(vz)*vz, w}
	--        local vz = dirobj:cross(vx)
	--        local w = math.min(math.abs(dr:dot(vx)),math.abs(dr:dot(vz)))*dirobj:normalized()
			local frame = {cedit.cval['Drag_Z'].dragstart - w/2, dr:dot(vx)*vx, dr:dot(vz)*vz, w}
	--        local w = math.min(math.abs(dr:dot(vx)),math.abs(dr:dot(vz)))*dirobj:normalized()
			local frame = {cedit.cval['Drag_Z'].dragstart - w/2, dr:dot(vx)*vx, dr:dot(vz)*vz, w}
	--                lo('?? for_frame:'..tostring(dirface)..':'..tostring(vx))
	--        local w = math.min(math.abs(dr:dot(vx)),math.abs(dr:dot(vz)))*dirobj:normalized()
			local frame = {cedit.cval['Drag_Z'].dragstart - w/2, dr:dot(vx)*vx, dr:dot(vz)*vz, w}
	--                lo('?? for_frame:'..tostring(dirface)..':'..tostring(vx))
--                    if math.abs(ang) < small_ang or math.abs(ang-math.pi) < small_ang then
						local ds = cedit.cval['DragRot'].dir*dpos:dot(cedit.cval['DragRot'].dir)
                lo('?? for_ds:'..tostring(ds)..':'..tostring(dpos),true)
			local cw = adesc[cedit.mesh].afloor[cij[1]].awall[cij[2]]
			local dir = (math.abs(dm:dot(cw.v:normalized())) > math.abs(dm:dot(cw.u:normalized()))) and 'z' or 'x'
--            local dir = (math.abs(ds:dot(cw.v:normalized())) > math.abs(ds:dot(cw.u:normalized()))) and 'z' or 'x'
			local cw = adesc[cedit.mesh].afloor[cij[1]].awall[cij[2]]
			local dir = (math.abs(dm:dot(cw.v:normalized())) > math.abs(dm:dot(cw.u:normalized()))) and 'z' or 'x'
--            local dir = (math.abs(ds:dot(cw.v:normalized())) > math.abs(ds:dot(cw.u:normalized()))) and 'z' or 'x'
			local dir = (math.abs(dm:dot(cw.v:normalized())) > math.abs(dm:dot(cw.u:normalized()))) and 'z' or 'x'
--            local dir = (math.abs(ds:dot(cw.v:normalized())) > math.abs(ds:dot(cw.u:normalized()))) and 'z' or 'x'
			forBuilding(adesc[cedit.mesh], function(w, ij)
			local dir = (math.abs(dm:dot(cw.v:normalized())) > math.abs(dm:dot(cw.u:normalized()))) and 'z' or 'x'
--            local dir = (math.abs(ds:dot(cw.v:normalized())) > math.abs(ds:dot(cw.u:normalized()))) and 'z' or 'x'
			forBuilding(adesc[cedit.mesh], function(w, ij)
				if dir == 'z' then
					w.winbot = cedit.cval['DragPos'][U.stamp(ij)].bot + ds:dot(cw.v:normalized())
				else
				else
					w.winleft = cedit.cval['DragPos'][U.stamp(ij)].left + ds:dot(cw.u:normalized())
					if w.winleft < 0 then w.winleft = small_dist end
				rc[#rc+1] = world2wall(out.ahole[i], cw)
--                rc[#rc+1] = vec3((out.ahole[i] - orig):dot(un), (out.ahole[i] - orig):dot(vn), 0)
			end
				rc[#rc+1] = world2wall(out.ahole[i], cw)
--                rc[#rc+1] = vec3((out.ahole[i] - orig):dot(un), (out.ahole[i] - orig):dot(vn), 0)
			end
								local v = base[i] - lmouse
								local ds = v - dir*dir:dot(v)
	--                                lo('?? HIT:'..i..':'..tostring(base[i])..':'..tostring(ds))
								local v = mbase[i] - lmouse
								local ds = v - dir*dir:dot(v)
	--                                lo('?? HIT:'..i..':'..tostring(base[i])..':'..tostring(ds))
				local un,vn = u:normalized(),v:normalized()
				local pu = (cp - p):dot(un)
				local pv = (cp - p):dot(vn)
				local pu = (cp - p):dot(un)
				local pv = (cp - p):dot(vn)
				if dir == 1 then
					dir = dir:normalized()
					local u = (t - cp):dot(dir)
--                       local un = dir:normalized()
					local d = (cp - p):dot(dir)
					local line = line2rect(t, base2world(desc, ij), w.u, w.v,
						local un = w.u:normalized()
						local d = (cp - p):dot(un)
						if (d + u) < 0 or (d + u) >= w.u:length() then return end
--                                        lo('?? edge_CLOSE:')
									if w.u:cross(w.v):dot(ray.dir) < 0 then
										ishit = {ij={ij[1],U.mod(ij[2]+k-1,#floor.base)}, line={p, p+vec3(0,0,floor.h)}}
	--[[
										if floor.awall[j].u:cross(vec3(0,0,1)):dot(ray.dir) < 0 then
											out.aedge.e[#out.aedge.e+1] =
								for _,j in pairs(r) do
									local prj = (U.mod(j,base) - base[cij[2]]):dot(u)
									if prj < pmi then
									else
										prj = (U.mod(j+1,base) - base[cij[2]]):dot(u)
										if prj > pma then
	--                        ma = U.mod(ma+1,#base)
							local p = (U.mod(mi,base) - base[cij[2]] + U.mod(ma,base) - base[cij[2]]):dot(u)
							local jp = cij[2]
							for k,j in pairs(aside[cij[1]]) do
								local p1,p2 = (base[j] - base[cij[2]]):dot(u),(U.mod(j+1,base) - base[cij[2]]):dot(u)
								if p1 <= p and p <= p2 then
							for k,j in pairs(aside[cij[1]]) do
								local p1,p2 = (base[j] - base[cij[2]]):dot(u),(U.mod(j+1,base) - base[cij[2]]):dot(u)
								if p1 <= p and p <= p2 then
	--                            lo('?? for_JP:'..jp)
							local pm = base2world(desc,cij, base[jp] + u*(base[cij[2]]-base[jp]):dot(u) + u*p/2)
							out.middle = {line = {pm, pm + vec3(0,0,desc.afloor[cij[1]].h)}, ij = cij}
											if j ~= ij[2] then
	--                                        if ain.u:dot(fsrc.awall[jmi].u) < 0 then
	--                                                lo('?? shifting:'..j, true)
			for j,_ in pairs(base) do
				desc.afloor[ij[1] ].base[j] = base[j] + u*(base[j]-center):dot(u)*(val-1)
--                base[j] = center + (base[j]-center)*val
			for j,_ in pairs(base) do
				desc.afloor[ij[1]].base[j] = base[j] + u*(base[j]-center):dot(u)*(val-1)
--                base[j] = center + (base[j]-center)*val
			for j,_ in pairs(base) do
				desc.afloor[ij[1]].base[j] = base[j] + u*(base[j]-center):dot(u)*(val-1)
--                base[j] = center + (base[j]-center)*val
@/lua/ge/extensions/editor/buildingEditor.lua
		-- projections
		local pi, pip = (p - ni):dot(nip - ni), (p - nip):dot(nip - ni)
		local shadow = math.abs(pi) + math.abs(pip)
		-- projections
		local pi, pip = (p - ni):dot(nip - ni), (p - nip):dot(nip - ni)
		local shadow = math.abs(pi) + math.abs(pip)
U.vang = function(u, v)
	return math.acos(u:dot(v)/u:length()/v:length())
end
			--?? massCenter role
			if (anode[path[i]].pos - massCenter/#anode):dot(vn) < 0 then
				vn = -vn
@/lua/ge/extensions/gameplay/drag/general.lua

      local frontness = forward:dot(wheelNodePos - center)

      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      wheelsByFrontness[frontness] = wheelsByFrontness[frontness] or {}

      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      wheelsByFrontness[frontness] = wheelsByFrontness[frontness] or {}

      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      wheelsByFrontness[frontness] = wheelsByFrontness[frontness] or {}

    local posL = vec3(frontLeft:dot(x), frontLeft:dot(y), frontLeft:dot(z))
    local posR = vec3(frontRight:dot(x), frontRight:dot(y), frontRight:dot(z))

    local posL = vec3(frontLeft:dot(x), frontLeft:dot(y), frontLeft:dot(z))
    local posR = vec3(frontRight:dot(x), frontRight:dot(y), frontRight:dot(z))

    local posL = vec3(frontLeft:dot(x), frontLeft:dot(y), frontLeft:dot(z))
    local posR = vec3(frontRight:dot(x), frontRight:dot(y), frontRight:dot(z))
    local posL = vec3(frontLeft:dot(x), frontLeft:dot(y), frontLeft:dot(z))
    local posR = vec3(frontRight:dot(x), frontRight:dot(y), frontRight:dot(z))
    maxFrontness = "oobb"
    local posL = vec3(frontLeft:dot(x), frontLeft:dot(y), frontLeft:dot(z))
    local posR = vec3(frontRight:dot(x), frontRight:dot(y), frontRight:dot(z))
    maxFrontness = "oobb"
    local posL = vec3(frontLeft:dot(x), frontLeft:dot(y), frontLeft:dot(z))
    local posR = vec3(frontRight:dot(x), frontRight:dot(y), frontRight:dot(z))
    maxFrontness = "oobb"
@/lua/vehicle/extensions/tech/platooning.lua
-- Projects a vector onto another vector.
local function project(a, b) return (a:dot(b) / b:dot(b)) * b end
-- Projects a vector onto another vector.
local function project(a, b) return (a:dot(b) / b:dot(b)) * b end
      local distantPoint = pos + (1e12 * fwd)                                                                     -- A point on the player vehicle forward vector, far in the distance.
      -- if fwd:dot(fwdB) > 0.0 and (distantPoint - pos):lenSquared() > (distantPoint - posB):lenSquared() then      -- Test that other vehicle is in front hemisphere and has same dir. --edit for 360 comment it
      local distToPlayerVehicleSq = (pos - posB):lenSquared()
@/lua/ge/extensions/editor/tech/roadArchitect/link.lua
            class = '2W -> 2W Perfect. Y-Junction'
            if abs(vT:dot(vJ)) < 0.4 then
              bestType = 'T'
                vJ:normalize()
                if abs(vT:dot(vJ)) < 0.4 then
                  bestType = 'T'
                vJ:normalize()
                if abs(vT:dot(vJ)) < 0.4 then
                  bestType = 'T'
@/lua/vehicle/controller/drivingDynamics/actuators/activeDiffBias.lua
    local wheelVector = avgWheelPosition - avgDiffPosition --create a vector from our "center" to the wheel
    local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
    local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
    local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
    local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
    --print(string.format("Side: %d, Name: %q, Front/Back: %.2f, LeftRight: %.2f", wheelSideIndex, relevantWheels[wheelSideIndex].wheels[1].name, dotForward, dotLeft))
@/lua/ge/spawn.lua
  -- Turn it around if upside down
  if vehBB:getAxis(2):dot(vec3(0, 0, 1)) < 0 then
    local mat = vehBB:getMatrix()
  -- Turn it around if upside down
  if boundingBox:getAxis(2):dot(vec3(0, 0, 1)) < 0 then
    local mat = boundingBox:getMatrix()
            if routePlanner.path and routePlanner.path[2] then
              if drivingDir:dot(routePlanner.path[2].pos - n1.pos) < 0 then
                drivingDir = -drivingDir
                local routeDir = core_groundMarkers.routePlanner.path[2].pos - getPlayerVehicle(0):getPosition()
                roadSide = drivingDir:dot(routeDir) > 0 and legalSide or -legalSide
              end
            if not roadSide then
              roadSide = perpendicular:dot(recoveryPoint.pos - n1.pos) > 0 and 1 or -1
            end
          if segLenSq > 0 then
            scalarProjection = clamp(segmentDir:dot((recoveryPoint.pos - n1.pos)) / segLenSq, 0, 1)
          end
@/lua/ge/extensions/editor/gen/region.lua
	end
	return (p - corner):dot(v:normalized())
end
		if ang > math.pi/2 then
			dstart = (pc - anode[sto.fr]):dot(forStem(sto,0))
			local wfr = editor.getNodes(scenetree.findObjectById(adec[sfr.rd].id))[sfr.to].width
--                        out.agreen = {p}
					lo('?? sPush:'..forStem(side, 1):dot(vlist[2]-vlist[1]))
				if parity < 0 and not tonext and forStem(side, 1):dot(vlist[2]-vlist[1]) < 0 then
					lo('?? sPush:'..forStem(side, 1):dot(vlist[2]-vlist[1]))
				if parity < 0 and not tonext and forStem(side, 1):dot(vlist[2]-vlist[1]) < 0 then
					-- goto next branch

	--                dir = (prd - ppre):dot(v) > 0 and 1 or -1
	--                    U.dump(side, '?? for_CORNER:'..tostring(ni)..':'..side.dir..':'..s)
				local ishiftpre = (#basepre - 4)/2
				if valong:dot(basepre[2+ishiftpre] - basepre[1+ishiftpre]) > 0 then
					local shift = (pbound - base[1+ishift]):dot(valong)
				if valong:dot(basepre[2+ishiftpre] - basepre[1+ishiftpre]) > 0 then
					local shift = (pbound - base[1+ishift]):dot(valong)
					--                    out.ayel = {base[1],base[2],base[3],base[4]}
				margin + anobj[side.fr].width/2 + mm_depth[2])
--                    U.dump(sideprev, '?? sideprev:'..(p - anode[side.fr]):dot(forStem(side, 0)))
--                    out.ayel = {p}
--                if true then return end
			if p and (p - anode[side.fr]):dot(forStem(side, 0)) > 0 then
				local prd,ni = p2side(p, side, side.fr)
@/lua/ge/extensions/editor/gen/mesh.lua
	for _,b in pairs(base) do
		auv[#auv+1] = {u = (b-ref):dot(u), v = (b-ref):dot(v)}
	end
	for _,b in pairs(base) do
		auv[#auv+1] = {u = (b-ref):dot(u), v = (b-ref):dot(v)}
	end
		local b = U.mod(i,base)
		local uv = refuv + scale[1]*uvu*(b-ref):dot(u) + scale[2]*uvv*(b-ref):dot(v)
		auv[#auv+1] = {u = uv.x, v = uv.y}
		local b = U.mod(i,base)
		local uv = refuv + scale[1]*uvu*(b-ref):dot(u) + scale[2]*uvv*(b-ref):dot(v)
		auv[#auv+1] = {u = uv.x, v = uv.y}
		auv[#auv+1] = {u = uv.x, v = uv.y}
--        auv[#auv+1] = {u = (b-ref):dot(u), v = (b-ref):dot(v)}
	end
		auv[#auv+1] = {u = uv.x, v = uv.y}
--        auv[#auv+1] = {u = (b-ref):dot(u), v = (b-ref):dot(v)}
	end

		auv[#auv + 1] = {u = (av[#av-3] - orig):dot(ref[1]), v = (av[#av-3] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-2] - orig):dot(ref[1]), v = (av[#av-2] - orig):dot(ref[2])}

		auv[#auv + 1] = {u = (av[#av-3] - orig):dot(ref[1]), v = (av[#av-3] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-2] - orig):dot(ref[1]), v = (av[#av-2] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-3] - orig):dot(ref[1]), v = (av[#av-3] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-2] - orig):dot(ref[1]), v = (av[#av-2] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-1] - orig):dot(ref[1]), v = (av[#av-1] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-3] - orig):dot(ref[1]), v = (av[#av-3] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-2] - orig):dot(ref[1]), v = (av[#av-2] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-1] - orig):dot(ref[1]), v = (av[#av-1] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-2] - orig):dot(ref[1]), v = (av[#av-2] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-1] - orig):dot(ref[1]), v = (av[#av-1] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av] - orig):dot(ref[1]), v = (av[#av] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-2] - orig):dot(ref[1]), v = (av[#av-2] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-1] - orig):dot(ref[1]), v = (av[#av-1] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av] - orig):dot(ref[1]), v = (av[#av] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av-1] - orig):dot(ref[1]), v = (av[#av-1] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av] - orig):dot(ref[1]), v = (av[#av] - orig):dot(ref[2])}
	end
		auv[#auv + 1] = {u = (av[#av-1] - orig):dot(ref[1]), v = (av[#av-1] - orig):dot(ref[2])}
		auv[#auv + 1] = {u = (av[#av] - orig):dot(ref[1]), v = (av[#av] - orig):dot(ref[2])}
	end

		auv[#auv + 1] = {u = (av[#av] - orig):dot(ref[1]), v = (av[#av] - orig):dot(ref[2])}
	end

		auv[#auv + 1] = {u = (av[#av] - orig):dot(ref[1]), v = (av[#av] - orig):dot(ref[2])}
	end

	auv[#auv + 1] = {u = (a - orig):dot(ref[1]), v = (a - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (b - orig):dot(ref[1]), v = (b - orig):dot(ref[2])}

	auv[#auv + 1] = {u = (a - orig):dot(ref[1]), v = (a - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (b - orig):dot(ref[1]), v = (b - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (a - orig):dot(ref[1]), v = (a - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (b - orig):dot(ref[1]), v = (b - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (c - orig):dot(ref[1]), v = (c - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (a - orig):dot(ref[1]), v = (a - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (b - orig):dot(ref[1]), v = (b - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (c - orig):dot(ref[1]), v = (c - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (b - orig):dot(ref[1]), v = (b - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (c - orig):dot(ref[1]), v = (c - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (b - orig):dot(ref[1]), v = (b - orig):dot(ref[2])}
	auv[#auv + 1] = {u = (c - orig):dot(ref[1]), v = (c - orig):dot(ref[2])}
	for i = #ax*#ay-1,0,-1 do
		auv[#auv + 1] = {u = (av[#av - i] + orig):dot(u), v = -(av[#av - i] + orig):dot(v)}
	end
	for i = #ax*#ay-1,0,-1 do
		auv[#auv + 1] = {u = (av[#av - i] + orig):dot(u), v = -(av[#av - i] + orig):dot(v)}
	end
	for j,p in pairs(aloop[1]) do
		local proj = (p-ref):dot(u)
		if proj < mi then
	-- slice
	local w = (pma-pmi):dot(u)
--	step = w/math.floor(w/step+0.5)
--					lo('?? for_cross:'..i..':'..stamp..':'..tostring(p)..':'..tostring(s))
--				across[stamp] = (p-l[1]):dot(dir)
				across[#across+1] = {stamp, (p-l[1]):dot(dir)}
--				across[stamp] = (p-l[1]):dot(dir)
				across[#across+1] = {stamp, (p-l[1]):dot(dir)}
			end
					local pc,s = U.line2seg(p,av[iv].p,av[e[1]].p,av[e[2]].p,0.00001)
--							U.dump(e,'?? for_dtep:'..k..':'..tostring(p)..'>'..tostring(pc)..':'..tostring(s)..':'..iv) --..':'..tostring((pc-p):dot(p-av[iv].p)))
--						if i == 12 then -- and k == 5 then
--						if i == 12 then -- and k == 5 then
--							U.dump(e,'?? for_12:'..k..':'..tostring(p)..'>'..tostring(pc)..':'..tostring(s)..':'..iv) --..':'..tostring((pc-p):dot(p-av[iv].p)))
--						end
--						end
					if pc and (pc-p):dot(p-av[iv].p) > 0 then
						local d = (p-pc):length()
--                            imi = i
						elseif v:dot(p-c) < 0 then    -- intersection is in v-direction
--                            d = (c - p):length()
		for i=2,#rc-1 do
			if (v4e[rc[i+1]].p - v4e[rc[i]].p):dot(v4e[rc[i]].p - v4e[rc[i-1]].p) < 0.00001 then
--                lo('?? first_in_rc:'..k..':'..i)
		for i=#rc-1,2,-1 do
			if (v4e[rc[i+1]].p - v4e[rc[i]].p):dot(v4e[rc[i]].p - v4e[rc[i-1]].p) > 0.00001 then
				-- remove colinear
		end
		if (v4e[rc[1]].p - v4e[rc[#rc]].p):dot(v4e[rc[#rc]].p - v4e[rc[#rc-1]].p) > 0.00001 then
			-- remove colinear
				end
			if #list == 1 and (list[1]-c):dot(ap[j+1]-ap[j])>0 then
--							lo('?? is_CROSS:'..tostring(c)..':'..j..':'..(istep-1)..':'..tostring(list[1]))
		d = (v-pmi).x
--			d = u:dot(v-pmi)
		av[#av+1] = {d=d,ind=i}
--						lo('?? for_AB:'..k..'>'.._..':'..tostring(p)..':'..tostring(f.p)..':'..tostring(f.vn))
			d = math.abs((a.m.verts[p]-f.p):dot(f.vn))
--				if d == 0 then
				for t=1,3 do
					local ang = ((f.av[t<3 and t+1 or 1]-f.av[t]):normalized()):cross(a.m.verts[p]-f.av[t]):dot(f.vn)
					if ang < -0.005 then
--						lo('?? for_AB:'..tostring(p)..':'..tostring(f.p)..':'..tostring(f.vn))
					d = math.abs((m.verts[p]-f.p):dot(f.vn))
					if d < dmi then
						for t=1,3 do
							local ang = ((f.av[t<3 and t+1 or 1]-f.av[t]):normalized()):cross(m.verts[p]-f.av[t]):dot(f.vn)
--[[
					for t=1,3 do
						local ang = ((fmi.av[t<3 and t+1 or 1]-fmi.av[t]):normalized()):cross(m.verts[p]-fmi.av[t]):dot(fmi.vn)
							if dbg and p == 20 then
@/lua/ge/extensions/editor/trafficSignalsEditor.lua
        if not other.intersectionId and instance.sequenceId == other.sequenceId then -- sequence ids must match
          if other.pos:squaredDistance(refPos) <= 1600 and other.dir:dot(refPos - other.pos) > 0 then
            table.insert(idList, other.id)
          local dir2 = obj:getTransform():getForward()
          if dir1:dot(dir2) >= 0.93 then -- roughly within 20 degrees
            table.insert(validIds, obj:getId())
@/lua/ge/extensions/gameplay/taxi.lua
        local toWp = (marker.pos - vehPos):normalized()
        local dot = toWp:dot(vehFwd)
        -- If we have a previous dot product and this one is lower, we found our local maximum
@/lua/ge/extensions/editor/tech/sensorConfiguration/utilities.lua
  local right = fwd:cross(up)
  return vec3(posVS:dot(fwd), posVS:dot(right), posVS:dot(up))
end
  local right = fwd:cross(up)
  return vec3(posVS:dot(fwd), posVS:dot(right), posVS:dot(up))
end
  local right = fwd:cross(up)
  return vec3(posVS:dot(fwd), posVS:dot(right), posVS:dot(up))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirVS), right:dot(dirVS), up:dot(dirVS)), vec3(fwd:dot(upVS), right:dot(upVS), up:dot(upVS))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirVS), right:dot(dirVS), up:dot(dirVS)), vec3(fwd:dot(upVS), right:dot(upVS), up:dot(upVS))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirVS), right:dot(dirVS), up:dot(dirVS)), vec3(fwd:dot(upVS), right:dot(upVS), up:dot(upVS))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirVS), right:dot(dirVS), up:dot(dirVS)), vec3(fwd:dot(upVS), right:dot(upVS), up:dot(upVS))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirVS), right:dot(dirVS), up:dot(dirVS)), vec3(fwd:dot(upVS), right:dot(upVS), up:dot(upVS))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirVS), right:dot(dirVS), up:dot(dirVS)), vec3(fwd:dot(upVS), right:dot(upVS), up:dot(upVS))
end
@/lua/ge/extensions/util/vehicleRopeDebug.lua
  local oc = rayOrigin - sphereCenter
  local a = rayDir:dot(rayDir)
  local b = 2.0 * oc:dot(rayDir)
  local a = rayDir:dot(rayDir)
  local b = 2.0 * oc:dot(rayDir)
  local c = oc:dot(oc) - sphereRadius * sphereRadius
  local b = 2.0 * oc:dot(rayDir)
  local c = oc:dot(oc) - sphereRadius * sphereRadius
  local discriminant = b * b - 4 * a * c
  -- Intersect ray with drag plane
  local denom = dragPlaneNormal:dot(rayDir)
  if math.abs(denom) > 0.0001 then
  if math.abs(denom) > 0.0001 then
    local t = -(dragPlaneNormal:dot(rayOrigin) - dragPlaneDist) / denom
    if t > 0 then
@/lua/ge/extensions/core/cameraModes/path.lua
  for i = path.rotFixId, self.ctrlPoint - 2 do
    if markers[i].rot:dot(markers[i + 1].rot) < 0 then
      markers[i + 1].rot = -markers[i + 1].rot

  if r1:dot(r2) < 0 then r2 = -r2 end
  if r2:dot(r3) < 0 then r3 = -r3 end
  if r1:dot(r2) < 0 then r2 = -r2 end
  if r2:dot(r3) < 0 then r3 = -r3 end
  if r3:dot(r4) < 0 then r4 = -r4 end
  if r2:dot(r3) < 0 then r3 = -r3 end
  if r3:dot(r4) < 0 then r4 = -r4 end
  self.lastFrameR2 = r2
@/lua/ge/extensions/tech/techCore.lua
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
@/lua/ge/extensions/gameplay/rally/notebook/pacenoteGenerator.lua
  local bsql = d2:squaredLength()
  local adotb = d1:dot(d2)
@/lua/vehicle/controller/drivingDynamics/sensors/sensorHub.lua
  M.directionVectorLeft = M.directionVectorUp:cross(M.directionVector)
  M.vX = M.worldVelocity:dot(M.directionVector)
  M.vY = M.worldVelocity:dot(M.directionVectorLeft)
  M.vX = M.worldVelocity:dot(M.directionVector)
  M.vY = M.worldVelocity:dot(M.directionVectorLeft)
  -------
@/lua/common/graphpath.lua
          tmpVec:setSub2(positions[child], p1) -- edgeVec
          local xnorm = min(1, max(0, tmpVec:dot(nodeToTargetVec) / (tmpVec:squaredLength() + 1e-30)))
          if xnorm > 0 and xnorm < 1 then
          tmpVec:setSub2(positions[child], nodePos)
          local xnorm = tmpVec:dot(nodeToTargetVec) / (tmpVec:squaredLength() + 1e-30)
          if xnorm > 0 and xnorm < 1 then
            nextSegDir:setSub2(positions[child], nodePos); nextSegDir.z = 0; nextSegDir:normalize()
            local cDirCoef = 0.5 * max(0, 1 + nextSegDir:dot(curSegDir))
            local t = square(square(min(1, graph[node][child].drivability / inDrivability))) * square(cDirCoef)
        nextSegDir:setSub2(positions[child], positions[node]); nextSegDir.z = 0; nextSegDir:normalize()
        local t = square(min(1, graph[node][child].drivability / inDrivability)) * square(0.5 * max(0, 1 + nextSegDir:dot(curSegDir)))
        local outFwdFlow, outBackFlow = self:getFlows(node, child)
              nextSegDir:setSub2(positions[child], nodePos); nextSegDir.z = 0; nextSegDir:normalize()
              local t = square(min(1, graph[node][child].drivability / inDrivability)) * square(0.5 * max(0, 1 + nextSegDir:dot(curSegDir)))
              local outFwdFlow, outBackFlow = self:getFlows(node, child)
              nextSegDir:setSub2(positions[child], nodePos); nextSegDir.z = 0; nextSegDir:normalize()
              local t = square(min(1, graph[node][child].drivability / inDrivability)) * square(0.5 * max(0, 1 + nextSegDir:dot(curSegDir)))
              local outFwdFlow, outBackFlow = self:getFlows(node, child)
    local posNodeDist = nodeStartVec:squaredLength()
    local posNodeScore = dir and nodeStartVec:dot(dir) or posNodeDist
  local meToTarget = (targetPos + targetVel:normalized()) - mePos -- target point is slightly ahead of original pos
  local meDotTarget = meToTarget:dot(targetVel)
  local wpAhead = meToTarget:dot(wp1pos - mePos) > meToTarget:dot(wp2pos - mePos) and nodeBehind or nodeAhead -- best wp that goes to target wp
  local meDotTarget = meToTarget:dot(targetVel)
  local wpAhead = meToTarget:dot(wp1pos - mePos) > meToTarget:dot(wp2pos - mePos) and nodeBehind or nodeAhead -- best wp that goes to target wp
  local twpAhead = wpAhead == targetNodeBehind and targetNodeBehind or targetNodeAhead -- check if best wp matches target wp
  local meDotTarget = meToTarget:dot(targetVel)
  local wpAhead = meToTarget:dot(wp1pos - mePos) > meToTarget:dot(wp2pos - mePos) and nodeBehind or nodeAhead -- best wp that goes to target wp
  local twpAhead = wpAhead == targetNodeBehind and targetNodeBehind or targetNodeAhead -- check if best wp matches target wp

  if meVel:squaredLength() >= 9 and meDotTarget >= 9 and meVel:dot(graphpos[path[1]] - mePos) < 0 then -- simply pick waypoint ahead if driving same as player
    path = {nodeAhead}
      local vis = visited[child] or 1
      local posNodeScore = vis * fleeDirScoreCoeff[link.oneWay and link.inNode == child] * driveability * (3 + pathVec:dot(prevDir) / max(pathVecLen, 1)) * max(0, 3 + (chasePos - childPos):normalized():dot(prevDir) * chaseCoef)
      visited[child] = vis * 0.2
      local vis = visited[child] or 1
      local posNodeScore = vis * fleeDirScoreCoeff[link.oneWay and link.inNode == child] * driveability * (3 + pathVec:dot(prevDir) / max(pathVecLen, 1)) * max(0, 3 + (chasePos - childPos):normalized():dot(prevDir) * chaseCoef)
      visited[child] = vis * 0.2
      local vis = visited[child] or 1
      local posNodeScore = vis * dirScoreCoeff[link.oneWay and link.inNode == child] * link.drivability * (2 + pathVec:dot(prevDir) / max(pathVecLen, 1))
      visited[child] = vis * 0.2

    if maxVec:dot(prevDir) <= 0 then
      ropePos = curPos
            local childCurrCost = minCost[child]
            local penalty = 1 + 10 * square(max(0, edgeDirVec:dot((positions[child] - nodePos):normalized()) - 0.2))
            local childNewCost = cost + penalty * data.len * dirCoeff[data.oneWay and data.inNode == child] * ((node == nodeAhead and child == nodeBehind) and 1e4 or 1)
@/lua/ge/extensions/gameplay/rally/transcripts/entry.lua
    if res.markers[i] then
      if res.markers[i].rot:dot(res.markers[i - 1].rot) < 0 then
        res.markers[i].rot = -res.markers[i].rot
@/lua/ge/extensions/editor/assemblySpline/import.lua
      -- Check if binormals are aligned (dot product > 0).
      if expectedBinormal:dot(actualBinormal) > 0 then
        alignmentCount = alignmentCount + 1
@/lua/ge/extensions/gameplay/drag/utils.lua
  end
  return racer._wheelDistances[racer.frontWheelId]:dot(dragData.strip.lanes[racer.lane].stageToEndNormalized)
end

  local dotProduct = racer.vehDirectionVector:dot(lineTransform.y)
  local tolerance = 0.70
    end
    processTreeLights(racer, k, distVec:dot(stageToEndNorm))
  end
@/lua/ge/extensions/gameplay/speedTraps.lua

      if triggerDir:dot(vehVelocity) > 0 then
@/lua/vehicle/extensions/chassisData.lua
    local wheelVector = wheelNodePos - avgWheelPos --create a vector from our "center" to the wheel
    local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
    local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
    local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
    local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
@/lua/ge/extensions/core/groundMarkerArrows.lua
    if getPlayerVehicle(0) then
      local wrongDirection = getPlayerVehicle(0):getVelocity():dot(path[2].pos - getPlayerVehicle(0):getPosition()) < 0
      if wrongDirection then
@/lua/ge/extensions/editor/roadSpline/import.lua
      perpDir:set(-segmentDir.y, segmentDir.x, 0.0)
      local sign = toNode:dot(perpDir) >= 0.0 and -1 or 1
      refTangent:normalize() -- Reference spline tangent at the closest point.
      if layerTangent:dot(refTangent) < 0 then -- Vote on flip (negative dot product means opposite directions).
        flipVotes = flipVotes + 1
@/lua/ge/extensions/career/modules/delivery/precisionParking.lua
  -- Calculate alignment (dot product between vehicle and target direction)
  local dotAngle = vehicleDir:dot(targetDir)
  local angle = math.acos(math.max(-1, math.min(1, dotAngle))) / math.pi * 180

  local sideDist = math.abs(alignedOffset:dot(xVec))
  local forwardDist = math.abs(alignedOffset:dot(yVec))
  local sideDist = math.abs(alignedOffset:dot(xVec))
  local forwardDist = math.abs(alignedOffset:dot(yVec))
@/lua/ge/extensions/editor/gen/top.lua
				if 0 <= s and s < 1 then
					local dir = (v1 + s*(v2-v1) - u1):dot(u2-u1)
--                        lo('?? for_cross:'..i..'>'..k..':'..dir)
		av[#av+1] = b
--        auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	end
		av[#av+1] = b
--        auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	end
			if d < dmi and ang < 10*small_ang then
--                    lo('?? pU_j:'..U.mod(j,#base)..' d:'..d..'/'..tostring(dmi)..' ang:'..tostring(ang)) --..':'..tostring(u)..':'..tostring(v)..':'..tostring(U.vang(u,v))..':'..tostring(u:dot(v)/u:length()/v:length())..':'..tostring(math.acos(u:dot(v)/u:length()/v:length())))
				local cmi = {U.mod(i+ishift,#base),U.mod(j,#base)}
			if d < dmi and ang < 10*small_ang then
--                    lo('?? pU_j:'..U.mod(j,#base)..' d:'..d..'/'..tostring(dmi)..' ang:'..tostring(ang)) --..':'..tostring(u)..':'..tostring(v)..':'..tostring(U.vang(u,v))..':'..tostring(u:dot(v)/u:length()/v:length())..':'..tostring(math.acos(u:dot(v)/u:length()/v:length())))
				local cmi = {U.mod(i+ishift,#base),U.mod(j,#base)}
	--            av[#av+1] = base[i]
	--            auv[#auv+1] = {u=(av[#av]-ref):dot(u), v=(av[#av]-ref):dot(v)}
			end
	--            av[#av+1] = base[i]
	--            auv[#auv+1] = {u=(av[#av]-ref):dot(u), v=(av[#av]-ref):dot(v)}
			end
	--                for _,b in pairs(baseext) do
						auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	--                    auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	--                for _,b in pairs(baseext) do
						auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	--                    auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
						auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	--                    auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
					end
						auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	--                    auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
					end
	for _,b in pairs(baseext) do
		auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	end
	for _,b in pairs(baseext) do
		auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	end
		for _,b in pairs(baseext) do
			auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
		end
		for _,b in pairs(baseext) do
			auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
		end
@/lua/ge/extensions/gameplay/traffic/roles/police.lua
        if self.veh.speed >= 8 and targetVeh.speed >= 8 and self.veh.speed + targetVeh.speed >= self.avoidSpeed
        and targetVeh.driveVec:dot(self.veh.driveVec) <= -0.707 and (targetVeh.pos - self.veh.pos):normalized():dot(self.veh.driveVec) >= 0.707 then
          if self.state == 'chase' then
        if self.veh.speed >= 8 and targetVeh.speed >= 8 and self.veh.speed + targetVeh.speed >= self.avoidSpeed
        and targetVeh.driveVec:dot(self.veh.driveVec) <= -0.707 and (targetVeh.pos - self.veh.pos):normalized():dot(self.veh.driveVec) >= 0.707 then
          if self.state == 'chase' then
        if targetVeh.pursuit.timers.evadeValue >= 0.5 or not targetVeh.pursuit.roadblockPos
        or targetVeh.vel:dot((targetVeh.pos - targetVeh.pursuit.roadblockPos):normalized()) >= 9 then
          self:setAction('chaseTarget') -- exit roadblock mode
        if self.targetPursuitMode < 3 and targetVisible and targetVeh.speed <= minSpeed and self.veh.speed >= 8 then
          if self.state == 'chase' and distSq <= brakeDistSq and targetVeh.driveVec:dot(targetVeh.pos - self.veh.pos) > 0 then -- pull over near target vehicle
            self:setAction('pullOver')
@/lua/ge/extensions/editor/tech/roadArchitect/geometry.lua
  local n2, n3 = p1 - center, p2 - center
  return (twoPi + atan2(n2:dot(n3:cross(rotDir)), n2:dot(n3))) % twoPi
end
  local n2, n3 = p1 - center, p2 - center
  return (twoPi + atan2(n2:dot(n3:cross(rotDir)), n2:dot(n3))) % twoPi
end
  local v1 = pStart_2D - cen
  local theta, signFac = 0.0, -sign2((p2 - p1):cross(vertical):dot(p3 - p1))
  local rotDir = (pStart_2D - pEnd_2D):cross(pMid_2D - pEnd_2D):normalized()
    tgt_2D:normalize()
    local signFac = -sign2(tgt_2D:cross(vertical):dot(pIp - pI))
    local theta = util.angleBetweenVecs(v1_2D, p3_2D - iCen_2D) * signFac
          local angDeg = max(0.0, min(8.0, -0.015 * radius + 8.5))
          local bankingSign = sign2((p2 - p1):cross(vertical):dot(p3 - p1))
          nodes[i].rot = im.FloatPtr(bankingSign * autoBankingFactor * angDeg)
@/lua/ge/extensions/editor/tech/roadArchitect/utilities.lua
local function slerp(v1, v2, t)
  local dot = v1:dot(v2)
  if dot > 1.0 then dot = 1.0 end
-- Computes the (small) angle between two unit vectors, in radians.
local function angleBetweenVecsNorm(a, b) return acos(a:dot(b)) end
  local c = cos(theta)
  return v * c + k:cross(v) * sin(theta) + k * k:dot(v) * (1.0 - c)
end
  v2:normalize()
  local dot = v1:dot(v2)
  if dot > 0.999999 then
@/lua/ge/extensions/core/trafficSignals.lua
      end
      if nDir:dot(dir) < 0 then
        n1, n2 = n2, n1
  local dist = self.pos:distance(map.objects[vehId].pos)
  local vehDot = self.dir:dot(map.objects[vehId].dirVec)
  local relDist = map.objects[vehId].pos:xnormOnLine(self.pos, tempVec) -- negative while before signal point
      if instance.pos:squaredDistance(refPos) <= 1600 then -- within 40 m of the reference position (safe enough?)
        if instance.dir:dot(refPos - instance.pos) > 0 then -- facing the same direction relative to the reference position
          vectors[instance.name] = instance.pos
@/lua/common/extensions/ui/imguiUtils.lua
  local w = vec3(nodePos - startPos)
  local c1 = w:dot(v)
  local c2 = v:dot(v)
  local c1 = w:dot(v)
  local c2 = v:dot(v)
  local b = c1/c2
@/lua/ge/extensions/gameplay/rally/snaproad/geoPacenotes.lua
--   local bsql = d2:squaredLength()
--   local adotb = d1:dot(d2)
@/lua/ge/extensions/freeroam/crashCamMode.lua
              local edgeVector = (p2 - p1):normalized()
              local dotProduct = edgeVector:dot(playerVel)
              local velocityTowardsWall = playerVel - (edgeVector * dotProduct)
@/inspector/External/three.js/OrbitControls.js
                lastPosition.distanceToSquared( scope.object.position ) > EPS ||
                8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
@/lua/vehicle/extensions/tech/wheelForces.lua

      local p2x = p1 + vectorSum:dot(wheelLeftVector) * wheelLeftVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2x = p1 + vectorSum:dot(wheelLeftVector) * wheelLeftVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2z = p1 + vectorSum:dot(upVector) * upVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2z = p1 + vectorSum:dot(upVector) * upVector
      obj.debugDrawProxy:drawCylinder(p1, p2x, 0.05, color(0, 255, 0, 255))

      local p2x = p1 + vectorSum:dot(wheelLeftVector) * wheelLeftVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2x = p1 + vectorSum:dot(wheelLeftVector) * wheelLeftVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2z = p1 + vectorSum:dot(upVector) * upVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2z = p1 + vectorSum:dot(upVector) * upVector

      local p2x = p1 + vectorSum:dot(wheelLeftVector) * wheelLeftVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2x = p1 + vectorSum:dot(wheelLeftVector) * wheelLeftVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2z = p1 + vectorSum:dot(upVector) * upVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2z = p1 + vectorSum:dot(upVector) * upVector

      local p2x = p1 + vectorSum:dot(wheelLeftVector) * wheelLeftVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2x = p1 + vectorSum:dot(wheelLeftVector) * wheelLeftVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2z = p1 + vectorSum:dot(upVector) * upVector
      local p2y = p1 + vectorSum:dot(wheelForwardVector) * wheelForwardVector
      local p2z = p1 + vectorSum:dot(upVector) * upVector
@/lua/ge/extensions/gameplay/markers/parkingMarker.lua

    tmpZ:setScaled(tmpVec:dot(tmpY) / 25)
    self.iconPos:setAdd(tmpZ)
@/lua/vehicle/extensions/perfectLaunch.lua
    local directionVector = obj:getDirectionVector()
    local actualVelocity = max((directionVector:dot(velocity) / (directionVector:length() * directionVector:length()) * directionVector):length(), 0)
@/lua/ge/extensions/editor/toolUtilities/fitPoly.lua
          toPoint:normalize()
          local dot = currentDir:dot(toPoint)
          if dot > 0.5 then
    dir2:normalize()
    local dot = dir1:dot(dir2)
@/lua/ge/extensions/gameplay/police.lua
                  if getObjectByID(otherId):getActive() and otherVeh.role.validTargets[id] and otherVeh.role.validTargets[id].dist > 10000
                  and otherVeh.focusDist > minDist and veh.focus.dirVec:dot(otherVeh.pos - veh.focus.pos) < 0 then
                    table.insert(vehIds, otherId)
@/lua/ge/extensions/editor/toolUtilities/splineInput.lua
    local divIdx = selSpline.discMap[dragNodeIdx]
    delta = mouseVel2D:dot(selSpline.binormals[divIdx])
  else -- Full spline.
    local handleSign = dragRibIsFirstHandle and -1 or 1
    delta = handleSign * mouseVel2D:dot(binVec)
  end
@/lua/ge/extensions/scenario/waypoints.lua
        local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
        local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
        table.insert(vData.wheelOffsets, pos)
        local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
        local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
        table.insert(vData.wheelOffsets, pos)
        local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
        local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
        table.insert(vData.wheelOffsets, pos)
@/lua/ge/extensions/gameplay/race/pathnode.lua
  if self.hasNormal then
    return inside and ((pos-self.pos):normalized():dot(self.normal) >= 0)
  else
@/lua/ge/extensions/editor/gen/network.lua
        -- projections
        local pi, pip = (p - ni):dot(nip - ni), (p - nip):dot(nip - ni)
        local shadow = math.abs(pi) + math.abs(pip)
        -- projections
        local pi, pip = (p - ni):dot(nip - ni), (p - nip):dot(nip - ni)
        local shadow = math.abs(pi) + math.abs(pip)
            --?? massCenter role
            if (anode[path[i]].pos - massCenter/#anode):dot(vn) < 0 then
                vn = -vn
            --?? massCenter role
            if (U.proj2D(anode[path[i]].pos) - massCenter/#anode):dot(vn) < 0 then
                vn = -vn
@/lua/ge/extensions/core/cameraModes/external.lua
  if openxrSessionRunning then return end
  offset = vec3(offset:dot(nx), offset:dot(ny), offset:dot(nz)) -- from world axis system to vehicle axis system
  self.autopoint.localOffset = offset -- in local vehicle coordinates
  if openxrSessionRunning then return end
  offset = vec3(offset:dot(nx), offset:dot(ny), offset:dot(nz)) -- from world axis system to vehicle axis system
  self.autopoint.localOffset = offset -- in local vehicle coordinates
  if openxrSessionRunning then return end
  offset = vec3(offset:dot(nx), offset:dot(ny), offset:dot(nz)) -- from world axis system to vehicle axis system
  self.autopoint.localOffset = offset -- in local vehicle coordinates
@/lua/ge/extensions/gameplay/traffic.lua
      local roadDir = traffic[id] and traffic[id].respawn.spawnDirBias or 0
      if math.abs(roadDir) < 0.6 and (focus.dist < 5 or focus.dirVec:dot(tempVec) < 0) then
        roadDir = 0.6 -- vehicles respawning behind you should mostly drive towards you
      else
        traffic[id].respawnSpeed = max(3.333, dir:dot(vecUp) * 30) -- 12 km/h, or higher if uphill is steep enough
        local link = mapNodes[spawnData.n1].links[spawnData.n2] or mapNodes[spawnData.n2].links[spawnData.n1]
      if veh.state == 'active' then
        local dotDir = sign2(focus.dirVec:dot(veh.dirVec))
        if dotDir == 1 then
@/lua/ge/extensions/editor/gen/utils.lua
	local p = vec3(x,y)
	if (c-p):dot(d-p) <= sense then
--			lo('?? l2s_has:', true)
--			lo('?? l2s_has:', true)
--    if (vec3(c[1],c[2],0)-p):dot(vec3(d[1],d[2],0)-p) <= 0 then
		local s = (p-c):length()/(d-c):length()
	if s then
		if (b-a):dot(p-a) > sense then
			return p,s
--            lo('?? if_Z:'..i..':'..tostring((U.mod(p[1]+1,base)-U.mod(p[1],base)):cross(dp)))
		if dir:dot(dp) < 0 and l < mileft then
			if (U.mod(p[1]+1,base)-U.mod(p[1],base)):cross(dp).z < 0 then
		end
		if dir:dot(dp) > 0 and l < miright then
			if (U.mod(p[1]+1,base)-U.mod(p[1],base)):cross(dp).z < 0 then
--                            imi = i
						elseif v:dot(p-c) < 0 then    -- intersection is in v-direction
--                            d = (c - p):length()
		for i=2,#rc-1 do
			if (v4e[rc[i+1]].p - v4e[rc[i]].p):dot(v4e[rc[i]].p - v4e[rc[i-1]].p) < 0.00001 then
--                lo('?? first_in_rc:'..k..':'..i)
		for i=#rc-1,2,-1 do
			if (v4e[rc[i+1]].p - v4e[rc[i]].p):dot(v4e[rc[i]].p - v4e[rc[i-1]].p) > 0.00001 then
				-- remove colinear
		end
		if (v4e[rc[1]].p - v4e[rc[#rc]].p):dot(v4e[rc[#rc]].p - v4e[rc[#rc-1]].p) > 0.00001 then
			-- remove colinear
							c = line2seg(p, p+v, pth[jr], pth[jr-1])
							if c and v:dot(p-c) < 0 then
								d = (c - p):length()
--                                lo('?? for_TRY: c='..tostring(c)..' p='..tostring(p)..' v:'..tostring(v))
							if c and v:dot(p-c) < 0 then
								d = (c - p):length()
	local p = vec3(x,y,0)
	if (vec3(c[1],c[2],0)-p):dot(vec3(d[1],d[2],0)-p) <= 0 then
		return p
		if (u:normalized()-v:normalized()):length() < 0.00000001 then return 0 end
	--    math.acos(u:normalized():dot(v:normalized()))
		if math.abs(crs) < 0.0000001 then
		if math.abs(crs) < 0.0000001 then
      		return u:dot(v) < 0 and math.pi or 0
    	end

		return (crs > 0 and 1 or -1)*math.acos(u:dot(v)/u:length()/v:length())
	end
	end
--        lo('?? vang:'..tostring(u)..':'..tostring(v)..':'..tostring(math.acos(u:dot(v)/u:length()/v:length())))
	local cs = u:dot(v)/u:length()/v:length()
--        lo('?? vang:'..tostring(u)..':'..tostring(v)..':'..tostring(math.acos(u:dot(v)/u:length()/v:length())))
	local cs = u:dot(v)/u:length()/v:length()
--    if dbg then lo('?? vang:'..tostring(cs)..':'..tostring(cs+1)..':'..tostring(cs+1==0)) end
		  	if strict then
				if (p-rc[j]):cross(mod(j+1,rc)-rc[j]):dot(vn) <= 0 then
	--            if (p-rc[j]):cross(mod(j+1,rc)-rc[j]).z > 0 then
			else
				if (p-rc[j]):cross(mod(j+1,rc)-rc[j]):dot(vn) < 0 then
	--            if (p-rc[j]):cross(mod(j+1,rc)-rc[j]).z > 0 then
	dir = dir:normalized()
	return p - dir*p:dot(dir)
end

	return math.sqrt(v:length()^2 - v:dot(u)^2), p+u*v:dot(u)-v
end

	return math.sqrt(v:length()^2 - v:dot(u)^2), p+u*v:dot(u)-v
end
local function less(a, b, v)
--    if (a - b):dot(v) == 0 then return 0 end
	return (a - b):dot(v)
--    if (a - b):dot(v) == 0 then return 0 end
	return (a - b):dot(v)
end
	local dir = (raypos-campos):normalized()
	local h = math.abs((p - campos):dot(norm:normalized()))
	local r = math.abs(h/math.cos(U.vang(dir,norm)))
			dp = (v1 + v2):normalized() * margin/math.sin(U.vang(v1,v2)/2) --math.pi/4)
			if v2:cross(v1):dot(up) < 0 then
				dp = -dp
@/lua/ge/extensions/ui/uiNavi.lua
      mapObj.pos[1], mapObj.pos[2], mapObj.pos[3] = v.pos.x, v.pos.y, v.pos.z
      mapObj.rot = math.deg(math.atan2(v.dirVec:dot(xPlus), v.dirVec:dot(yMinus)))
      mapObj.speed = v.vel:length()
      mapObj.pos[1], mapObj.pos[2], mapObj.pos[3] = v.pos.x, v.pos.y, v.pos.z
      mapObj.rot = math.deg(math.atan2(v.dirVec:dot(xPlus), v.dirVec:dot(yMinus)))
      mapObj.speed = v.vel:length()
      -- --v.vel = v.vel:toTable()
      --   rot = math.deg(math.atan2(dir:dot(xPlus), dir:dot(yMinus))),
      -- --v.dirVec = v.dirVec:toTable()
      -- --v.vel = v.vel:toTable()
      --   rot = math.deg(math.atan2(dir:dot(xPlus), dir:dot(yMinus))),
      -- --v.dirVec = v.dirVec:toTable()
@/lua/ge/extensions/flowgraph/nodes/scene/rectMarker.lua
  local trigger = Sim.upcast(self.triggerObj)
  local front = ((vDirVec:dot(yVec) > 0) and 1 or 0) + 1
  self.pinOut.inside.value = true
  local fwdAligned = vDirVec:projectToOriginPlane(zVec); fwdAligned:normalize()
  self.pinOut.dotAngle.value = math.abs(fwdAligned:dot(yVec))
  self.pinOut.forward.value = fwdAligned:dot(yVec) > 0
  self.pinOut.dotAngle.value = math.abs(fwdAligned:dot(yVec))
  self.pinOut.forward.value = fwdAligned:dot(yVec) > 0
      and trigger:isPointContained(ob:getPoint(i*2+1))
      and (self.pinIn.onlyForward.value and (fwdAligned:dot(yVec) > 0) or (not self.pinIn.onlyForward.value))
    local clr = contained and clrIn or clrOut
  local alignedOffset = (bbCenter - tpos):projectToOriginPlane(zVec)
  self.pinOut.sideDistance.value = math.abs(alignedOffset:dot(xVec))
  self.pinOut.forwardDistance.value = math.abs(alignedOffset:dot(yVec))
  self.pinOut.sideDistance.value = math.abs(alignedOffset:dot(xVec))
  self.pinOut.forwardDistance.value = math.abs(alignedOffset:dot(yVec))

  self.pinOut.sideDistanceRelative.value = math.abs(alignedOffset:dot(xVec)) / sc.x
  self.pinOut.forwardDistanceRelative.value = math.abs(alignedOffset:dot(yVec)) / sc.y
  self.pinOut.sideDistanceRelative.value = math.abs(alignedOffset:dot(xVec)) / sc.x
  self.pinOut.forwardDistanceRelative.value = math.abs(alignedOffset:dot(yVec)) / sc.y
@/lua/ge/extensions/editor/gen/lib/ai.lua
        for i,p in pairs(set) do
            local ds = (p - (a + u*(p-a):dot(u))):length()
--                lo('?? ds:'..i..':'..tostring(p)..':'..ds)
@/lua/ge/extensions/editor/sidewalkSpline/populate.lua
          -- Remove any component along X to make Y orthogonal to X.
          local dotXO = tmpVec1:dot(tmpForward)
          tmpVec2:setScaled2(tmpForward, dotXO)
@/lua/ge/extensions/editor/terrainAndRoadImporter.lua
  local rposc = rpos - c
  local pOnTri = rposc:dot(norm) / norm.z
  rposc.z = rposc.z - pOnTri
  local pacnorm = rposc:cross(norm)
  local bx, by = bc:dot(pacnorm), ca:dot(pacnorm)
  if min(bx, by) >= 0 and bx + by <= normSq then
  local pacnorm = rposc:cross(norm)
  local bx, by = bc:dot(pacnorm), ca:dot(pacnorm)
  if min(bx, by) >= 0 and bx + by <= normSq then
@/lua/ge/extensions/editor/gen/test.lua
		av[#av+1] = b
		auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	end
		av[#av+1] = b
		auv[#auv+1] = {u=(b-ref):dot(u), v=(b-ref):dot(v)}
	end
@/lua/ge/extensions/flowgraph/nodes/util/distanceRemaining.lua
  dirVec:setSub2(nextPos, prevPos)
  local goingTheRightDirection = vel <= threshold or (dirVec:dot(vehData.vel) > 0 and vel > threshold)
@/lua/vehicle/scriptai.lua
  avgWheelNodePos:set(
    avgWheelNodePos:dot(vec3(leftVec.x, -dir.x, up.x)),
    avgWheelNodePos:dot(vec3(leftVec.y, -dir.y, up.y)),
    avgWheelNodePos:dot(vec3(leftVec.x, -dir.x, up.x)),
    avgWheelNodePos:dot(vec3(leftVec.y, -dir.y, up.y)),
    avgWheelNodePos:dot(vec3(leftVec.z, -dir.z, up.z))
    avgWheelNodePos:dot(vec3(leftVec.y, -dir.y, up.y)),
    avgWheelNodePos:dot(vec3(leftVec.z, -dir.z, up.z))
  )
  local vehCenterPositionRelative = vec3(
    vehCenterPosRel:dot(obj:getDirectionVectorUp():cross(obj:getDirectionVector())),
    -(vehCenterPosRel:dot(obj:getDirectionVector())),
    vehCenterPosRel:dot(obj:getDirectionVectorUp():cross(obj:getDirectionVector())),
    -(vehCenterPosRel:dot(obj:getDirectionVector())),
    vehCenterPosRel:dot(obj:getDirectionVectorUp())
    -(vehCenterPosRel:dot(obj:getDirectionVector())),
    vehCenterPosRel:dot(obj:getDirectionVectorUp())
  )
    local xnorm = aiPos:xnormOnLine(p1, p2)
    if (p1:squaredDistance(p2) < 0.0025 and s2.t < time) or xnorm > 1 or (xnorm < 0 and s2.t < time and aiVel:dot(p2) < aiVel:dot(p1)) then
      if s1.forceSpeed and not s2.forceSpeed then s2.forceSpeed = s1.forceSpeed end
    local xnorm = aiPos:xnormOnLine(p1, p2)
    if (p1:squaredDistance(p2) < 0.0025 and s2.t < time) or xnorm > 1 or (xnorm < 0 and s2.t < time and aiVel:dot(p2) < aiVel:dot(p1)) then
      if s1.forceSpeed and not s2.forceSpeed then s2.forceSpeed = s1.forceSpeed end
  local targetaivec = targetPos - aiPos
  local targetai = targetaivec:dot(aiDirVec)
  aiSpeed = aiVel:dot(aiDirVec) * sign(targetai)
  local targetai = targetaivec:dot(aiDirVec)
  aiSpeed = aiVel:dot(aiDirVec) * sign(targetai)
  if aiVelLen > 1 then
    local leftVel = aiLeftVec:dot(aiVel)
    if leftVel * aiLeftVec:dot(targetPosOnLine - aiPos) > 0 then
    local leftVel = aiLeftVec:dot(aiVel)
    if leftVel * aiLeftVec:dot(targetPosOnLine - aiPos) > 0 then
      local dirDiff = -math.asin(aiLeftVec:dot(targetaivec:normalized()))
    if leftVel * aiLeftVec:dot(targetPosOnLine - aiPos) > 0 then
      local dirDiff = -math.asin(aiLeftVec:dot(targetaivec:normalized()))
      local rotVel = min(1, (prevDirVec:projectToOriginPlane(aiUpVec):normalized() - aiDirVec):length() * dt * 10000)
  if targetPosOnLine:xnormOnLine(p1, p2) > 1 then
    tp2 = (targetPosOnLine - p2):normalized():dot(turnleft)
  else
  else
    tp2 = (p3 - p2):normalized():dot(turnleft)
  end

  local deviation = (aiPos - p2):dot(turnleft)
  deviation = sign(deviation) * min(5, abs(deviation))
  -- target bending
  local grleft = aiLeftVec:dot(obj:getGravityVector())
  if deviation * grleft > 0 then
  if deviation * grleft > 0 then
    local carturn = turnleft:dot(aiLeftVec)
    targetPos = targetPosOnLine - aiLeftVec * sign(deviation) * min(5, abs(0.01 * deviation * grleft * aiVelLen * min(1, carturn * carturn)))
  local targetDirVec = (targetPos - aiPos):normalized()
  local dirDiff = -math.asin(aiLeftVec:dot(targetDirVec))
  local steerCoef = reldeviation * min(aiSpeed * aiSpeed, abs(aiSpeed)) * min(1, dirDiff * dirDiff * 4) * 0.2
  local understeerCoef = max(0, -steerCoef) * min(1, abs(aiVel:dot(p2p1:normalized()) * 3))
  local noUndersteerCoef = max(0, 1 - understeerCoef)
        local posAccel = targetPos - aiPos
        posAccel = posAccel + (reqVel * fwd - vel) * dt / clamp(posAccel:length() / max(1e-30, vel:dot(posAccel:normalized())), dt, 1)
        local posAccelL = posAccel:dot(fwd)
        posAccel = posAccel + (reqVel * fwd - vel) * dt / clamp(posAccel:length() / max(1e-30, vel:dot(posAccel:normalized())), dt, 1)
        local posAccelL = posAccel:dot(fwd)
        local posAccelT = posAccel - posAccelL * fwd
        thrusters.applyAccel(posAccel, dt)
        extForceVel = posAccel:dot(fwd) * dt
        -- if s2.t-time<=dt then print((targetPos - aiPos):projectToOriginPlane(up):length()) end -- measure error
@/lua/ge/extensions/flowgraph/nodes/mission/knockAwayCheck.lua
            local up = mapData.dirVecUp
            if up:dot(val.up) < (math.pi * self.pinIn.tippingMinAngle.value / 180) then
              tipped = true
@/lua/vehicle/mapmgr.lua
    local edge = graph[currRoads[i]][currRoads[i+1]]
    local score = push3(dir):dot((push3(nodePositions[edge.outNode]) - push3(nodePositions[edge.inNode])):normalized())
    if not edge.oneWay then score = math.abs(score) end -- manage edges with multiple directions
            tmpVec:setSub(n1Pos) -- node1ToPosVec
            local xnorm = min(1, max(0, edgeVec:dot(tmpVec) / (edgeVec:squaredLength() + 1e-30)))
            local key
@/gameplay/missionTypes/scatterPickup/customNodes/scatterPrefabSetupNode.lua
      if option.align then
        local angle = (math.acos(vec3(0,0,1):dot(point.normal))) / math.pi * 180
        if angle <= option.align then
@/lua/ge/extensions/editor/toolUtilities/geom.lua
  local v0, v1, v2 = c - a, b - a, p - a
  local dot00, dot01, dot02, dot11, dot12 = v0:dot(v0), v0:dot(v1), v0:dot(v2), v1:dot(v1), v1:dot(v2)
  local denom = dot00 * dot11 - dot01 * dot01
  local v0, v1, v2 = c - a, b - a, p - a
  local dot00, dot01, dot02, dot11, dot12 = v0:dot(v0), v0:dot(v1), v0:dot(v2), v1:dot(v1), v1:dot(v2)
  local denom = dot00 * dot11 - dot01 * dot01
  local v0, v1, v2 = c - a, b - a, p - a
  local dot00, dot01, dot02, dot11, dot12 = v0:dot(v0), v0:dot(v1), v0:dot(v2), v1:dot(v1), v1:dot(v2)
  local denom = dot00 * dot11 - dot01 * dot01
  local v0, v1, v2 = c - a, b - a, p - a
  local dot00, dot01, dot02, dot11, dot12 = v0:dot(v0), v0:dot(v1), v0:dot(v2), v1:dot(v1), v1:dot(v2)
  local denom = dot00 * dot11 - dot01 * dot01
  local v0, v1, v2 = c - a, b - a, p - a
  local dot00, dot01, dot02, dot11, dot12 = v0:dot(v0), v0:dot(v1), v0:dot(v2), v1:dot(v1), v1:dot(v2)
  local denom = dot00 * dot11 - dot01 * dot01
  tmp0:setScaled(s)
  local kDotV = k:dot(v)
  tmp1:setScaled2(k, kDotV * (1.0 - c))
  tmp0:setScaled(s)
  local kDotV = k:dot(v) -- tmp1 = k * (k . v) * (1 - c).
  tmp1:setScaled2(k, kDotV * oneMinusC)
  bcNorm:normalize()
  local dot = clamp(abNorm:dot(bcNorm), -1.0, 1.0)
  local angle = acos(dot)
-- Computes the (small) angle between two unit vectors, in radians.
local function angleBetweenVecsNorm(a, b) return acos(a:dot(b)) end
  tmp1:normalize()
  return acos(tmp0:dot(tmp1))
end
  tmp1:normalize()
  return acos(tmp0:dot(tmp1))
end
local function signedAngleBetweenVecs(a, b, axis)
  local dotAB = clamp(a:dot(b), -1, 1)
  local angle = acos(dotAB)
  tmp0:setCross(a, b)
  local sign = tmp0:dot(axis) >= 0 and 1 or -1
  return angle * sign
  local toProj = toVec:projectToOriginPlane(axis)
  local dot = max(-1, min(1, fromProj:dot(toProj)))
  local angle = acos(dot) -- The unsigned angle.
  local angle = acos(dot) -- The unsigned angle.
  local sign = (fromProj:cross(toProj)):dot(axis) >= 0 and 1 or -1 -- Determine the sign of the angle.
  return angle * sign * (180 / pi) -- Signed angle in degrees.
    if lenSq > 0 then
      local t = clamp((pos - p0):dot(seg) / lenSq, 0, 1)
      local proj = p0 + seg * t

  local t = 2.0 * (pos - bestProj):dot(bin) / width
  return bestProj, bestS, t
  tmp1:normalize()
  local dot = clamp(tmp0:dot(tmp1), -1, 1)
  local angle = acos(dot)
  -- Calculate angle between the two vectors
  local unsignedAngle = acos(max(-1, min(1, tmp1:dot(tmpTangent))))
  local avgLen = 0.5 * (tmp1:length() + tmpTangent:length())
  tmpCross:setCross(tmp1, tmpTangent)
  local sign = tmpCross:dot(globalUp) >= 0 and 1 or -1
  return curvature * sign
@/lua/ge/extensions/flowgraph/nodes/scene/raceLineParking.lua
  local diff = pos - vec3(self.pinIn.position.value)
  return vec3(diff:dot(xn)*scale+centerOffset.x+tlCenter.x, diff:dot(yn)*scale + centerOffset.y+tlCenter.y, 0)
end
  local diff = pos - vec3(self.pinIn.position.value)
  return vec3(diff:dot(xn)*scale+centerOffset.x+tlCenter.x, diff:dot(yn)*scale + centerOffset.y+tlCenter.y, 0)
end

  local front = ((vDirVec:dot(yVec) > 0) and 1 or 0) +1
  local contained = false
  local fwdAligned = fwd:projectToOriginPlane(zVec):normalized()
  self.pinOut.dotAngle.value = math.abs(fwdAligned:dot(yVec))
  self.pinOut.forward.value = fwdAligned:dot(yVec) > 0
  self.pinOut.dotAngle.value = math.abs(fwdAligned:dot(yVec))
  self.pinOut.forward.value = fwdAligned:dot(yVec) > 0
  local w1Off, w2Off = (w1 - tpos):projectToOriginPlane(zVec), (w2 - tpos):projectToOriginPlane(zVec)
  self.pinOut.sideDistance.value = alignedOffset:dot(xVec)
  self.pinOut.forwardDistance.value = math.min(-w1Off:dot(yVec), -w2Off:dot(yVec))
  self.pinOut.sideDistance.value = alignedOffset:dot(xVec)
  self.pinOut.forwardDistance.value = math.min(-w1Off:dot(yVec), -w2Off:dot(yVec))
  self.pinOut.sideDistance.value = alignedOffset:dot(xVec)
  self.pinOut.forwardDistance.value = math.min(-w1Off:dot(yVec), -w2Off:dot(yVec))
      nodePos = vec3(nodePos.x, nodePos.y, nodePos.z)
      table.insert(wheels,{wheelNodePos = vehicle:getPosition() + nodePos, distance = -nodePos:dot(forward)})
      --debugDrawer:drawTextAdvanced(vehicle:getPosition() + nodePos, String(tostring(-nodePos:dot(forward))),  ColorF(1,1,1,1), true, false, ColorI(0,0,0,192))
      table.insert(wheels,{wheelNodePos = vehicle:getPosition() + nodePos, distance = -nodePos:dot(forward)})
      --debugDrawer:drawTextAdvanced(vehicle:getPosition() + nodePos, String(tostring(-nodePos:dot(forward))),  ColorF(1,1,1,1), true, false, ColorI(0,0,0,192))
    end
@/lua/vehicle/extensions/vehiclePerformanceData.lua
      local wheelVector = wheelNodePos - avgWheelPos --create a vector from our "center" to the wheel
      local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
      local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
      local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
      local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
@/lua/ge/extensions/flowgraph/nodes/gameplay/rally/rallySuperCountdown.lua
  tmpToVehicle:setSub2(vehPos, planePos)
  local dist = tmpToVehicle:dot(tmpPlaneNormal)
@/lua/ge/extensions/core/cameraModes/driver.lua
  camUp:setRotate(camRot, vecZ)
  local carRoll = math.atan2(push3(camUp):dot(-push3(carLeft)), camUp:dot(carUp))
  local carRollFactor = 1 - self.stableHorizonFactor * smootheststep(clamp(1.42*carUp.z, 0, 1))
  camUp:setRotate(camRot, vecZ)
  local carRoll = math.atan2(push3(camUp):dot(-push3(carLeft)), camUp:dot(carUp))
  local carRollFactor = 1 - self.stableHorizonFactor * smootheststep(clamp(1.42*carUp.z, 0, 1))
  -- Look-ahead angle
  self.fwdSpeed = lerp(self.fwdSpeed, -data.vel:length() * push3(data.vel):normalized():dot(carFwd), data.dt * ( 1.5 - self.lookAheadSmoothness))
  nRockPos:set(push3(carFwd) * (1 - self.rockPos:length() / self.lookAheadSmoothness) + self.rockPos)
@/lua/vehicle/controller/sbrGauges.lua
    local dir = obj:getDirectionVector():normalized()
    mapData.rotation = deg(atan2(dir:dot(vecX), dir:dot(vecY)))
    htmlTexture.call(gaugesScreenName, "updateMap", mapData)
    local dir = obj:getDirectionVector():normalized()
    mapData.rotation = deg(atan2(dir:dot(vecX), dir:dot(vecY)))
    htmlTexture.call(gaugesScreenName, "updateMap", mapData)
@/lua/ge/extensions/tech/openDriveExporter.lua
      local testTanNorm = testTan:normalized()
      local shortAngle = stdTanNorm:dot(testTanNorm)
      if abs(shortAngle) > max(0.707, maxSoFar) then
@/lua/vehicle/wheels.lua
    local wheelVector = wheelNodePos - avgWheelPos --create a vector from our "center" to the wheel
    local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
@/lua/ge/extensions/gameplay/parking.lua
      local activeRadius = currVeh.activeRadius + focus.dist
      activeRadius = activeRadius + max(0, focus.dirVec:dot(tempVec)) * 150
      if square(activeRadius) < focus.pos:squaredDistance(vehPos) then
@/lua/ge/extensions/editor/toolUtilities/simplex.lua
-- Dot product.
local function dot(g, x, y)
  return g[1] * x + g[2] * y
    t0 = t0 * t0
    n0 = t0 * t0 * dot(grad3[gi0], x0, y0)
  end
    t1 = t1 * t1
    n1 = t1 * t1 * dot(grad3[gi1], x1, y1)
  end
    t2 = t2 * t2
    n2 = t2 * t2 * dot(grad3[gi2], x2, y2)
  end
@/lua/vehicle/controller/tech/idealRADARSensor.lua
-- Projects a vector onto another vector.
local function project(a, b) return (a:dot(b) / b:dot(b)) * b end
-- Projects a vector onto another vector.
local function project(a, b) return (a:dot(b) / b:dot(b)) * b end
      local distantPoint = pos + (1e12 * fwd)                                                                     -- A point on the player vehicle forward vector, far in the distance.
      if fwd:dot(fwdB) > 0.0 and (distantPoint - pos):lenSquared() > (distantPoint - posB):lenSquared() then      -- Test that other vehicle is in front hemisphere and has same dir.
        local distToPlayerVehicleSq = (pos - posB):lenSquared()                                                   -- The squared distance between the player and other vehicle.
@/lua/vehicle/controller/tech/roadsSensor.lua
  local u, v = vec3(a.x - p.x, a.y - p.y), vec3(b.x - a.x, b.y - a.y)
  local vu, vv = v:dot(u), v:dot(v)
  local t = -vu / vv
  local u, v = vec3(a.x - p.x, a.y - p.y), vec3(b.x - a.x, b.y - a.y)
  local vu, vv = v:dot(u), v:dot(v)
  local t = -vu / vv
  local vec1Sqlen, vec2Sqlen = vec1:squaredLength(), vec2:squaredLength()
  local dot12 = vec1:dot(vec2)
  local cos8sq = min(1, dot12 * dot12 / max(1e-30, vec1Sqlen * vec2Sqlen))

  if vfwd:dot(p_front) < vfwd:dot(p_prev) then
    p_rearKey, p_frontKey = p_frontKey, p_rearKey

  if vfwd:dot(p_front) < vfwd:dot(p_prev) then
    p_rearKey, p_frontKey = p_frontKey, p_rearKey
      local p = coords[cands[i]]
      local Dot = (p_front - p_prev):dot(p - p_front)   --(p - p_front):dot(p_front - p_prev)
      local absDot = abs(Dot)
      local p = coords[cands[i]]
      local Dot = (p_front - p_prev):dot(p - p_front)   --(p - p_front):dot(p_front - p_prev)
      local absDot = abs(Dot)
    local p = coords[cands1[i]]
    local Dot = ((p1 - p2):dot(p - p1))
    local absDot = abs(Dot)
    local p = coords[cands2[i]]
    local Dot = ((p2 - p1):dot(p - p2))
    local absDot = abs(Dot)
      lineSegNorm:normalize()
      if fwd:dot(best1) > fwd:dot(best2) then
        lineSegNorm = -lineSegNorm
      lineSegNorm:normalize()
      if fwd:dot(best1) > fwd:dot(best2) then
        lineSegNorm = -lineSegNorm
      local alfa = 0.5
      headingAngle = alfa*acos(max(-1, min(1, fwdproj:dot(lineSegNormproj)))) + (1-alfa)*headingAngle_prev-- New
      if headingAngle < 1.5*math.pi/180 then
@/lua/vehicle/ai.lua
    sensors.gz,
    ego.vel:dot(ego.dirVec),
    -(ego.vel:dot(ego.rightVec)),
    ego.vel:dot(ego.dirVec),
    -(ego.vel:dot(ego.rightVec)),
    ego.vel:dot(ego.upVec),
    -(ego.vel:dot(ego.rightVec)),
    ego.vel:dot(ego.upVec),
    lastCommand.throttle * 100,
    local wheelPos = obj:getNodePosition(wheel.node1)
    if wheelPos:dot(dirVec) > avgWheelNodePos:dot(dirVec) then
      avgFrontWheelPos:setAdd(wheelPos)
    local wheelPos = obj:getNodePosition(wheel.node1)
    if wheelPos:dot(dirVec) > avgWheelNodePos:dot(dirVec) then
      avgFrontWheelPos:setAdd(wheelPos)
  local targetVec = targetPos - ego.pos; targetVec:normalize()
  local dirAngle = asin(ego.rightVec:dot(targetVec))
  if ego.speed > 1 then
    local rightVel = ego.rightVec:dot(ego.vel)
    if rightVel * ego.rightVec:dot(targetPos - ego.pos) > 0 then
    local rightVel = ego.rightVec:dot(ego.vel)
    if rightVel * ego.rightVec:dot(targetPos - ego.pos) > 0 then
      local rotVel = min(1, (ego.prevDirVec:projectToOriginPlane(ego.upVec):normalized()):distance(ego.dirVec) * dt * 10000)

  local dirVel = ego.vel:dot(ego.dirVec)
  local absegoSpeed = abs(dirVel)
    local tp2 = (plan.targetSeg or 0) > 1 and targetPos or plan[3].pos
    local targetSide = (tp2 - p2):dot(p2p1DirVec:cross(ego.upVec))
      local steerCoef = outDeviation * absegoSpeed * absegoSpeed * min(1, dirAngle * dirAngle * 4)
      local understeerCoef = max(0, steerCoef) * min(1, abs(ego.vel:dot(p2p1DirVec) * 3))
      local noUndersteerCoef = max(0, 1 - understeerCoef)

  local dirTarget = ego.dirVec:dot(targetVec)
  local dirTargetAxis = ego.rightVec:dot(targetVec)
  local dirTarget = ego.dirVec:dot(targetVec)
  local dirTargetAxis = ego.rightVec:dot(targetVec)

  if internalState.crash.manoeuvre == 1 and dirTarget < ego.dirVec:dot(internalState.crash.dir) then
    driveCar(-sign(dirAngle), brake * brakeCoef, throttle * throttleCoef, 0)
      local steering = twt.steerSmoother:get(twt.dirState[2], dt)
      local pbrake = 0 -- * clamp(sign2(0.83 + ego.upVec:dot(gravityDir)), 0, 1) -- >= 10 deg
      local throttle, brake = 0, 0
    local pbrake
    if ego.vel:dot(ego.dirVec) < 0 and ego.speed > 0.1 then
      -- TODO: handbrake when stoped or moving backward

    local aggSq = square(aggression + max(0, -(ego.dirVec:dot(gravityDir))))
    local rate = max(throttleSmoother[throttleSmoother:value() < throttle], 10 * aggSq * aggSq)
  if ego.speed < 2 then return true end
  if newTvec:dot(ego.dirVec) * baseTvec:dot(ego.dirVec) <= 0 then return false end
  local baseTargetRight = baseTvec:cross(ego.upVec); baseTargetRight:normalize()
  if ego.speed < 2 then return true end
  if newTvec:dot(ego.dirVec) * baseTvec:dot(ego.dirVec) <= 0 then return false end
  local baseTargetRight = baseTvec:cross(ego.upVec); baseTargetRight:normalize()
  local baseTargetRight = baseTvec:cross(ego.upVec); baseTargetRight:normalize()
  return abs(newTvec:normalized():dot(baseTargetRight)) * ego.speed < 2
end
  local vec2 = mapData.positions[wp2] - ego.pos
  local dot1 = vec1:dot(dirVec)
  local dot2 = vec2:dot(dirVec)
  local dot1 = vec1:dot(dirVec)
  local dot2 = vec2:dot(dirVec)
  if (dot1 * dot2) <= 0 then
      outEdgeDir:setSub2(mapData:getEdgePositions(k, wp2)); outEdgeDir:normalize()
      local dirCoef = 0.5 * max(0, 1 + outEdgeDir:dot(inEdgeDir))
      local outLaneCountOpposite = (#outLaneConfig - numOfOutLanes)
        local nodePos = mapData.positions[nodeId]
        local dirRatio = max(0, (push3(mapData.positions[newNode.nextNodeInPath or newNode.id]) - newNode.posOrig):normalized():dot((push3(newNode.posOrig) - nodePos):normalized()))
        local drivabilityRatio = min(1, edgeData.drivability * inEdgeDrivabilityInv)
        if thisEdgeInLanes > 0 then
          if newNode.inEdgeNormal:dot(nodePos) < newNode.inEdgeNormal:dot(newNode.posOrig) then -- coming into newNode from the left
            numOfInLanes = numOfInLanes + thisEdgeInLanes
        if thisEdgeInLanes > 0 then
          if newNode.inEdgeNormal:dot(nodePos) < newNode.inEdgeNormal:dot(newNode.posOrig) then -- coming into newNode from the left
            numOfInLanes = numOfInLanes + thisEdgeInLanes
    local thisLaneLatPos = (thisLaneLimRight + thisLaneLimLeft) * 0.5
    local laneColinearity = ((thisLaneLatPos * 2 - 1) * push3(newNodeWidthVec) + newEdgeVec):normalized():dot(dirVec)
    local colinearityError = 1 - max(0, laneColinearity)
      plan[planCount].normal:setScaled(1 / (tmp + 1e-30))
      local chordLength = min(2 / tmp, (1 - norm1:dot(norm2) * 0.5) * tmp) -- 2 / tmp == cos(x/2) : x is angle between norm1, norm2
      plan[planCount].halfWidth = plan[planCount].radiusOrig * chordLength
  newNode.normal:setScaled(1 / (tmp + 1e-30))
  local newNodeChordLength = min(2 / tmp, (1 - newNode.inEdgeNormal:dot(newNode.outEdgeNormal) * 0.5) * tmp) -- new node road width multiplier
  newNode.halfWidth = newNode.radiusOrig * newNodeChordLength
    newNode.normal:setScaled(1 / (tmp + 1e-30))
    newNodeChordLength = min(2 / tmp, (1 - newNode.inEdgeNormal:dot(newNode.outEdgeNormal) * 0.5) * tmp)
    newNode.halfWidth = newNode.radiusOrig * newNodeChordLength
    -- keep inside lanes narrower
    if (push3(mapData.positions[newNode.nextNodeInPath]) - newNode.posOrig + mapData.positions[newNode.prevNodeInPath] - newNode.posOrig):dot(newNode.normal) < 0 then -- = turnDir * normal
      newNode.laneLimLeft = linearScale(newNode.rangeLeft, 0, 1, -newNode.halfWidth, newNode.halfWidth) + (bestLane - newNodeRangeLeftIdx) * laneWidth
    local tmpVec = p2 - p1; tmpVec:setCross(tmpVec, ego.upVec); tmpVec:normalize()
    --egoDeviation = dispVec:dot(tmpVec)
      tmpVec:setSub2(plan[i+1].pos, plan[i].pos)
      if math.abs(dispVecDir:dot(tmpVec)) > 0.5 * plan[i].length then
        break
      local lateralXnorm = n.lateralXnorm or 0
      local newLateralXnorm = clamp(lateralXnorm + ((dispVec):dot(n.normal) * sumLen / dTotal), (n.laneLimLeft + laneWidthMargin) or -math.huge, (n.laneLimRight - laneWidthMargin) or math.huge)
      tmpVec:setScaled2(n.normal, newLateralXnorm - lateralXnorm)
    local lanew = (plan1.rangeRight - plan1.rangeLeft)/plan1.rangeLaneCount
    if plan1.rangeLaneCount > 1 and ego.dirVec:dot(vdirVec) > 0.7 and ego2v < square((1.2 * ego.length + 1.2*v.length)) and (xnormV > plan1.rangeLeft and xnormV < plan1.rangeRight) and (not (xnormV > (plan1.rangeLeft + lanew*plan1.rangeBestLane) and xnormV < (plan1.rangeLeft + lanew*(plan1.rangeBestLane+1)))) then
      if draw then obj.debugDrawProxy:drawSphere(2, vPfront, color(0,0,0,160)) end
      if draw then obj.debugDrawProxy:drawSphere(2, vPfront, color(0,0,0,160)) end
      if ego2PlVec:dot(ego.rightVec) > 0 then
        ego.ghostR = true
      -- *Check 1.1.1: check if v-vehicle is coming in opposite direction
      if ego2PlVec:dot(vdirVec) < 0 then
        -- smooth transition of dirVec if mesh is not large enough
        -- *Check 1.1.1.1: add it if it is not parallel to current path-segment
        if vdirVec:dot(dirVec) < 0.95 then
          if draw then obj.debugDrawProxy:drawSphere(2, vPfront, color(255, 0, 0, 160)) end
        v.width = v.vy:length() * 2
        local check_ahead = (ego.length * push3(ego.dirVec) - ego.pos + v.posFront):dot(ego.dirVec) > 0 --(v.posFront - (ego.pos - ego.length * ego.dirVec)):dot(ego.dirVec) > 0
        plan.distancesV = check_ahead and min(ego.pos:squaredDistance(v.posMiddle), plan.distancesV) or plan.distancesV
        v.width = v.vy:length() * 2
        local check_ahead = (ego.length * push3(ego.dirVec) - ego.pos + v.posFront):dot(ego.dirVec) > 0 --(v.posFront - (ego.pos - ego.length * ego.dirVec)):dot(ego.dirVec) > 0
        plan.distancesV = check_ahead and min(ego.pos:squaredDistance(v.posMiddle), plan.distancesV) or plan.distancesV
            local ego2PlDist = ego2PlDist_0 - ego.speed * ego.race.time_gap --max(2.5, ego.speed * 1)
            local velProjOnSeg = v.vel:dot(segDirVec) -- max(0, v.vel:dot(segDirVec))
            local gain = (ego2PlDist > 0 and ego.race.catchAgg or ego.race.brakeAgg) * abs(ego2PlDist) + 1 -- gain factor to try to catch the vehicle ahead by boosting acceleration (ego2PlDist > 0) or brake at maximum acceleration (ego2PlDist < 0)
            local ego2PlDist = ego2PlDist_0 - ego.speed * ego.race.time_gap --max(2.5, ego.speed * 1)
            local velProjOnSeg = v.vel:dot(segDirVec) -- max(0, v.vel:dot(segDirVec))
            local gain = (ego2PlDist > 0 and ego.race.catchAgg or ego.race.brakeAgg) * abs(ego2PlDist) + 1 -- gain factor to try to catch the vehicle ahead by boosting acceleration (ego2PlDist > 0) or brake at maximum acceleration (ego2PlDist < 0)
      dV:setSub2(v.vel, ego.vel)
      local dS = dP:dot(ego.dirVec) -- longitudinal distance between ego vehicle and v-vehicle
      local dD = dP:dot(nvec)      -- lateral distance between ego vehicle and v-vehicle
      local dS = dP:dot(ego.dirVec) -- longitudinal distance between ego vehicle and v-vehicle
      local dD = dP:dot(nvec)      -- lateral distance between ego vehicle and v-vehicle
      local v_rel = dV:dot(nvec)   -- lateral relative speed between ego vehicle and v-vehicle
      local dD = dP:dot(nvec)      -- lateral distance between ego vehicle and v-vehicle
      local v_rel = dV:dot(nvec)   -- lateral relative speed between ego vehicle and v-vehicle
      local a = math.exp(-square(dS / egoLength)) -- Intensity factor
    n1.turnDir:setSub2(v1, v2); n1.turnDir:normalize()
    nforce:setScaled2(n1.turnDir, (1-twt.state) * max(1 - v1:dot(v2), 0) * parameters.turnForceCoef)
    -- Calculate node displacement: avoids switching displacement direction (sign) in concecutive frames
    local displacement = max(min(n.normal:dot(forces[i]), forceMagLim), -forceMagLim)
    displacement = displacement * max(min(displacement * n.dispDir * math.huge, 1), 0) -- second term returns 0 if (displacement * n.dispDir) is negative, 1 otherwise.
    if c1 <= c2 then
      curvature = sign2(n1.turnDir:dot(n1.normal)) * c1
    else
    else
      curvature = sign2((n1.vec):dot(n1.normal) - n3vec:dot(n1.normal)) * c2
    end
    else
      curvature = sign2((n1.vec):dot(n1.normal) - n3vec:dot(n1.normal)) * c2
    end
    -- consider inclination
    gT:setSub2(n2.pos, n1.pos); gT:setScaled(gravityDir:dot(gT) / max(square(n1.length), 1e-30)) -- gravity vec parallel to road segment: positive when downhill
    local gN = gravityDir:distance(gT) -- gravity component normal to road segment
          local wp1TOwp2EdgeVec = wp2Pos_1 - wp1Pos
          if minNodeEdgeVec:dot(wp1TOwp2EdgeVec) > 0 then -- road natural continuation is up to 90 deg
            local edgeNormal = gravityDir:cross(minNodePos - wp2Pos_2):normalized()
            local wp3Pos = mapData:getEdgePositions(wp3, wp2)
            local side = sign2(edgeNormal:dot(wp3Pos) - edgeNormal:dot(minNodePos))
            table.insert(route.laneChanges, {pathIdx = route.lastLaneChangeIdx, side = side, alternate = minNode})
            local wp3Pos = mapData:getEdgePositions(wp3, wp2)
            local side = sign2(edgeNormal:dot(wp3Pos) - edgeNormal:dot(minNodePos))
            table.insert(route.laneChanges, {pathIdx = route.lastLaneChangeIdx, side = side, alternate = minNode})
      n1.turnDir:setSub2(v1, v2); n1.turnDir:normalize()
      nforce:setScaled2(n1.turnDir, (1-twt.state) * max(1 - v1:dot(v2), 0) * parameters.turnForceCoef)
      n1.turnDir:setSub2(v1, v2); n1.turnDir:normalize()
      nforce:setScaled2(n1.turnDir, (1-twt.state) * max(1 - v1:dot(v2), 0) * parameters.turnForceCoef)

      nforce:setScaled2(n1.turnDir, (1-twt.state) * max(1 - v1:dot(v2), 0) * parameters.turnForceCoef * stiff)
      dforce:setScaled2((velocities[i+1] - velocities[i]) - (velocities[i] - velocities[i-1]), parameters.turnForceCoef * damper * 0.25)
      dforce:setScaled2((velocities[i+1] - velocities[i]) - (velocities[i] - velocities[i-1]), parameters.turnForceCoef * damper * 0.25)
      dforce:setScaled2(n1.turnDir, n1.turnDir:dot(dforce))
      nforce:setAdd(dforce)
        local xnormL = xnormF > 0 and xnormF or xnormR
        if ego.speed > 1 and v.vel:dot(ego.dirVec) > 0 and xnormL > 0 and xnormL < 1 and abs(v.posFront.z - ego.pos.z) < 4 then
          -- distance from ego.pos to v.posFront or v.posRear
          -- distance from ego.pos to v.posFront or v.posRear
          local distF = (v.posFront - ego.pos):dot(ego.rightVec)
          local distR = (v.posRear - ego.pos):dot(ego.rightVec)
          local distF = (v.posFront - ego.pos):dot(ego.rightVec)
          local distR = (v.posRear - ego.pos):dot(ego.rightVec)
          -- side of v w.r.t. ego (ego -> v = 1, v <- ego = -1)
          -- relative lateral speed of v w.r.t. ego (rsLat > 0 means v is moving toward us)
          local rsLat = vRel:dot(ego.rightVec) * side
          -- time to lateral collision (> 0 means collision is imminent, < 0 means collision does not happen)
          -- relative longitudinal speed of v w.r.t. ego (rsLong > 0 means ego is moving faster than v)
          local rsLong = vRel:dot(ego.dirVec)
          -- if TTC is less than TTO or if is greater but vehicles are close to each other: ACTIVATE SIDE AVOIDANCE
          if v.dirVec:dot(ego.dirVec) > 0.3 then
            if TTC > 0 and TTC < min(3, TTO) then
                dispLeft = max(dispLeft, square(clamp(0.1 / TTC, 0, 1)))
              elseif side > 0 then -- v-vehicle is on our right side  --(and (xnormF < 0.5 or v.vel:dot(ego.dirVec) > ego.speed))
                dispRight = max(dispRight, square(clamp(0.1 / TTC, 0, 1)))
                dispLeft = max(dispLeft, 0.1)
              elseif side > 0 then -- v-vehicle is on our right side  --(and (xnormF < 0.5 or v.vel:dot(ego.dirVec) > ego.speed))
                dispRight = max(dispRight, 0.1)
        local xnorm = v.posFront:xnormOnLine(midPos + lenVec, midPos - lenVec)
        if ego.speed > 1 and v.vel:dot(ego.dirVec) > 0 and xnorm > 0 and xnorm < 1 and abs(v.posFront.z - ego.pos.z) < 4 then
          fl = fl or midPos - ego.rightVec * ego.width * 0.5 + lenVec
    nDir:setSub2(plan[2].pos, plan[1].pos); nDir:setScaled(1 / (plan[1].length + 1e-30))
    local egoPathVel = ego.vel:dot(nDir)
    local egoPathVelInv = 1 / abs(egoPathVel + 1e-30)
        local ego2PlVec = plPosFront - ego.pos
        local ego2PlDir = ego2PlVec:dot(ego.dirVec)
          v1:setSub2(n1ext, plPosRear)
          local v1dot = v1:dot(v.dirVec)
          if v1dot > 0 and v1dot < rlen then
          v1:setSub2(n2ext, plPosRear)
          v1dot = v1:dot(v.dirVec)
          if v1dot > 0 and v1dot < rlen then
        if minSqDist < square((ego.width + limWidth) * 0.8) then
          local velProjOnSeg = max(0, v.vel:dot(nDir))
            if plan.stopSeg == math.huge and v.targetType ~= 'follow' then -- apply side forces to avoid vehicles
              local side1 = sign(n1.normal:dot(v.posMiddle) - n1.normal:dot(n1.pos))
              local side2 = sign(n2.normal:dot(v.posMiddle) - n2.normal:dot(n2.pos))
            if plan.stopSeg == math.huge and v.targetType ~= 'follow' then -- apply side forces to avoid vehicles
              local side1 = sign(n1.normal:dot(v.posMiddle) - n1.normal:dot(n1.pos))
              local side2 = sign(n2.normal:dot(v.posMiddle) - n2.normal:dot(n2.pos))
              local side1 = sign(n1.normal:dot(v.posMiddle) - n1.normal:dot(n1.pos))
              local side2 = sign(n2.normal:dot(v.posMiddle) - n2.normal:dot(n2.pos))
              local side1 = sign(n1.normal:dot(v.posMiddle) - n1.normal:dot(n1.pos))
              local side2 = sign(n2.normal:dot(v.posMiddle) - n2.normal:dot(n2.pos))
                                  parameters.awarenessForceCoef *
                                  max(0, ego.speed - velProjOnSeg, -sign(nDir:dot(v.dirVec)) * trafficStates.side.cTimer) /
                                  ((1 + minSqDist) * (1 + distanceT * min(0.1, 1 / (2 * max(0, egoPathVel - v.vel:dot(nDir)) + 1e-30))))
                                  max(0, ego.speed - velProjOnSeg, -sign(nDir:dot(v.dirVec)) * trafficStates.side.cTimer) /
                                  ((1 + minSqDist) * (1 + distanceT * min(0.1, 1 / (2 * max(0, egoPathVel - v.vel:dot(nDir)) + 1e-30))))
                local Deltax = distanceT
                local factor1 = clamp(ego.vel:dot(nDir) - velProjOnSeg, 0, 4)
                local factor2 = max(0,-sign(nDir:dot(v.dirVec)) * trafficStates.side.cTimer)
                local factor1 = clamp(ego.vel:dot(nDir) - velProjOnSeg, 0, 4)
                local factor2 = max(0,-sign(nDir:dot(v.dirVec)) * trafficStates.side.cTimer)
                for ii = 2, plan.planCount-1 do
                  --local n2i = plan[ii + 1]
                  local distY = n1i.normal:dot(v.posMiddle) - n1i.normal:dot(n1i.pos)
                  --local distY = plan[1].normal:dot(v.posMiddle) - plan[1].normal:dot(ego.pos)
                  --local n2i = plan[ii + 1]
                  local distY = n1i.normal:dot(v.posMiddle) - n1i.normal:dot(n1i.pos)
                  --local distY = plan[1].normal:dot(v.posMiddle) - plan[1].normal:dot(ego.pos)
                  local distY = n1i.normal:dot(v.posMiddle) - n1i.normal:dot(n1i.pos)
                  --local distY = plan[1].normal:dot(v.posMiddle) - plan[1].normal:dot(ego.pos)
                  --local Deltax = -n2i.dirVec:dot(v.posMiddle - n1i.pos) --Need to be improved
                  local distY = n1i.normal:dot(v.posMiddle) - n1i.normal:dot(n1i.pos)
                  --local distY = plan[1].normal:dot(v.posMiddle) - plan[1].normal:dot(ego.pos)
                  --local Deltax = -n2i.dirVec:dot(v.posMiddle - n1i.pos) --Need to be improved
                  --local distY = plan[1].normal:dot(v.posMiddle) - plan[1].normal:dot(ego.pos)
                  --local Deltax = -n2i.dirVec:dot(v.posMiddle - n1i.pos) --Need to be improved
                  if ii > 2 then
              trafficMinSpeedSq = min(trafficMinSpeedSq, v.vel:squaredLength())
              minTrafficDir = min(minTrafficDir, v.dirVec:dot(nDir))
            end

            if i == 2 and minSqDist < square((ego.width + limWidth) * 0.6) and ego2PlDir > 0 and v.vel:dot(ego.rightVec) * ego2PlVec:dot(ego.rightVec) < 0 then
              n1.trafficSqVel = max(0, n1.trafficSqVel - abs(1 - v.vel:dot(ego.dirVec)) * (v.vel:length()))

            if i == 2 and minSqDist < square((ego.width + limWidth) * 0.6) and ego2PlDir > 0 and v.vel:dot(ego.rightVec) * ego2PlVec:dot(ego.rightVec) < 0 then
              n1.trafficSqVel = max(0, n1.trafficSqVel - abs(1 - v.vel:dot(ego.dirVec)) * (v.vel:length()))
            if i == 2 and minSqDist < square((ego.width + limWidth) * 0.6) and ego2PlDir > 0 and v.vel:dot(ego.rightVec) * ego2PlVec:dot(ego.rightVec) < 0 then
              n1.trafficSqVel = max(0, n1.trafficSqVel - abs(1 - v.vel:dot(ego.dirVec)) * (v.vel:length()))
            end
    -- Calculate node displacement: avoids switching displacement direction (sign) in concecutive frames
    local displacement = forceToLaneCenter + max(min(n.normal:dot(forces[i]), forceMagLim), -forceMagLim)
    displacement = displacement * max(min((displacement * n.dispDir) * math.huge, 1), 0) -- second term returns 0 if (displacement * n.dispDir) is negative, 1 otherwise.
    tmpVec:setSub2(p2, p1); tmpVec:setCross(tmpVec, ego.upVec); tmpVec:normalize()
    plan.egoDeviation = dispVec:dot(tmpVec)
      dispVec:setScaled2(dispVecRatio, dTotal - sumLen[i])
      dispVec:setSub(dispVec:dot(n.biNormal) * n.biNormal)
      n.pos:setAdd(dispVec)
    if c1 <= c2 then
      curvature = sign2(n1.turnDir:dot(n1.normal)) * c1
    else
    else
      curvature = sign2((n1.vec):dot(n1.normal) - n3vec:dot(n1.normal)) * c2
    end
    else
      curvature = sign2((n1.vec):dot(n1.normal) - n3vec:dot(n1.normal)) * c2
    end
      -- consider inclination
      gT:setSub2(n2.pos, n1.pos); gT:setScaled(gravityDir:dot(gT) / max(square(n1.length), 1e-30)) -- gravity vec parallel to road segment: positive when downhill
      local gN = gravityDir:distance(gT) -- gravity component normal to road segment
      -- consider inclination
      gT:setSub2(n2.pos, n1.pos); gT:setScaled(gravityDir:dot(gT) / max(square(n1.length), 1e-30)) -- gravity vec parallel to road segment: positive when downhill
      local gN = gravityDir:distance(gT) -- gravity component normal to road segment
    local plan = currentRoute.plan
    if ego.pos:dot(ego.dirVec) >= player.pos:dot(ego.dirVec) and not targetWPName and internalState.road ~= 'offroad' and plan.trafficMinProjSpeed > 3 then
      local path = currentRoute.path
    local plan = currentRoute.plan
    if ego.pos:dot(ego.dirVec) >= player.pos:dot(ego.dirVec) and not targetWPName and internalState.road ~= 'offroad' and plan.trafficMinProjSpeed > 3 then
      local path = currentRoute.path

  if positions[wp2]:dot(ego.dirVec) < positions[wp1]:dot(ego.dirVec) then wp1, wp2 = wp2, wp1 end
  -- wp2 is next node for ego to drive to

  if positions[wp2]:dot(ego.dirVec) < positions[wp1]:dot(ego.dirVec) then wp1, wp2 = wp2, wp1 end
  -- wp2 is next node for ego to drive to

  if (playerVel / (playerSpeed + 1e-30)):dot(positions[plwp2] - positions[plwp1]) < 0 then plwp1, plwp2 = plwp2, plwp1 end
  -- plwp2 is next node that player is driving to
    local planVec = curPlan[2].pos - curPlan[1].pos
    local playerIncoming = playerSpeed >= 3 and playerNode == wp1 and egoPlDist < max(ego.speed, playerSpeed) and playerVel:dot(planVec) < 0 -- player is driving towards or past ego on the segment
    local playerBehind = playerSpeed >= 3 and planVec:dot(playerVel) > 0 and ego.dirVec:dot(egoPosRear - player.pos) > 0 -- player got passed by ego
    local playerIncoming = playerSpeed >= 3 and playerNode == wp1 and egoPlDist < max(ego.speed, playerSpeed) and playerVel:dot(planVec) < 0 -- player is driving towards or past ego on the segment
    local playerBehind = playerSpeed >= 3 and planVec:dot(playerVel) > 0 and ego.dirVec:dot(egoPosRear - player.pos) > 0 -- player got passed by ego
    local playerOtherWay = not playerNodeInPath and planVec:dot(positions[playerNode] - ego.pos) < 0 and (playerSpeed < 3 or playerVel:dot(player.pos - ego.pos) > 0) -- player is driving other way from ego
    local playerIncoming = playerSpeed >= 3 and playerNode == wp1 and egoPlDist < max(ego.speed, playerSpeed) and playerVel:dot(planVec) < 0 -- player is driving towards or past ego on the segment
    local playerBehind = playerSpeed >= 3 and planVec:dot(playerVel) > 0 and ego.dirVec:dot(egoPosRear - player.pos) > 0 -- player got passed by ego
    local playerOtherWay = not playerNodeInPath and planVec:dot(positions[playerNode] - ego.pos) < 0 and (playerSpeed < 3 or playerVel:dot(player.pos - ego.pos) > 0) -- player is driving other way from ego
    local playerBehind = playerSpeed >= 3 and planVec:dot(playerVel) > 0 and ego.dirVec:dot(egoPosRear - player.pos) > 0 -- player got passed by ego
    local playerOtherWay = not playerNodeInPath and planVec:dot(positions[playerNode] - ego.pos) < 0 and (playerSpeed < 3 or playerVel:dot(player.pos - ego.pos) > 0) -- player is driving other way from ego
    local playerBehind = playerSpeed >= 3 and planVec:dot(playerVel) > 0 and ego.dirVec:dot(egoPosRear - player.pos) > 0 -- player got passed by ego
    local playerOtherWay = not playerNodeInPath and planVec:dot(positions[playerNode] - ego.pos) < 0 and (playerSpeed < 3 or playerVel:dot(player.pos - ego.pos) > 0) -- player is driving other way from ego
    local route
    if not playerNodeInPath and not internalState.chaseData.driveAhead and (ego.speed < 3 or ego.dirVec:dot(player.pos - ego.pos) > 0) then -- prevents ego from cancelling its current route if it should slow down to turn around
      local path = mapData:getChasePath(wp1, wp2, plwp1, plwp2, ego.pos, ego.vel, player.pos, player.vel, opt.driveInLaneFlag and 1e4 or 1)
      route = planAhead(path, currentRoute) -- ignore current route if path should go other way
      if route and route.plan then --and tempPlan.targetSpeed >= min(ego.speed, curPlan.targetSpeed) and (tempPlan.targetPos-curPlan.targetPos):dot(ego.dirVec) >= 0 then
        currentRoute = route
      local brakeDist = square(ego.speed) / (2 * g * aggression)
      local relSpeed = playerVel:dot(ego.dirVec)
      local crashSpeed = 10 -- minimum relative crash speed
      local crashSpeed = 10 -- minimum relative crash speed
      if egoPlDist < max(brakeDist, nearDist) and ego.dirVec:dot(egoPosRear - player.pos) < 0 then
        targetSpeed = max(crashSpeed, relSpeed + crashSpeed)
        internalState.road = 'tail'
      elseif egoPlDist < 25 and ego.dirVec:dot((ego.pos - ego.dirVec * ego.length) - player.pos) < 0 then -- player is near ego, but ego path does a u-turn
        local uTurn = false
          if p == playerNode then break end
          if i > 2 and ego.dirVec:dot(positions[p] - positions[currentRoute.path[i - 1]]) < 0 then
            uTurn = true
        local p2Target = tarPos - player.pos; p2Target:normalize()
        local plVel2Target = playerSpeed > 0.1 and player.vel:dot(p2Target) or 0
        local plTimeToTarget = tarPos:distance(player.pos) / (plVel2Target + 1e-30)

        local egoVel2Target = ego.speed > 0.1 and ego.vel:dot((tarPos - ego.pos):normalized()) or 0
        local egoTimeToTarget = tarPos:distance(ego.pos) / (egoVel2Target + 1e-30)
    local path
    if M.mode == 'chase' and ego.dirVec:dot(playerVel) > 0 and ego.dirVec:dot(egoPosRear - player.pos) > 0 then
      path = mapData:getFleePath(wp2, playerVel, player.pos, getMinPlanLen(100, ego.speed), 0, 0)
    local path
    if M.mode == 'chase' and ego.dirVec:dot(playerVel) > 0 and ego.dirVec:dot(egoPosRear - player.pos) > 0 then
      path = mapData:getFleePath(wp2, playerVel, player.pos, getMinPlanLen(100, ego.speed), 0, 0)
      posRelativeToPolice:normalize()
      if posRelativeToPolice:dot(police.dirVec) > 0.94 then
        if ego.speed < 10 and ego.pos:squaredDistance(police.pos) < 400 then

        if ego.dirVec:dot(police.dirVec) > 0.5 then
          -- Check if there's a vehicle next to this one
          for otherID, v in pairs(mapmgr.getObjects()) do
            if otherID ~= objectId and v.pos and otherID ~= trafficStates.action.nearestPoliceId and v.dirVec and v.dirVec:dot(ego.dirVec) < 0 then
              local distance = ego.pos:squaredDistance(v.pos)
                relativePosOtherVehicle:setSub2(v.pos, ego.pos)
                local forwardDist = relativePosOtherVehicle:dot(ego.dirVec)
                local lateralDist = relativePosOtherVehicle:dot(ego.rightVec)
                local forwardDist = relativePosOtherVehicle:dot(ego.dirVec)
                local lateralDist = relativePosOtherVehicle:dot(ego.rightVec)
          -- or if the current path edge leading to nid1 has drivability lower than other roads incident on nid1
          local giveWay = abs(nDir:dot(linkDir)) < 0.707
            local nContinuation = fourthNode and roadNaturalContinuation(fourthNode, nid1)
            local dotDir = side*gravityDir:cross(nDir):dot(linkDir)
            if not (fourthNode and nContinuation ~= nid2 and dotDir > 0) then
        if tSi.turnDir then
          if abs(tSi.dir:dot(tSi.turnDir)) < 0.707 then
            tSi.turn = -sign2(tSi.dir:cross(gravityDir):dot(tSi.turnDir))
          if abs(tSi.dir:dot(tSi.turnDir)) < 0.707 then
            tSi.turn = -sign2(tSi.dir:cross(gravityDir):dot(tSi.turnDir))
          end

    if tSi.pos:dot(tSi.dir) + 4 * tSi.dir:dot(tSi.dir) >= ego.pos:dot(tSi.dir)  then -- vehicle position is at the stop pos (with extra distance, to be safe)
      if tSi.action == 3 or tSi.action == 2 or (tSi.action == 1 and (square(brakeDist) < distSq or tSi.commitStopOnYellow)) then -- red light or other stop condition

    if tSi.pos:dot(tSi.dir) + 4 * tSi.dir:dot(tSi.dir) >= ego.pos:dot(tSi.dir)  then -- vehicle position is at the stop pos (with extra distance, to be safe)
      if tSi.action == 3 or tSi.action == 2 or (tSi.action == 1 and (square(brakeDist) < distSq or tSi.commitStopOnYellow)) then -- red light or other stop condition

    if tSi.pos:dot(tSi.dir) + 4 * tSi.dir:dot(tSi.dir) >= ego.pos:dot(tSi.dir)  then -- vehicle position is at the stop pos (with extra distance, to be safe)
      if tSi.action == 3 or tSi.action == 2 or (tSi.action == 1 and (square(brakeDist) < distSq or tSi.commitStopOnYellow)) then -- red light or other stop condition
                local checkDirRad
                if not isVehicleStopped(v) and v.dirVec:dot(vPosF - (ego.pos + distToJcenter * ego.dirVec)) < 0 then
                  checkDirRad = v.dirVec:dot(tSi.dir) < 0.707 and egoCenterPos:squaredDistance(vPosF) < square(max(min(60, max(40, v.vel:squaredLength() / (g * ego.staticFrictionCoef))), v.vel:length()*4))
                if not isVehicleStopped(v) and v.dirVec:dot(vPosF - (ego.pos + distToJcenter * ego.dirVec)) < 0 then
                  checkDirRad = v.dirVec:dot(tSi.dir) < 0.707 and egoCenterPos:squaredDistance(vPosF) < square(max(min(60, max(40, v.vel:squaredLength() / (g * ego.staticFrictionCoef))), v.vel:length()*4))
                end
                    local vFxnorm = tSi.turnDir and vPosF:xnormOnLine(tSi.pos, tSi.pos + 1.5*mapData.radius[tSi.turnNode or tSi.node]*tSi.turnDir) or 0
                    if vFxnorm > 0 and vFxnorm < 1 and v.dirVec:dot(tSi.dir) < -0.707 then
                      check = true
                  elseif tSi.otherGiveWay or tSi.turn == (mapmgr.rules.rightHandDrive and -1 or 1) then -- other or stop/full but turning to right
                    if tSi.turnDir and v.dirVec:dot(tSi.turnDir) > 0.707 then
                      check = true
      local xnorm = ego.pos:xnormOnLine(position[wp1], position[wp2])
      if xnorm >= 0 and xnorm <= 1 and (position[wp2] - position[wp1]):dot(ego.dirVec) < 0 then
        -- vehicle is within the first path segment but facing the wrong way
    local minHit = intersectsRay_OBB(ego.pos, ego2PlDirVec, plC, plX, plY, plZ)
    local plSpeedFromego = player.vel:dot(ego2PlDirVec)
    local ego2PlDist = minHit - (distLim or 3)
  -- local wp1, wp2 = mapmgr.findClosestRoad(ego.pos)
  -- if (mapData.positions[wp2] - mapData.positions[wp1]):dot(ego.dirVec) > 0 then
  --   wp1, wp2 = wp2, wp1
        local vec2 = mapData.positions[wp2] - ego.pos
        if ego.dirVec:dot(vec1) > 0 and ego.dirVec:dot(vec2) > 0 then
          if vec1:squaredLength() > vec2:squaredLength() then
        local vec2 = mapData.positions[wp2] - ego.pos
        if ego.dirVec:dot(vec1) > 0 and ego.dirVec:dot(vec2) > 0 then
          if vec1:squaredLength() > vec2:squaredLength() then
          end
        elseif ego.dirVec:dot(mapData.positions[wp2] - mapData.positions[wp1]) > 0 then
          wp1, wp2 = wp2, wp1
        end
      elseif ego.dirVec:dot(mapData.positions[wp2] - mapData.positions[wp1]) > 0 then
        wp1, wp2 = wp2, wp1
      if player ~= nil then
        if (ego.pos - player.pos):dot(ego.dirVec) > 0 then
          setAggressionInternal(max(min(0.1 + max((150 - player.pos:distance(ego.pos)) / 150, 0), M.extAggression), 0.5))
            local dSqLengthInv = 1/(d:squaredLength() + 1e-30)
            local kcurvature = 2 * abs(d:dot(n)) * dSqLengthInv
            local axSq = square(0.5 * max(egoSqspeed - square(kplan[kplan.targetSeg].speed), 0)) * dSqLengthInv
            local dSqLengthInv = 1/(d:squaredLength() + 1e-30)
            local kcurvature = 2 * abs(d:dot(n)) * dSqLengthInv
            local axSq = square(0.5 * max(egoSqspeed - square(kplan[kplan.targetSeg].speed), 0)) * dSqLengthInv
            local targetPos = plan_index == 1 and currentRoute.planL.targetPos or currentRoute.planR.targetPos
            local targetError = (push3(mainPlan.targetPos) - targetPos):dot(mainPlan[mainPlan.targetSeg].normal)
            if square(targetError) < 0.8 or (plan_index == 1 and targetError < 0) or (plan_index == 2 and targetError > 0) then
      end
      if ego.dirVec:dot(positions[wpFore] - positions[wpAft]) < 0 then wpAft, wpFore = wpFore, wpAft end
        local plego = player.pos - ego.pos
        local relvel = ego.vel:dot(plego) - player.vel:dot(plego)
        local plego = player.pos - ego.pos
        local relvel = ego.vel:dot(plego) - player.vel:dot(plego)
      currentRoute.plan.targetSpeed = min(currentRoute.plan.targetSpeed, targetSpeed)
    elseif ego.vel:dot(ego.dirVec) > 0 then
      driveCar(0, 0, 0.5, 0)

    if ego.upVec:dot(gravityDir) >= -0.2588 then -- vehicle upside down
      driveCar(0, 0, 0, 0)
    local lowTargetSpeedVal = 0.24
    if not plan[egoSeg+2] and ((targetSpeed < lowTargetSpeedVal and ego.speed < 0.15) or (targetPos - ego.pos):dot(ego.dirVec) < 0) then
      if M.mode == 'span' then
@/lua/ge/extensions/editor/aiViz.lua
          while edgeProgress <= edgeLength do
            color = core_camera.getForward():dot(edgeDirVec) >= 0 and arrowBaseColor or arrowAltColor
            debugDrawer:drawSquarePrism((inNodePos + edgeProgress * edgeDirVec), (inNodePos + (edgeProgress + 2) * edgeDirVec), arrowSize1, arrowSize2, color)
@/lua/ge/extensions/scenario/busdriver.lua
  local pos1 = mapData.nodes[second].pos
  return (pos1-pos0):normalized():cross(vec3(0, 0, 1)):dot((triggerPos-pos0):normalized()) > 0
end
      local fwdAligned = fwd:projectToOriginPlane(busStopUp):normalized()
      dotAngle = abs(fwdAligned:dot(busStopFwd))
      if dotAngle < 0.70710678118 then
        busStopFwd = busStopFwd:cross(busStopUp):normalized()
        dotAngle = abs(fwdAligned:dot(busStopFwd))
      end
    -- local vLeftVec=vDirVec:cross(vUpVec)
    local front = ((vDirVec:dot(yVec) > 0) and 1 or 0) +1
    local contained = false
@/lua/ge/extensions/core/ropeVisualTest.lua
  local oc = rayOrigin - sphereCenter
  local a = rayDir:dot(rayDir)
  local b = 2.0 * oc:dot(rayDir)
  local a = rayDir:dot(rayDir)
  local b = 2.0 * oc:dot(rayDir)
  local c = oc:dot(oc) - sphereRadius * sphereRadius
  local b = 2.0 * oc:dot(rayDir)
  local c = oc:dot(oc) - sphereRadius * sphereRadius
  local discriminant = b * b - 4 * a * c
  -- Intersect ray with drag plane
  local denom = dragPlaneNormal:dot(rayDir)
  if math.abs(denom) > 0.0001 then
  if math.abs(denom) > 0.0001 then
    local t = -(dragPlaneNormal:dot(rayOrigin) - dragPlaneDist) / denom
    if t > 0 then
@/lua/ge/extensions/tech/sensors.lua
  local c = math.cos(theta)
  return v * c + k:cross(v) * math.sin(theta) + k * k:dot(v) * (1.0 - c)
end
-- Computes the (small) angle between two unit vectors, in radians.
local function angleBetweenVecsNorm(a, b) return math.acos(a:dot(b)) end
@/lua/ge/extensions/gameplay/sites/zone.lua
function C:validPlanes()
  return self.top.active and self.top.normal:dot(vec3(0,0, 1)) > 0
     and self.bot.active and self.bot.normal:dot(vec3(0,0,-1)) > 0
  return self.top.active and self.top.normal:dot(vec3(0,0, 1)) > 0
     and self.bot.active and self.bot.normal:dot(vec3(0,0,-1)) > 0
end
  if self.top.active then
    if (point - self.top.pos):dot(self.top.normal) > 0 then
      return false
  if self.bot.active then
    if (point - self.bot.pos):dot(self.bot.normal) > 0 then
      return false
  local l = vec3(0,0,1)
  local ln = l:dot(plane.normal)
  if math.abs(ln) <= 1e-30 then
  end
  local d = (plane.pos - vertex):dot(plane.normal) / ln
  return vertex + vec3(0,0,d)
@/lua/ge/extensions/editor/camPathEditor.lua
      -- Fix rotations
      if r2:dot(r1) < 0 then
        r2 = -r2
      end
      if r3:dot(r2) < 0 then
        r3 = -r3
      end
      if r4:dot(r3) < 0 then
        r4 = -r4
  for i = 1, #markers - 1 do
    if markers[i].rot:dot(markers[i + 1].rot) < 0 then
      markers[i + 1].rot = -markers[i + 1].rot
@/lua/vehicle/input.lua
  local speedThreshold = 13
  local velRightCos = velVec:dot(rightVec) / (velLen + 1e-10)
  local oversteer = lowSpeedCoef * min(velLen / speedThreshold, 1) * velRightCos
    local margin = sign(st) == sign(oversteer) and -1 or 0.15
    local oversteerMult = 1 - clamp(5 * (abs(lowSpeedCoef * min(velLen / speedThreshold, 1) * sqrt(1 - max(0, velVec:dot(frontVec) / (velLen + 1e-10)))) - margin), 0, 1) -- zero while driving straight ahead (with a deadzone of 'margin' around 'straight ahead'); and 1 when sliding, spinning out, or driving in reverse
    local overSm = smOversteer:getWithRateUncapped(oversteerMult, dt, 3.0) -- avoid sudden inputs if e.g. spinning out fast
@/lua/ge/extensions/gameplay/race/race.lua
        vehDir:set(veh:getDirectionVectorXYZ())
        local dir = sign2(vehDir:dot(vehVel)) -- negative if driving in reverse
      local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      table.insert(self.states[newId].wheelOffsets, pos)
      local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      table.insert(self.states[newId].wheelOffsets, pos)
      local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      table.insert(self.states[newId].wheelOffsets, pos)
          local nodePos = vec3(veh:getNodePosition(axisNodes[1]))
          local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
          table.insert(self.states[id].wheelOffsets, pos)
          local nodePos = vec3(veh:getNodePosition(axisNodes[1]))
          local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
          table.insert(self.states[id].wheelOffsets, pos)
          local nodePos = vec3(veh:getNodePosition(axisNodes[1]))
          local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
          table.insert(self.states[id].wheelOffsets, pos)
@/lua/vehicle/controller/drivingDynamics/sensors/vehicleData.lua
      local wheelVector = wheelNodePos - avgWheelPos
      local dotForward = vectorForward:dot(wheelVector)
      local dotLeft = vectorRight:dot(wheelVector)
      local dotForward = vectorForward:dot(wheelVector)
      local dotLeft = vectorRight:dot(wheelVector)
      wheelCount = wheelCount + 1
@/lua/ge/extensions/core/cameraModes/chase.lua
  local vel = (data.pos - self.lastDataPos) / data.dt
  local velF = vel:dot(dir)
  local velNF = vel:distance(velF * dir)
@/lua/ge/extensions/editor/gen/exp_meshexplorer.lua
--                    m.verts[ind] =  v + vec3(1,0,0)
                    m.verts[ind] = line.ab[1] + (v-line.ab[1]):dot(u)*u + vx*va.x + vy*va.y - pos
--                        set[#set+1] = line.ab[1] + (v-line.ab[1]):dot(u)*u
                    m.verts[ind] = line.ab[1] + (v-line.ab[1]):dot(u)*u + vx*va.x + vy*va.y - pos
--                        set[#set+1] = line.ab[1] + (v-line.ab[1]):dot(u)*u
--                        apath[#apath+1] = {v,set[#set]}
@/lua/ge/extensions/gameplay/rally/cameraPathPlayer.lua
    if res.markers[i] then
      if res.markers[i].rot:dot(res.markers[i - 1].rot) < 0 then
        res.markers[i].rot = -res.markers[i].rot
@/lua/ge/extensions/gameplay/rally/geometry.lua
  local bsql = d2:squaredLength()
  local adotb = d1:dot(d2)
@/lua/vehicle/extensions/escMeasurement.lua
    local directionVector = obj:getDirectionVector()
    local actualVelocity = (directionVector:dot(velocity) / (directionVector:length() * directionVector:length()) * directionVector):length()
    local velocityVector = vec3(velocity.x, velocity.y, 0)
    local velocityVector = vec3(velocity.x, velocity.y, 0)
    local dot = velocityVector:dot(directionVector)
    local floatAngle = acos(min(max(dot / (directionVector:length() * velocityVector:length()), -1), 1))
@/lua/ge/extensions/util/trackBuilder/splineTrack.lua
  local adjustedPoint = point - trackPosition.position
  local intX = adjustedPoint:dot(trackPosition.unitX) / (math.sqrt(3) / 2)
  local intY = adjustedPoint:dot(trackPosition.unitY) / 0.5
  local intX = adjustedPoint:dot(trackPosition.unitX) / (math.sqrt(3) / 2)
  local intY = adjustedPoint:dot(trackPosition.unitY) / 0.5
  local originalZ = adjustedPoint.z
@/lua/ge/extensions/gameplay/sites/parkingSpot.lua

    return math.abs(offset:dot(dx)) <= self.scl.x / 2 and math.abs(offset:dot(dx)) <= self.scl.y / 2 and math.abs(offset:dot(dx)) <= self.scl.z / 2
  end

    return math.abs(offset:dot(dx)) <= self.scl.x / 2 and math.abs(offset:dot(dx)) <= self.scl.y / 2 and math.abs(offset:dot(dx)) <= self.scl.z / 2
  end

    return math.abs(offset:dot(dx)) <= self.scl.x / 2 and math.abs(offset:dot(dx)) <= self.scl.y / 2 and math.abs(offset:dot(dx)) <= self.scl.z / 2
  end
      parkingSpotDir:setRotate(self.rot)
      local parkingDir = vehicleDir:dot(parkingSpotDir)
    local posOffset = (pos - fl)
    local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
    local posOffset = (pos - fl)
    local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
    local posOffset = (pos - fl)
    local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
@/lua/ge/extensions/core/cameraModes/crash.lua
      local driverPos = veh2:getPosition() + veh2:getNodePosition(driverNode)
      if veh2:getDirectionVector():dot(bb1:getCenter() - driverPos) > 0 then
        self.cockpitView = true
@/lua/ge/extensions/gameplay/crawl/boundary.lua
      local worldUp = vec3(0, 0, 1)
      local terrainUpDot = terrainNormal:dot(worldUp)
@/lua/ge/extensions/gameplay/markers/inspectVehicleMarker.lua

    tmpZ:setScaled(tmpVec:dot(tmpY) / 25)
    self.iconPos:setAdd(tmpZ)
@/lua/ge/extensions/freeroam/dragRace.lua
      -- We need actual distance from starting line and not the center
      local dot = vec3(nodePos.x, nodePos.y, nodePos.z):dot(vehicle:getDirectionVector():normalized())
      maxFwd = math.max(dot, maxFwd)

    local dot = centerPointToTrigger:dot(vehicle:getDirectionVector():normalized())
    local distanceFromStart = -dot
@/lua/vehicle/controller/tech/advancedIMU.lua
  local gravity = obj:getGravityVector() -- Gravity vector in world space.
  return gravity:dot(forwardWS), gravity:dot(upWS), gravity:dot(rightWS) -- Transform gravity from world space to the sensor frame.
end
  local gravity = obj:getGravityVector() -- Gravity vector in world space.
  return gravity:dot(forwardWS), gravity:dot(upWS), gravity:dot(rightWS) -- Transform gravity from world space to the sensor frame.
end
  local gravity = obj:getGravityVector() -- Gravity vector in world space.
  return gravity:dot(forwardWS), gravity:dot(upWS), gravity:dot(rightWS) -- Transform gravity from world space to the sensor frame.
end
  curl:setAdd(tempVec3)
  local divergence = r1:dot(aRot1) * state.w1 + r2:dot(aRot2) * state.w2 + r3:dot(aRot3) * state.w3 -- The divergence at the projected point.
  curl:setAdd(tempVec3)
  local divergence = r1:dot(aRot1) * state.w1 + r2:dot(aRot2) * state.w2 + r3:dot(aRot3) * state.w3 -- The divergence at the projected point.
  curl:setAdd(tempVec3)
  local divergence = r1:dot(aRot1) * state.w1 + r2:dot(aRot2) * state.w2 + r3:dot(aRot3) * state.w3 -- The divergence at the projected point.
  -- Transform the total acceleration vector to world space.
  accel:set(totalAccel:dot(forwardWS), totalAccel:dot(upWS), totalAccel:dot(rightWS))
  -- Transform the total acceleration vector to world space.
  accel:set(totalAccel:dot(forwardWS), totalAccel:dot(upWS), totalAccel:dot(rightWS))
  -- Transform the total acceleration vector to world space.
  accel:set(totalAccel:dot(forwardWS), totalAccel:dot(upWS), totalAccel:dot(rightWS))
@/lua/vehicle/controller/esc.lua
    local directionVector = obj:getDirectionVector()
    local actualVelocity = (directionVector:dot(velocity) / (directionVector:length() * directionVector:length()) * directionVector):length()
    local velocityVector = vec3(velocity.x, velocity.y, 0)
    local velocityVector = vec3(velocity.x, velocity.y, 0)
    local dot = velocityVector:dot(directionVector)
    local floatAngle = acos(min(max(dot / (directionVector:length() * velocityVector:length()), -1), 1))
    local wheelVector = wheelNodePos - avgWheelPos --create a vector from our "center" to the wheel
    local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
    local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
    local dotForward = vectorForward:dot(wheelVector) --calculate dot product of said vector and forward vector
    local dotLeft = vectorRight:dot(wheelVector) --calculate dot product of said vector and left vector
@/lua/ge/extensions/util/screenshotCreator.lua
  -- split that offset into components using the vehicle unit vectors
  local xOff = x:dot(vehToCam)
  local yOff = y:dot(vehToCam)
  local xOff = x:dot(vehToCam)
  local yOff = y:dot(vehToCam)
  local zOff = z:dot(vehToCam)
  local yOff = y:dot(vehToCam)
  local zOff = z:dot(vehToCam)
  local offset = vec3(xOff, yOff, zOff)
@/lua/ge/extensions/core/cameraModes/onboard.lua
  if data.lookBack then
    qdir = rotateEuler(math.rad(180),0,math.atan2(rotatedUp:dot(camLeft), rotatedUp:dot(camUp)),qdir)
    data.res.pos:set(data.veh:getSpawnWorldOOBBRearPoint())
  if data.lookBack then
    qdir = rotateEuler(math.rad(180),0,math.atan2(rotatedUp:dot(camLeft), rotatedUp:dot(camUp)),qdir)
    data.res.pos:set(data.veh:getSpawnWorldOOBBRearPoint())
  else
    qdir = rotateEuler(math.rad(self.camRot.x), math.rad(self.camRot.y), math.atan2(rotatedUp:dot(camLeft), rotatedUp:dot(camUp)), qdir)
    data.res.pos:setAdd2(carPos, nodePos)
  else
    qdir = rotateEuler(math.rad(self.camRot.x), math.rad(self.camRot.y), math.atan2(rotatedUp:dot(camLeft), rotatedUp:dot(camUp)), qdir)
    data.res.pos:setAdd2(carPos, nodePos)
@/lua/ge/extensions/util/trackBuilder/pieces.lua
      noPoints = empty or false,
      globalPosition = vec3(globalPos:dot(tp.unitX ), globalPos:dot(tp.unitY )),
      localPosition =  vec3(localPos:dot(localUnitX), localPos:dot(localUnitY)),
      noPoints = empty or false,
      globalPosition = vec3(globalPos:dot(tp.unitX ), globalPos:dot(tp.unitY )),
      localPosition =  vec3(localPos:dot(localUnitX), localPos:dot(localUnitY)),
      globalPosition = vec3(globalPos:dot(tp.unitX ), globalPos:dot(tp.unitY )),
      localPosition =  vec3(localPos:dot(localUnitX), localPos:dot(localUnitY)),
      globalHdg = pos.hdg + dirOff - tp.hdg,
      globalPosition = vec3(globalPos:dot(tp.unitX ), globalPos:dot(tp.unitY )),
      localPosition =  vec3(localPos:dot(localUnitX), localPos:dot(localUnitY)),
      globalHdg = pos.hdg + dirOff - tp.hdg,
@/lua/ge/extensions/flowgraph/nodes/gameplay/rally/rallyMoveVehicleTo.lua
    local posOffset = pos - frontBottom
    local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
    local posOffset = pos - frontBottom
    local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
    local posOffset = pos - frontBottom
    local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
@/lua/ge/extensions/gameplay/statisticModules/watchJturn.lua

  if vdir:dot(velocity) < -THRESHOLD then
    triggered = true
  if triggered then
    if vdir:dot(velocity) > THRESHOLD and backingdir:dot(velocity) < THRESHOLDUTURN then
      frontTimer = frontTimer - dtSim
  if triggered then
    if vdir:dot(velocity) > THRESHOLD and backingdir:dot(velocity) < THRESHOLDUTURN then
      frontTimer = frontTimer - dtSim
  -- print(simTime)
  -- if upWorldVector:dot(vup) > THRESHOLD then
  --   if triggered then
  -- end
  -- if upWorldVector:dot(vup) < -THRESHOLD and abs(vdir:dot(velocity)) lastRoof+REFRESH then
  --   log("I","","roof")
  -- end
  -- if upWorldVector:dot(vup) < -THRESHOLD and abs(vdir:dot(velocity)) lastRoof+REFRESH then
  --   log("I","","roof")
  -- end
  -- if upWorldVector:dot(vup) < -THRESHOLD and abs(vdir:dot(velocity)) lastRoof+REFRESH then
  --   log("I","","roof")
  -- end
  -- print( dumps(upWorldVector:dot(vup)).."\t"..dumps(vdir:dot(velocity)) .."\ttr="..dumps(triggered) )
end
  -- end
  -- print( dumps(upWorldVector:dot(vup)).."\t"..dumps(vdir:dot(velocity)) .."\ttr="..dumps(triggered) )
end
  debugDrawer:drawCylinder(vpos, vpos+velocity, 0.05, ColorF(0,1,0,1), false)
  debugDrawer:drawCylinder(vpos, vpos+vdir*vdir:dot(velocity), 0.05, ColorF(1,1,0,1), false)
end
@/lua/ge/extensions/core/cameraModes/relative.lua
      local pos = data.pos - carPos
      pos = vec3(pos:dot(nx), pos:dot(ny), pos:dot(nz))
      pos.z = ref.z
      local pos = data.pos - carPos
      pos = vec3(pos:dot(nx), pos:dot(ny), pos:dot(nz))
      pos.z = ref.z
      local pos = data.pos - carPos
      pos = vec3(pos:dot(nx), pos:dot(ny), pos:dot(nz))
      pos.z = ref.z
@/lua/ge/extensions/editor/masterSpline/homologation.lua
    sideAxis:normalize()
    local bankComponent = nml:dot(sideAxis) -- The lateral component of the normal.
    bankComponent = clamp(bankComponent, -1, 1)
@/lua/ge/extensions/editor/meshSpline/import.lua
  -- Compare spline tangent with mesh X-axis to determine rotation.
  local dotProduct = splineTangent:dot(meshXAxis)
  if abs(dotProduct) > 0.707 then -- Tangent is roughly aligned with mesh X-axis
@/lua/ge/extensions/editor/scriptAIEditor.lua
  local ab, av  = b - a, v - a
  if av:dot(ab) <= 0.0 then
    return av:length()
  local bv  = v - b
  if bv:dot(ab) >= 0.0 then
    return bv:length()
  local pMinusB = p - rayPos
  local t0 = rayDir:dot(pMinusB) / rayDir:dot(rayDir)
  if t0 > 0 then
  local pMinusB = p - rayPos
  local t0 = rayDir:dot(pMinusB) / rayDir:dot(rayDir)
  if t0 > 0 then
    end
    if r2:dot(r1) < 0 then
      r2 = -r2
    end
    if r3:dot(r2) < 0 then
      r3 = -r3
    end
    if r4:dot(r3) < 0 then
      r4 = -r4
@/lua/ge/extensions/freeroam/bigMapMode.lua
        local vehDir = playerVehicle:getDirectionVector()
        local vehicleDirLocalX, vehicleDirLocalY = vehDir:dot(core_camera.getRight()), vehDir:dot(core_camera.getUp())
        local vehicleDirXYLocal = vec3(vehicleDirLocalX,vehicleDirLocalY,0)
        local vehDir = playerVehicle:getDirectionVector()
        local vehicleDirLocalX, vehicleDirLocalY = vehDir:dot(core_camera.getRight()), vehDir:dot(core_camera.getUp())
        local vehicleDirXYLocal = vec3(vehicleDirLocalX,vehicleDirLocalY,0)
        local det = vehicleDirLocalX * yVector.y - vehicleDirLocalY * yVector.x
        local angle = math.atan2(det, vehicleDirXYLocal:dot(yVector))
        iconInfo.rotation = angle
          local camVec = camData.res.pos - camPath.markers[1].pos
          local dotProduct = lineP1P3:dot(camVec)
          camData.res.pos = camPath.markers[1].pos + (lineP1P3:normalized() * (dotProduct / lineP1P3:length()))
          local camVec = camData.res.pos - camPath.markers[2].pos
          local dotProduct = lineP2P4:dot(camVec)
          camData.res.pos = camPath.markers[2].pos + (lineP2P4:normalized() * (dotProduct / lineP2P4:length()))
@/lua/ge/extensions/gameplay/race/pacenote.lua
  if self.hasNormal then
    return inside and ((pos-self.pos):normalized():dot(self.normal) >= 0)
  else
@/lua/ge/extensions/gameplay/statisticModules/watchRollover.lua
  end
  if vup.z < -THRESHOLD and abs(vdir:dot(velocity)) lastRoof+REFRESH then
    -- log("I","","roof")
  end
  if vup.z < -THRESHOLD and abs(vdir:dot(velocity)) lastRoof+REFRESH then
    -- log("I","","roof")
  end
  -- print( dumps(vup.z).."\t"..dumps(vdir:dot(velocity)) .."\ttr="..dumps(triggered) )
end
  debugDrawer:drawCylinder(vpos, vpos+velocity, 0.05, ColorF(0,1,0,1), false)
  debugDrawer:drawCylinder(vpos, vpos+vright*vright:dot(velocity), 0.05, ColorF(1,1,0,1), false)
  -- debugDrawer:drawCylinder(vpos, vpos+vright*vright:dot(velocity)+vup*vup:dot(velocity), 0.05, ColorF(1,1,0,1), false)
  debugDrawer:drawCylinder(vpos, vpos+vright*vright:dot(velocity), 0.05, ColorF(1,1,0,1), false)
  -- debugDrawer:drawCylinder(vpos, vpos+vright*vright:dot(velocity)+vup*vup:dot(velocity), 0.05, ColorF(1,1,0,1), false)
end
  debugDrawer:drawCylinder(vpos, vpos+vright*vright:dot(velocity), 0.05, ColorF(1,1,0,1), false)
  -- debugDrawer:drawCylinder(vpos, vpos+vright*vright:dot(velocity)+vup*vup:dot(velocity), 0.05, ColorF(1,1,0,1), false)
end
@/lua/ge/extensions/gameplay/rally/loop/stagedCountdownUtils.lua
  tmpToVehicle:setSub2(vehPos, planePos)
  local signedDistance = tmpToVehicle:dot(tmpPlaneNormal)
@/lua/ge/extensions/editor/gen/exp_solidflex.lua
    local cup = U.proj(cu, w):normalized()
    local da = cup:cross(cu):dot(ax[2]-ax[1])
--        lo('?? toTarget:'..i..':'..da..':'..#ahist)
            local cup = U.proj(cu, w):normalized()
            local da = cup:cross(cu):dot(ax[2]-ax[1])
            ac[i+1] = ac[i+1] - da/100
                local cup = U.proj(cu, w):normalized()
                local da = cup:cross(cu):dot(ax[2]-ax[1])
    --            local da = cu:cross(u):length()
@/lua/ge/extensions/gameplay/crawl/utils.lua
          local approachDir = (pathnode.pos - vehPos):normalized()
          local approachDot = pathnodeForward:dot(approachDir)
          local approachValid = approachDot > 0.5
          -- Check vehicle facing direction matches pathnode direction
          local facingDot = pathnodeForward:dot(vehDirection)
          local facingValid = facingDot > 0.5
          if vehTravelDir then
            local velocityDot = pathnodeForward:dot(vehTravelDir)
            velocityValid = velocityDot > 0.5
      local nodePos = vec3(veh:getNodePosition(axisNodes[1]))
      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      table.insert(cD.dynamicData.wheelOffsets, pos)
      local nodePos = vec3(veh:getNodePosition(axisNodes[1]))
      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      table.insert(cD.dynamicData.wheelOffsets, pos)
      local nodePos = vec3(veh:getNodePosition(axisNodes[1]))
      local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
      table.insert(cD.dynamicData.wheelOffsets, pos)
  tmp2.z = 0
  local dot = tmp1:dot(tmp2)
  if dot < drivingBackwardsSettings.velocityDotThreshold then
@/lua/ge/extensions/gameplay/traffic/trafficUtils.lua
        tempPos:normalize()
        relSpeed = clamp(tempDir:dot(tempPos), 0, 50)
        local relSpeedCoef = 1.4 -- artificial coefficient, for a stricter result
        tempDir:normalize()
        if spawnData.dir:dot(tempDir) < 0 then
          tempDir:setScaled(-1)
        tempDir:normalize()
        if spawnData.dir:dot(tempDir) < 0 then
          tempDir:setScaled(-1)
    tempDir:setSub2(p2, p1)
    if tempDir:dot(startDir) < 0 then -- if true, swap the nodes
      n1, n2 = n2, n1
@/lua/ge/extensions/flowgraph/nodes/vehicle/special/wheelDistance.lua
      wheelNodePosToTrigger:setSub2(wheelNodePos, vehCenter) -- direction vector from vehicle center
      if not self.data.onlyUseFrontWheels or dirVec:dot(wheelNodePosToTrigger) > 0 then -- assumes front wheels if dot is positive
        wheelNodePosToTrigger:setSub2(wheelNodePos, target) -- direction vector from target position
        -- We need actual distance from starting line and not the center
        local dot = wheelNodePosToTrigger:normalized():dot(dirVec:normalized())
        local distance = (wheelNodePosToTrigger * dot):len()
    pointToTrigger.z = 0
    local dot = pointToTrigger:dot(dirVec:normalized())
    local distanceFromStart = -dot --(vehicle:getDirectionVector() * dot):len()
@/lua/ge/extensions/editor/toolUtilities/render.lua
  tmpB:normalize()
  local angle = acos(tmpA:dot(tmpB)) -- The angle between the two vectors.
  local step = -sign2(twistAngle) * angle * numArcSegmentsInv
              local normal = spline.nmls[j]
              local dp = globalUp:dot(tmpTgt)
              tmpScale:setScaled2(tmpTgt, dp)
@/inspector/External/three.js/three.js

                r = vFrom.dot( vTo ) + 1;

            var scalar = vector.dot( this ) / vector.lengthSq();

                return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );

            var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
                    // project all 3 vertices of the triangle onto the seperating axis
                    var p0 = v0.dot( testAxis );
                    var p1 = v1.dot( testAxis );
                    var p0 = v0.dot( testAxis );
                    var p1 = v1.dot( testAxis );
                    var p2 = v2.dot( testAxis );
                    var p1 = v1.dot( testAxis );
                    var p2 = v2.dot( testAxis );
                    // actual test, basically see if either of the most extreme of the triangle points intersects r
            this.normal.copy( normal );
            this.constant = - point.dot( this.normal );

            return this.normal.dot( point ) + this.constant;

                var denominator = this.normal.dot( direction );

                var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;

                this.constant = - referencePoint.dot( normal );

            this.constant -= offset.dot( this.normal );

    var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";

    var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n";

    var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif\n";

    var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif\n";

    var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";

    var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";

    var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";

    var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";

    var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";

    var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";

    var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";

    var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1  (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale =  bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n";

    var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1  (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale =  bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n";

    var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n";

    var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n";

    var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n";

    var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n";

    var lights_pars_begin = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n";

    var lights_pars_begin = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n";

    var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n";

    var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(    0, 1,    0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";

    var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(    0, 1,    0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";

    var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256.,  256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";

            var directionDistance = target.dot( this.direction );

                var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
                var segExtent = v0.distanceTo( v1 ) * 0.5;
                var a01 = - this.direction.dot( segDir );
                var b0 = diff.dot( this.direction );
                var a01 = - this.direction.dot( segDir );
                var b0 = diff.dot( this.direction );
                var b1 = - diff.dot( segDir );
                var b0 = diff.dot( this.direction );
                var b1 = - diff.dot( segDir );
                var c = diff.lengthSq();
                v1.subVectors( sphere.center, this.origin );
                var tca = v1.dot( this.direction );
                var d2 = v1.dot( v1 ) - tca * tca;
                var tca = v1.dot( this.direction );
                var d2 = v1.dot( v1 ) - tca * tca;
                var radius2 = sphere.radius * sphere.radius;

            var denominator = plane.normal.dot( this.direction );

            var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;

            var denominator = plane.normal.dot( this.direction );
                //   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
                var DdN = this.direction.dot( normal );
                var sign;
                diff.subVectors( this.origin, a );
                var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );

                var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
                // Line intersects triangle, check if ray does.
                var QdN = - sign * diff.dot( normal );

                var startEnd2 = startEnd.dot( startEnd );
                var startEnd_startP = startEnd.dot( startP );
                var startEnd2 = startEnd.dot( startEnd );
                var startEnd_startP = startEnd.dot( startP );

                var dot00 = v0.dot( v0 );
                var dot01 = v0.dot( v1 );
                var dot00 = v0.dot( v0 );
                var dot01 = v0.dot( v1 );
                var dot02 = v0.dot( v2 );
                var dot01 = v0.dot( v1 );
                var dot02 = v0.dot( v2 );
                var dot11 = v1.dot( v1 );
                var dot02 = v0.dot( v2 );
                var dot11 = v1.dot( v1 );
                var dot12 = v1.dot( v2 );
                var dot11 = v1.dot( v1 );
                var dot12 = v1.dot( v2 );
    //  - followed by an optional right bracket (found when array index)
    //  - followed by an optional left bracket or dot (type of subscript)
    //

            if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {

                    theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors

                theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
                theta /= segments;

                if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
@/lua/ge/extensions/editor/gen/exp_frame.lua
                local w = u:cross(v)
                local a = w:normalized():dot(body.pelvic.r)
            a = U.vang(v,body.tibia_l.r)
    --        s = s + rec('teb_fem_l_ang', (v:dot(body.pelvic.r)>0 and 0.02 or 0.4)*a)
    --        s = s + rec('teb_fem_l_ang', (v:dot(body.pelvic.r)>0 and (cfix == 'r' and 0.03 or 0.04) or 0.2)*a)
    --        s = s + rec('teb_fem_l_ang', (v:dot(body.pelvic.r)>0 and 0.02 or 0.4)*a)
    --        s = s + rec('teb_fem_l_ang', (v:dot(body.pelvic.r)>0 and (cfix == 'r' and 0.03 or 0.04) or 0.2)*a)
--            s = s + rec('teb_fem_l_ang', (0.001+math.pow(0.2/d,2))*math.pow(5*a,2))
            s = s + rec('tib_fem_l_dir', tf_dir(body.tibia_l.r, v))
--            a = body.tibia_l.r:cross(v):normalized():dot(body.pelvic.r)
--            s = s + rec('tib_fem_l_dir', (a>0 and 0.0001 or 0.001)*math.pow(1-a,1))
            a = U.vang(v,body.tibia_r.r)
    --        s = s + rec('teb_fem_r_ang', (v:dot(body.pelvic.r)>0 and 0.02 or 0.4)*a)
--            s = s + rec('teb_fem_r_ang', (0.001+math.pow(0.1/d,2))*math.pow(5*a,2))
            s = s + rec('tib_fem_r_dir', tf_dir(body.tibia_r.r, v))
--            a = body.tibia_r.r:cross(v):normalized():dot(body.pelvic.r)
            a = U.vang(body.femur_l.r,body.tibia_l.r)
    --        s = s + rec('teb_fem_l_ang', (v:dot(body.pelvic.r)>0 and 0.02 or 0.4)*a)
    --        s = s + rec('teb_fem_l_ang', (v:dot(body.pelvic.r)>0 and (cfix == 'r' and 0.03 or 0.04) or 0.2)*a)
    --        s = s + rec('teb_fem_l_ang', (v:dot(body.pelvic.r)>0 and 0.02 or 0.4)*a)
    --        s = s + rec('teb_fem_l_ang', (v:dot(body.pelvic.r)>0 and (cfix == 'r' and 0.03 or 0.04) or 0.2)*a)
            s = s + rec('teb_fem_l_ang', (0.001+math.pow(0.2/d,2))*math.pow(5*a,2))
            a = U.vang(body.femur_r.r,body.tibia_r.r)
    --        s = s + rec('teb_fem_r_ang', (v:dot(body.pelvic.r)>0 and 0.02 or 0.4)*a)
            s = s + rec('teb_fem_r_ang', (0.001+math.pow(0.1/d,2))*math.pow(5*a,2))
        v = body.tibia_l.r:cross(body.femur_l.r)
        a = 1-math.abs(v:normalized():dot(body.pelvic.r))
--        s = s + rec('tib_fem_l_vs_pel',0.1*a*(1+1/math.pow(d,1)))
--        s = s + rec('tib_fem_l_vs_pel',
--            (v:normalized():dot(body.pelvic.r)>0 and 0.00 or 0.1)*v:length()*(1+1/math.pow(d,1)))
--            (v:normalized():dot(body.pelvic.r)>0 and 0.02 or 0.1)*v:length()*a*(1+1/math.pow(d,1)))
--            (v:normalized():dot(body.pelvic.r)>0 and 0.00 or 0.1)*v:length()*(1+1/math.pow(d,1)))
--            (v:normalized():dot(body.pelvic.r)>0 and 0.02 or 0.1)*v:length()*a*(1+1/math.pow(d,1)))
        v = body.tibia_r.r:cross(body.femur_r.r)
        v = body.tibia_r.r:cross(body.femur_r.r)
        a = 1-math.abs(v:normalized():dot(body.pelvic.r))
--            if not ind and nmove % ndump == 1 then
--        s = s + rec('tib_fem_r_vs_pel',
--            (v:normalized():dot(body.pelvic.r)>0 and 0.00 or 0.1)*v:length()*(1+1/math.pow(d,1)))
]]

--            (v:normalized():dot(body.pelvic.r)>0 and 0.02 or 0.1)*v:length()*a*(1+1/math.pow(d,1)))
--            rec('tib_fem_r_vs_pel_dir',v:normalized():dot(body.pelvic.r))
--            (v:normalized():dot(body.pelvic.r)>0 and 0.02 or 0.1)*v:length()*a*(1+1/math.pow(d,1)))
--            rec('tib_fem_r_vs_pel_dir',v:normalized():dot(body.pelvic.r))
--            rec('tib_fem_r_vs_pel_ang',v:length())
            v = body.femur_r.r:cross(body.tibia_r.r)
            a = v:normalized():dot(body.pelvic.r)
                if not ind and nmove%100 == 1 then
            v = body.femur_l.r:cross(body.tibia_l.r)
            a = v:normalized():dot(body.pelvic.r)
    --        a = U.vang(body.femur_l.r, body.tibia_l.r)
        -- tibia
        a = body.femur_r.r:cross(body.tibia_r.r):dot(body.pelvic.r)
--        a = U.vang(body.femur_r.r, body.tibia_r.r)
        s = s + 1*math.abs(a)
        a = body.femur_l.r:cross(body.tibia_l.r):dot(body.pelvic.r)
--        a = U.vang(body.femur_l.r, body.tibia_l.r)
@/lua/ge/extensions/editor/aiTests.lua
          local p1, p2 = nodes[n1].pos, nodes[n2].pos
          if dirVec:dot(p1 - pos) < 0 then
            n1, n2 = n2, n1
@/lua/vehicle/extensions/tech/trailSim.lua
    local trailerDirection = trailerVehicle.dirVec:z0():normalized()
    --trailerAngle = deg(acos(vehicleDirection:dot(trailerDirection)))
    trailerAngle = deg(atan2(vehicleDirection:cross(trailerDirection):dot(vec3(0, 0, 1)), vehicleDirection:dot(trailerDirection)))
    --trailerAngle = deg(acos(vehicleDirection:dot(trailerDirection)))
    trailerAngle = deg(atan2(vehicleDirection:cross(trailerDirection):dot(vec3(0, 0, 1)), vehicleDirection:dot(trailerDirection)))
  end
    --trailerAngle = deg(acos(vehicleDirection:dot(trailerDirection)))
    trailerAngle = deg(atan2(vehicleDirection:cross(trailerDirection):dot(vec3(0, 0, 1)), vehicleDirection:dot(trailerDirection)))
  end
@/lua/ge/extensions/gameplay/drift/drift.lua
  currDegAngle = math.abs(yawDifference(tempVec, dirVec) * (180 / math.pi))
  currDegAngleSign = vehData.vel:dot(up:cross(dirVec))
    crossUpTempVec:set(dirVec:cross(up))
    frontDot = frontPoint.vel:normalized():dot(crossUpTempVec)
    centerDot = velDir:dot(crossUpTempVec)
    frontDot = frontPoint.vel:normalized():dot(crossUpTempVec)
    centerDot = velDir:dot(crossUpTempVec)
    rearDot = rearPoint.vel:normalized():dot(crossUpTempVec)
    centerDot = velDir:dot(crossUpTempVec)
    rearDot = rearPoint.vel:normalized():dot(crossUpTempVec)

      if velDir:dot(up:cross(vehicleData.dirVec:normalized())) > 0 then
        driftChainActiveData.rightDrifts = driftChainActiveData.rightDrifts + 1
@/ui/modules/apps/IndicatedAirspeed/app.js

        bngApi.activeObjectLua('(obj:getDirectionVector():dot(obj:getVelocity() - obj:getFlow())) * math.sqrt(obj:getDensityAtNode(0) / 1.225)', callback)
        var displaySpeed = Math.max(airspeed * speedScale, 0)
@/lua/vehicle/extensions/straightLine.lua
    local directionVector = obj:getDirectionVector()
    local angleError = (distanceVector:dot(directionVector) / (directionVector:length() * distanceVector:length()))
    local vectorLeft = obj:getDirectionVectorUp():cross(directionVector)
    local vectorLeft = obj:getDirectionVectorUp():cross(directionVector)
    local angleSign = distanceVector:dot(vectorLeft)
@/lua/common/mathlib.lua
print( (c*1) )
print( vec3(10,0,0):dot(vec3(10,0,0)) )
]]

function LuaVec3:dot(a)
  return self.x * a.x + self.y * a.y + self.z * a.z
function LuaVec3:slerp(b, t)
  local dot = clamp(self:dot(b), -1, 1)
  if dot > 0.9995 then return self + t*(b-self) end
function LuaVec3:cosAngle(a)
  return max(min(self:dot(a) / (sqrt(self:squaredLength() * a:squaredLength()) + 1e-30), 1), -1)
end
  local abx, aby, abz, asx, asy, asz = a.x-b.x, a.y-b.y, a.z-b.z, a.x-self.x, a.y-self.y, a.z-self.z
  local xnorm = (abx*asx + aby*asy + abz*asz) / (abx*abx + aby*aby + abz*abz + 1e-30) -- ab:dot(a-self)/ab:dot(ab)
  return square(asx - abx*xnorm) + square(asy - aby*xnorm) + square(asz - abz*xnorm) -- (a-self):squaredDistance(ab * xnorm)
  local abx, aby, abz, asx, asy, asz = a.x-b.x, a.y-b.y, a.z-b.z, a.x-self.x, a.y-self.y, a.z-self.z
  local xnorm = (abx*asx + aby*asy + abz*asz) / (abx*abx + aby*aby + abz*abz + 1e-30) -- ab:dot(a-self)/ab:dot(ab)
  return square(asx - abx*xnorm) + square(asy - aby*xnorm) + square(asz - abz*xnorm) -- (a-self):squaredDistance(ab * xnorm)
  local abx, aby, abz, asx, asy, asz = a.x-b.x, a.y-b.y, a.z-b.z, a.x-self.x, a.y-self.y, a.z-self.z
  local xnormC = min(max((abx*asx + aby*asy + abz*asz) / (abx*abx + aby*aby + abz*abz + 1e-30), 0), 1) -- min(max(ab:dot(a-self)/ab:dot(ab), 0), 1)
  return square(asx - abx*xnormC) + square(asy - aby*xnormC) + square(asz - abz*xnormC) -- (a-self):squaredDistance(ab * xnormC)
  local abx, aby, abz, asx, asy, asz = a.x-b.x, a.y-b.y, a.z-b.z, a.x-self.x, a.y-self.y, a.z-self.z
  local xnormC = min(max((abx*asx + aby*asy + abz*asz) / (abx*abx + aby*aby + abz*abz + 1e-30), 0), 1) -- min(max(ab:dot(a-self)/ab:dot(ab), 0), 1)
  return square(asx - abx*xnormC) + square(asy - aby*xnormC) + square(asz - abz*xnormC) -- (a-self):squaredDistance(ab * xnormC)
  local bax, bay, baz = b.x-a.x, b.y-a.y, b.z-a.z
  return (bax*(self.x-a.x) + bay*(self.y-a.y) + baz*(self.z-a.z)) / (bax*bax + bay*bay + baz*baz + 1e-30) -- (b-a):dot(self-a) / (b-a):squaredLength()
end
  local pacnorm = (self - c):cross(norm)
  return bc:dot(pacnorm) / normsqlen, ca:dot(pacnorm) / normsqlen, norm / sqrt(normsqlen)
end
  local pacnorm = (self - c):cross(norm)
  return bc:dot(pacnorm) / normsqlen, ca:dot(pacnorm) / normsqlen, norm / sqrt(normsqlen)
end
  tmpv3:setSub2(self, a)
  local d1, d2 = tmpv1:dot(tmpv3), tmpv2:dot(tmpv3)
  if max(d1, d2) <= 0 then return 1, 0 end
  tmpv3:setSub2(self, a)
  local d1, d2 = tmpv1:dot(tmpv3), tmpv2:dot(tmpv3)
  if max(d1, d2) <= 0 then return 1, 0 end
  tmpv3:setSub2(self, b)
  local d3, d4 = tmpv1:dot(tmpv3), tmpv2:dot(tmpv3)
  if max(d4, 0) <= d3 then return 0, 1 end
  tmpv3:setSub2(self, b)
  local d3, d4 = tmpv1:dot(tmpv3), tmpv2:dot(tmpv3)
  if max(d4, 0) <= d3 then return 0, 1 end
  tmpv3:setSub2(self, c)
  local d5, d6 = tmpv1:dot(tmpv3), tmpv2:dot(tmpv3)
  if max(d5, 0) <= d6 then return 0, 0 end
  tmpv3:setSub2(self, c)
  local d5, d6 = tmpv1:dot(tmpv3), tmpv2:dot(tmpv3)
  if max(d5, 0) <= d6 then return 0, 0 end
  return (pnorm.x*(self.x-a.x) + pnorm.y*(self.y-a.y) + pnorm.z*(self.z-a.z)) *
          max(min(1 / (pnorm.x*(b.x-a.x) + pnorm.y*(b.y-a.y) + pnorm.z*(b.z-a.z)), 1e300), -1e300) -- pnorm:dot(self-a)/pnorm:dot(b-a)
end
  return (pnorm.x*(self.x-a.x) + pnorm.y*(self.y-a.y) + pnorm.z*(self.z-a.z)) *
          max(min(1 / (pnorm.x*(b.x-a.x) + pnorm.y*(b.y-a.y) + pnorm.z*(b.z-a.z)), 1e300), -1e300) -- pnorm:dot(self-a)/pnorm:dot(b-a)
end
  local invDif2len = 1 / max(lDif:squaredLength(), 1e-30)
  local dotab = -ac:dot(lDif) * invDif2len
  local D = dotab * dotab + (radius * radius - ac:squaredLength()) * invDif2len
  local c2xc3 = c2:cross(c3)
  local invDet = 1 / c1:dot(c2xc3)
  return newLuaVec3xyz(c2xc3:dot(self)*invDet, c3:cross(c1):dot(self)*invDet, c1:cross(c2):dot(self)*invDet)
  local invDet = 1 / c1:dot(c2xc3)
  return newLuaVec3xyz(c2xc3:dot(self)*invDet, c3:cross(c1):dot(self)*invDet, c1:cross(c2):dot(self)*invDet)
end
  local invDet = 1 / c1:dot(c2xc3)
  return newLuaVec3xyz(c2xc3:dot(self)*invDet, c3:cross(c1):dot(self)*invDet, c1:cross(c2):dot(self)*invDet)
end
  local invDet = 1 / c1:dot(c2xc3)
  return newLuaVec3xyz(c2xc3:dot(self)*invDet, c3:cross(c1):dot(self)*invDet, c1:cross(c2):dot(self)*invDet)
end

function StackVec3:dot(a)
  local ax, ay, az = a:xyz()

function LuaQuat:dot(a)
  return self.x * a.x + self.y * a.y + self.z * a.z + self.w * a.w
function LuaQuat:nlerp(a, t)
  local tmp = (1 - t) * self + (self:dot(a) < 0 and -t or t) * a
  tmp:normalize()
function LuaQuat:slerp(a, t)
  local dot = clamp(self:dot(a), -1, 1)
  if dot > 0.9995 then return self:nlerp(a, t) end
function LuaQuat:setRotationFromTo(fromV, toV)
  local w = 1 + fromV:dot(toV)
  tmpv2:normalize()
  if abs(tmpv2:dot(tmpv1)) > 0.9999 then
    tmpv2:set((push3(tmpv2) + tmpv2:perpendicularN() * 1e-5):normalized())
  tmpv2:setCross(v1, v2) -- axis
  return abs(tmpv1:dot(tmpv2))-abs(b2e1:dot(tmpv2))-abs(b2e2:dot(tmpv2))<=abs(b1e1:dot(tmpv2))+abs(b1e2:dot(tmpv2))
end
  tmpv2:setCross(v1, v2) -- axis
  return abs(tmpv1:dot(tmpv2))-abs(b2e1:dot(tmpv2))-abs(b2e2:dot(tmpv2))<=abs(b1e1:dot(tmpv2))+abs(b1e2:dot(tmpv2))
end
  tmpv2:setCross(v1, v2) -- axis
  return abs(tmpv1:dot(tmpv2))-abs(b2e1:dot(tmpv2))-abs(b2e2:dot(tmpv2))<=abs(b1e1:dot(tmpv2))+abs(b1e2:dot(tmpv2))
end
  tmpv2:setCross(v1, v2) -- axis
  return abs(tmpv1:dot(tmpv2))-abs(b2e1:dot(tmpv2))-abs(b2e2:dot(tmpv2))<=abs(b1e1:dot(tmpv2))+abs(b1e2:dot(tmpv2))
end
  tmpv2:setCross(v1, v2) -- axis
  return abs(tmpv1:dot(tmpv2))-abs(b2e1:dot(tmpv2))-abs(b2e2:dot(tmpv2))<=abs(b1e1:dot(tmpv2))+abs(b1e2:dot(tmpv2))
end
  tmpv1:setSub2(c1, c2)
  local d11,d12,d13=abs(x1:dot(x2)),abs(x1:dot(y2)),abs(x1:dot(z2))
  if abs(tmpv1:dot(x1))-d11-d12-d13>x1:squaredLength() then return false end
  tmpv1:setSub2(c1, c2)
  local d11,d12,d13=abs(x1:dot(x2)),abs(x1:dot(y2)),abs(x1:dot(z2))
  if abs(tmpv1:dot(x1))-d11-d12-d13>x1:squaredLength() then return false end
  tmpv1:setSub2(c1, c2)
  local d11,d12,d13=abs(x1:dot(x2)),abs(x1:dot(y2)),abs(x1:dot(z2))
  if abs(tmpv1:dot(x1))-d11-d12-d13>x1:squaredLength() then return false end
  local d11,d12,d13=abs(x1:dot(x2)),abs(x1:dot(y2)),abs(x1:dot(z2))
  if abs(tmpv1:dot(x1))-d11-d12-d13>x1:squaredLength() then return false end
  local d21,d22,d23=abs(y1:dot(x2)),abs(y1:dot(y2)),abs(y1:dot(z2))
  if abs(tmpv1:dot(x1))-d11-d12-d13>x1:squaredLength() then return false end
  local d21,d22,d23=abs(y1:dot(x2)),abs(y1:dot(y2)),abs(y1:dot(z2))
  if abs(tmpv1:dot(y1))-d21-d22-d23>y1:squaredLength() then return false end
  if abs(tmpv1:dot(x1))-d11-d12-d13>x1:squaredLength() then return false end
  local d21,d22,d23=abs(y1:dot(x2)),abs(y1:dot(y2)),abs(y1:dot(z2))
  if abs(tmpv1:dot(y1))-d21-d22-d23>y1:squaredLength() then return false end
  if abs(tmpv1:dot(x1))-d11-d12-d13>x1:squaredLength() then return false end
  local d21,d22,d23=abs(y1:dot(x2)),abs(y1:dot(y2)),abs(y1:dot(z2))
  if abs(tmpv1:dot(y1))-d21-d22-d23>y1:squaredLength() then return false end
  local d21,d22,d23=abs(y1:dot(x2)),abs(y1:dot(y2)),abs(y1:dot(z2))
  if abs(tmpv1:dot(y1))-d21-d22-d23>y1:squaredLength() then return false end
  local d31,d32,d33=abs(z1:dot(x2)),abs(z1:dot(y2)),abs(z1:dot(z2))
  if abs(tmpv1:dot(y1))-d21-d22-d23>y1:squaredLength() then return false end
  local d31,d32,d33=abs(z1:dot(x2)),abs(z1:dot(y2)),abs(z1:dot(z2))
  return abs(tmpv1:dot(z1))-d31-d32-d33<=z1:squaredLength() and abs(tmpv1:dot(x2))-d11-d21-d31<=x2:squaredLength()
  if abs(tmpv1:dot(y1))-d21-d22-d23>y1:squaredLength() then return false end
  local d31,d32,d33=abs(z1:dot(x2)),abs(z1:dot(y2)),abs(z1:dot(z2))
  return abs(tmpv1:dot(z1))-d31-d32-d33<=z1:squaredLength() and abs(tmpv1:dot(x2))-d11-d21-d31<=x2:squaredLength()
  if abs(tmpv1:dot(y1))-d21-d22-d23>y1:squaredLength() then return false end
  local d31,d32,d33=abs(z1:dot(x2)),abs(z1:dot(y2)),abs(z1:dot(z2))
  return abs(tmpv1:dot(z1))-d31-d32-d33<=z1:squaredLength() and abs(tmpv1:dot(x2))-d11-d21-d31<=x2:squaredLength()
  local d31,d32,d33=abs(z1:dot(x2)),abs(z1:dot(y2)),abs(z1:dot(z2))
  return abs(tmpv1:dot(z1))-d31-d32-d33<=z1:squaredLength() and abs(tmpv1:dot(x2))-d11-d21-d31<=x2:squaredLength()
     and abs(tmpv1:dot(y2))-d12-d22-d32<=y2:squaredLength() and abs(tmpv1:dot(z2))-d13-d23-d33<=z2:squaredLength()
  local d31,d32,d33=abs(z1:dot(x2)),abs(z1:dot(y2)),abs(z1:dot(z2))
  return abs(tmpv1:dot(z1))-d31-d32-d33<=z1:squaredLength() and abs(tmpv1:dot(x2))-d11-d21-d31<=x2:squaredLength()
     and abs(tmpv1:dot(y2))-d12-d22-d32<=y2:squaredLength() and abs(tmpv1:dot(z2))-d13-d23-d33<=z2:squaredLength()
  return abs(tmpv1:dot(z1))-d31-d32-d33<=z1:squaredLength() and abs(tmpv1:dot(x2))-d11-d21-d31<=x2:squaredLength()
     and abs(tmpv1:dot(y2))-d12-d22-d32<=y2:squaredLength() and abs(tmpv1:dot(z2))-d13-d23-d33<=z2:squaredLength()
     and axisCheck(x1,x2,y1,z1,y2,z2) and axisCheck(x1,y2,y1,z1,x2,z2) and axisCheck(x1,z2,y1,z1,x2,y2)
  return abs(tmpv1:dot(z1))-d31-d32-d33<=z1:squaredLength() and abs(tmpv1:dot(x2))-d11-d21-d31<=x2:squaredLength()
     and abs(tmpv1:dot(y2))-d12-d22-d32<=y2:squaredLength() and abs(tmpv1:dot(z2))-d13-d23-d33<=z2:squaredLength()
     and axisCheck(x1,x2,y1,z1,y2,z2) and axisCheck(x1,y2,y1,z1,x2,z2) and axisCheck(x1,z2,y1,z1,x2,y2)
  tmpv1:setSub2(c1, c2)
  return abs(tmpv1:dot(x1))+abs(x1:dot(x2))+abs(x1:dot(y2))+abs(x1:dot(z2))<=x1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
  tmpv1:setSub2(c1, c2)
  return abs(tmpv1:dot(x1))+abs(x1:dot(x2))+abs(x1:dot(y2))+abs(x1:dot(z2))<=x1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
  tmpv1:setSub2(c1, c2)
  return abs(tmpv1:dot(x1))+abs(x1:dot(x2))+abs(x1:dot(y2))+abs(x1:dot(z2))<=x1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
  tmpv1:setSub2(c1, c2)
  return abs(tmpv1:dot(x1))+abs(x1:dot(x2))+abs(x1:dot(y2))+abs(x1:dot(z2))<=x1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
  return abs(tmpv1:dot(x1))+abs(x1:dot(x2))+abs(x1:dot(y2))+abs(x1:dot(z2))<=x1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
     and abs(tmpv1:dot(z1))+abs(z1:dot(x2))+abs(z1:dot(y2))+abs(z1:dot(z2))<=z1:squaredLength()
  return abs(tmpv1:dot(x1))+abs(x1:dot(x2))+abs(x1:dot(y2))+abs(x1:dot(z2))<=x1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
     and abs(tmpv1:dot(z1))+abs(z1:dot(x2))+abs(z1:dot(y2))+abs(z1:dot(z2))<=z1:squaredLength()
  return abs(tmpv1:dot(x1))+abs(x1:dot(x2))+abs(x1:dot(y2))+abs(x1:dot(z2))<=x1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
     and abs(tmpv1:dot(z1))+abs(z1:dot(x2))+abs(z1:dot(y2))+abs(z1:dot(z2))<=z1:squaredLength()
  return abs(tmpv1:dot(x1))+abs(x1:dot(x2))+abs(x1:dot(y2))+abs(x1:dot(z2))<=x1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
     and abs(tmpv1:dot(z1))+abs(z1:dot(x2))+abs(z1:dot(y2))+abs(z1:dot(z2))<=z1:squaredLength()
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
     and abs(tmpv1:dot(z1))+abs(z1:dot(x2))+abs(z1:dot(y2))+abs(z1:dot(z2))<=z1:squaredLength()
end
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
     and abs(tmpv1:dot(z1))+abs(z1:dot(x2))+abs(z1:dot(y2))+abs(z1:dot(z2))<=z1:squaredLength()
end
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
     and abs(tmpv1:dot(z1))+abs(z1:dot(x2))+abs(z1:dot(y2))+abs(z1:dot(z2))<=z1:squaredLength()
end
     and abs(tmpv1:dot(y1))+abs(y1:dot(x2))+abs(y1:dot(y2))+abs(y1:dot(z2))<=y1:squaredLength()
     and abs(tmpv1:dot(z1))+abs(z1:dot(x2))+abs(z1:dot(y2))+abs(z1:dot(z2))<=z1:squaredLength()
end
  local x1sql, y1sql, z1sql = x1:squaredLength(), y1:squaredLength(), z1:squaredLength()
  local a, b, c = tmpv1:dot(x1), tmpv1:dot(y1), tmpv1:dot(z1)
  if abs(a) < x1sql and abs(b) < y1sql and abs(c) < z1sql then return 0 end -- fix small r2 num accuracy
  local x1sql, y1sql, z1sql = x1:squaredLength(), y1:squaredLength(), z1:squaredLength()
  local a, b, c = tmpv1:dot(x1), tmpv1:dot(y1), tmpv1:dot(z1)
  if abs(a) < x1sql and abs(b) < y1sql and abs(c) < z1sql then return 0 end -- fix small r2 num accuracy
  local x1sql, y1sql, z1sql = x1:squaredLength(), y1:squaredLength(), z1:squaredLength()
  local a, b, c = tmpv1:dot(x1), tmpv1:dot(y1), tmpv1:dot(z1)
  if abs(a) < x1sql and abs(b) < y1sql and abs(c) < z1sql then return 0 end -- fix small r2 num accuracy
  tmpv1:setSub2(c1, plpos)
  return abs(tmpv1:dot(pln))<=abs(x1:dot(pln))+abs(y1:dot(pln))+abs(z1:dot(pln))
end
  tmpv1:setSub2(c1, plpos)
  return abs(tmpv1:dot(pln))<=abs(x1:dot(pln))+abs(y1:dot(pln))+abs(z1:dot(pln))
end
  tmpv1:setSub2(c1, plpos)
  return abs(tmpv1:dot(pln))<=abs(x1:dot(pln))+abs(y1:dot(pln))+abs(z1:dot(pln))
end
  tmpv1:setSub2(c1, plpos)
  return abs(tmpv1:dot(pln))<=abs(x1:dot(pln))+abs(y1:dot(pln))+abs(z1:dot(pln))
end
  local x1len, y1len, z1len = x1:length(), y1:length(), z1:length()
  return abs(tmpv1:dot(x1))<=x1len*(x1len-r2) and abs(tmpv1:dot(y1))<=y1len*(y1len-r2) and abs(tmpv1:dot(z1))<=z1len*(z1len-r2)
end
  local x1len, y1len, z1len = x1:length(), y1:length(), z1:length()
  return abs(tmpv1:dot(x1))<=x1len*(x1len-r2) and abs(tmpv1:dot(y1))<=y1len*(y1len-r2) and abs(tmpv1:dot(z1))<=z1len*(z1len-r2)
end
  local x1len, y1len, z1len = x1:length(), y1:length(), z1:length()
  return abs(tmpv1:dot(x1))<=x1len*(x1len-r2) and abs(tmpv1:dot(y1))<=y1len*(y1len-r2) and abs(tmpv1:dot(z1))<=z1len*(z1len-r2)
end
  tmpv1:setSub2(c1, p)
  return abs(tmpv1:dot(x1))<=x1:squaredLength() and abs(tmpv1:dot(y1))<=y1:squaredLength() and abs(tmpv1:dot(z1))<=z1:squaredLength()
end
  tmpv1:setSub2(c1, p)
  return abs(tmpv1:dot(x1))<=x1:squaredLength() and abs(tmpv1:dot(y1))<=y1:squaredLength() and abs(tmpv1:dot(z1))<=z1:squaredLength()
end
  tmpv1:setSub2(c1, p)
  return abs(tmpv1:dot(x1))<=x1:squaredLength() and abs(tmpv1:dot(y1))<=y1:squaredLength() and abs(tmpv1:dot(z1))<=z1:squaredLength()
end
  tmpv1:setSub2(p, c1)
  local x, y, z = tmpv1:dot(x1), tmpv1:dot(y1), tmpv1:dot(z1)
  local a2, b2, c2 = x1:squaredLength(), y1:squaredLength(), z1:squaredLength()
  tmpv1:setSub2(p, c1)
  local x, y, z = tmpv1:dot(x1), tmpv1:dot(y1), tmpv1:dot(z1)
  local a2, b2, c2 = x1:squaredLength(), y1:squaredLength(), z1:squaredLength()
  tmpv1:setSub2(p, c1)
  local x, y, z = tmpv1:dot(x1), tmpv1:dot(y1), tmpv1:dot(z1)
  local a2, b2, c2 = x1:squaredLength(), y1:squaredLength(), z1:squaredLength()
  tmpv1:setSub2(c1, plpos)
  return tmpv1:dot(pln)+abs(x1:dot(pln))+abs(y1:dot(pln))+abs(z1:dot(pln))
end
  tmpv1:setSub2(c1, plpos)
  return tmpv1:dot(pln)+abs(x1:dot(pln))+abs(y1:dot(pln))+abs(z1:dot(pln))
end
  tmpv1:setSub2(c1, plpos)
  return tmpv1:dot(pln)+abs(x1:dot(pln))+abs(y1:dot(pln))+abs(z1:dot(pln))
end
  tmpv1:setSub2(c1, plpos)
  return tmpv1:dot(pln)+abs(x1:dot(pln))+abs(y1:dot(pln))+abs(z1:dot(pln))
end
  tmpv1:setSub2(plpos, rpos)
  return min(tmpv1:dot(pln) / rdir:dot(pln), math.huge)
end
  tmpv1:setSub2(plpos, rpos)
  return min(tmpv1:dot(pln) / rdir:dot(pln), math.huge)
end
  tmpv1:setSub2(c1, rpos)
  local rposc1x1, x1sq, invrdirx1 = tmpv1:dot(x1), x1:squaredLength(), 1 / rdir:dot(x1)
  local dx1, dx2 = (rposc1x1 - x1sq) * invrdirx1, min((rposc1x1 + x1sq) * invrdirx1, math.huge)
  tmpv1:setSub2(c1, rpos)
  local rposc1x1, x1sq, invrdirx1 = tmpv1:dot(x1), x1:squaredLength(), 1 / rdir:dot(x1)
  local dx1, dx2 = (rposc1x1 - x1sq) * invrdirx1, min((rposc1x1 + x1sq) * invrdirx1, math.huge)
  local dx1, dx2 = (rposc1x1 - x1sq) * invrdirx1, min((rposc1x1 + x1sq) * invrdirx1, math.huge)
  local rposc1y1, y1sq, invrdiry1 = tmpv1:dot(y1), y1:squaredLength(), 1 / rdir:dot(y1)
  local dy1, dy2 = (rposc1y1 - y1sq) * invrdiry1, min((rposc1y1 + y1sq) * invrdiry1, math.huge)
  local dx1, dx2 = (rposc1x1 - x1sq) * invrdirx1, min((rposc1x1 + x1sq) * invrdirx1, math.huge)
  local rposc1y1, y1sq, invrdiry1 = tmpv1:dot(y1), y1:squaredLength(), 1 / rdir:dot(y1)
  local dy1, dy2 = (rposc1y1 - y1sq) * invrdiry1, min((rposc1y1 + y1sq) * invrdiry1, math.huge)
  local dy1, dy2 = (rposc1y1 - y1sq) * invrdiry1, min((rposc1y1 + y1sq) * invrdiry1, math.huge)
  local rposc1z1, z1sq, invrdirz1 = tmpv1:dot(z1), z1:squaredLength(), 1 / rdir:dot(z1)
  local dz1, dz2 = (rposc1z1 - z1sq) * invrdirz1, min((rposc1z1 + z1sq) * invrdirz1, math.huge)
  local dy1, dy2 = (rposc1y1 - y1sq) * invrdiry1, min((rposc1y1 + y1sq) * invrdiry1, math.huge)
  local rposc1z1, z1sq, invrdirz1 = tmpv1:dot(z1), z1:squaredLength(), 1 / rdir:dot(z1)
  local dz1, dz2 = (rposc1z1 - z1sq) * invrdirz1, min((rposc1z1 + z1sq) * invrdirz1, math.huge)
  local rcpos = cpos - rpos
  local dcr = rdir:dot(rcpos)
  local s = dcr*dcr - rcpos:squaredLength() + cr*cr
  tmpv1:setSub2(rpos, c1)
  local pM = vec3(tmpv1:dot(x1)*invx1, tmpv1:dot(y1)*invy1, tmpv1:dot(z1)*invz1)
  local dirM = vec3(rdir:dot(x1)*invx1, rdir:dot(y1)*invy1, rdir:dot(z1)*invz1)
  tmpv1:setSub2(rpos, c1)
  local pM = vec3(tmpv1:dot(x1)*invx1, tmpv1:dot(y1)*invy1, tmpv1:dot(z1)*invz1)
  local dirM = vec3(rdir:dot(x1)*invx1, rdir:dot(y1)*invy1, rdir:dot(z1)*invz1)
  tmpv1:setSub2(rpos, c1)
  local pM = vec3(tmpv1:dot(x1)*invx1, tmpv1:dot(y1)*invy1, tmpv1:dot(z1)*invz1)
  local dirM = vec3(rdir:dot(x1)*invx1, rdir:dot(y1)*invy1, rdir:dot(z1)*invz1)
  local pM = vec3(tmpv1:dot(x1)*invx1, tmpv1:dot(y1)*invy1, tmpv1:dot(z1)*invz1)
  local dirM = vec3(rdir:dot(x1)*invx1, rdir:dot(y1)*invy1, rdir:dot(z1)*invz1)
  local pM = vec3(tmpv1:dot(x1)*invx1, tmpv1:dot(y1)*invy1, tmpv1:dot(z1)*invz1)
  local dirM = vec3(rdir:dot(x1)*invx1, rdir:dot(y1)*invy1, rdir:dot(z1)*invz1)
  local pM = vec3(tmpv1:dot(x1)*invx1, tmpv1:dot(y1)*invy1, tmpv1:dot(z1)*invz1)
  local dirM = vec3(rdir:dot(x1)*invx1, rdir:dot(y1)*invy1, rdir:dot(z1)*invz1)

  local a, b, c = dirM:squaredLength(), 2*pM:dot(dirM), pM:squaredLength() - 1
  local d = b*b - 4*a*c
  local ba, oa = cposb - cposa, rpos - cposa
  local baba, bard, baoa = ba:squaredLength(), ba:dot(rdir), ba:dot(oa)
  local a, b = baba - bard*bard, rdir:dot(oa) * baba - baoa*bard
  local ba, oa = cposb - cposa, rpos - cposa
  local baba, bard, baoa = ba:squaredLength(), ba:dot(rdir), ba:dot(oa)
  local a, b = baba - bard*bard, rdir:dot(oa) * baba - baoa*bard
  local baba, bard, baoa = ba:squaredLength(), ba:dot(rdir), ba:dot(oa)
  local a, b = baba - bard*bard, rdir:dot(oa) * baba - baoa*bard
  local h = b*b - a*((oa:squaredLength()-cR*cR) * baba - baoa*baoa)
    oa:set(y <= 0 and oa or rpos - cposb) -- caps
    b = rdir:dot(oa)
    h = b*b - oa:squaredLength() - cR*cR
  local rposc = rpos - c
  local pOnTri = rposc:dot(norm) / rdir:dot(norm)
  if pOnTri <= 0 then
  local rposc = rpos - c
  local pOnTri = rposc:dot(norm) / rdir:dot(norm)
  if pOnTri <= 0 then
    local pacnorm = (rposc - rdir * pOnTri):cross(norm)
    local bx, by = bc:dot(pacnorm), ca:dot(pacnorm)
    if min(bx, by) >= 0 then
    local pacnorm = (rposc - rdir * pOnTri):cross(norm)
    local bx, by = bc:dot(pacnorm), ca:dot(pacnorm)
    if min(bx, by) >= 0 then
@/lua/vehicle/controller/gauges/customModules/navigationData.lua
  local dir = obj:getDirectionVector()
  mapData.rotation = deg(atan2(dir:dot(vecX), dir:dot(vecY)))
  gaugeHTMLTexture:streamJS("updateMap", "updateMap", mapData)
  local dir = obj:getDirectionVector()
  mapData.rotation = deg(atan2(dir:dot(vecX), dir:dot(vecY)))
  gaugeHTMLTexture:streamJS("updateMap", "updateMap", mapData)
@/lua/ge/extensions/editor/cosimulationSignalEditor.lua
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
  local right = fwd:cross(up)
  return vec3(fwd:dot(dirLoc), right:dot(dirLoc), up:dot(dirLoc)), vec3(fwd:dot(upLoc), right:dot(upLoc), up:dot(upLoc))
end
@/lua/ge/extensions/career/modules/vehicleDeletionService.lua
      -- check if camera is looking away from vehicle
      if camDir:dot(camToVeh) < 0 then
        data.callback()
@/lua/ge/extensions/core/paths.lua
    if res.markers[i] then
      if res.markers[i].rot:dot(res.markers[i - 1].rot) < 0 then
        res.markers[i].rot = -res.markers[i].rot
  for i = 2, res.nodeCount - 1 do
    if res.markers[i].rot:dot(res.markers[i - 1].rot) < 0 then
      res.markers[i].rot = -res.markers[i].rot
@/lua/ge/extensions/editor/assemblySpline/populate.lua
        -- Compute the required roll angle to align the bridge at the source attachment point.
        tmpVec4:setScaled2(tmpVec3, sourceNailAxisWorld:dot(tmpVec3))
        sourceNailProj:setSub2(sourceNailAxisWorld, tmpVec4)
        sourceNailProj:normalize()
        tmpVec4:setScaled2(tmpVec3, bridgeSourceNailAxisWorld:dot(tmpVec3))
        bridgeSourceNailProj:setSub2(bridgeSourceNailAxisWorld, tmpVec4)
        tmpVec2:setCross(tmpVec3, bridgeSourceNailProj)
        local sourceRoll = atan2(sourceNailProj:dot(tmpVec2), sourceNailProj:dot(bridgeSourceNailProj))
        tmpVec2:setCross(tmpVec3, bridgeSourceNailProj)
        local sourceRoll = atan2(sourceNailProj:dot(tmpVec2), sourceNailProj:dot(bridgeSourceNailProj))
        -- Compute the required roll angle to align the bridge at the target attachment point.
        tmpVec4:setScaled2(tmpVec3, targetNailAxisWorld:dot(tmpVec3))
        targetNailProj:setSub2(targetNailAxisWorld, tmpVec4)
        targetNailProj:normalize()
        tmpVec4:setScaled2(tmpVec3, bridgeTargetNailAxisWorld:dot(tmpVec3))
        bridgeTargetNailProj:setSub2(bridgeTargetNailAxisWorld, tmpVec4)
        tmpVec2:setCross(tmpVec3, bridgeTargetNailProj)
        local targetRoll = atan2(targetNailProj:dot(tmpVec2), targetNailProj:dot(bridgeTargetNailProj))
        tmpVec2:setCross(tmpVec3, bridgeTargetNailProj)
        local targetRoll = atan2(targetNailProj:dot(tmpVec2), targetNailProj:dot(bridgeTargetNailProj))
@/lua/vehicle/extensions/dragAi.lua
    directionVector = vec3(directionVector.x, directionVector.y, 0)
    local angle = (distanceVector:dot(directionVector) / (directionVector:length() * distanceVector:length()))
    local vectorLeft = obj:getDirectionVectorUp():cross(directionVector)
    local vectorLeft = obj:getDirectionVectorUp():cross(directionVector)
    local angleSign = distanceVector:dot(vectorLeft)
@/lua/ge/extensions/editor/assemblySpline/molecule.lua
          nailVector:normalize()
          local dot = nailVector:dot(localXAxis)
          if abs(dot) > 0.9 then
            localXAxis:set(0, 1, 0) -- Nail is too close to X-axis, use Y-axis instead.
            dot = nailVector:dot(localXAxis)
          end
@/lua/vehicle/extensions/aeroDebug.lua
  --obj.debugDrawProxy:drawSphere(0.05, cog, color(255,0,255,255))
  aeroData.totalAeroForceVehicle = vec3(aeroData.totalAeroForce:dot(M.directionVectorLeft), aeroData.totalAeroForce:dot(M.directionVector), aeroData.totalAeroForce:dot(M.directionVectorUp))
  aeroData.afX = aeroData.totalAeroForce:dot(M.directionVectorLeft)
  --obj.debugDrawProxy:drawSphere(0.05, cog, color(255,0,255,255))
  aeroData.totalAeroForceVehicle = vec3(aeroData.totalAeroForce:dot(M.directionVectorLeft), aeroData.totalAeroForce:dot(M.directionVector), aeroData.totalAeroForce:dot(M.directionVectorUp))
  aeroData.afX = aeroData.totalAeroForce:dot(M.directionVectorLeft)
  --obj.debugDrawProxy:drawSphere(0.05, cog, color(255,0,255,255))
  aeroData.totalAeroForceVehicle = vec3(aeroData.totalAeroForce:dot(M.directionVectorLeft), aeroData.totalAeroForce:dot(M.directionVector), aeroData.totalAeroForce:dot(M.directionVectorUp))
  aeroData.afX = aeroData.totalAeroForce:dot(M.directionVectorLeft)
  aeroData.totalAeroForceVehicle = vec3(aeroData.totalAeroForce:dot(M.directionVectorLeft), aeroData.totalAeroForce:dot(M.directionVector), aeroData.totalAeroForce:dot(M.directionVectorUp))
  aeroData.afX = aeroData.totalAeroForce:dot(M.directionVectorLeft)
  aeroData.afY = aeroData.totalAeroForce:dot(M.directionVector)
  aeroData.afX = aeroData.totalAeroForce:dot(M.directionVectorLeft)
  aeroData.afY = aeroData.totalAeroForce:dot(M.directionVector)
  aeroData.afZ = aeroData.totalAeroForce:dot(M.directionVectorUp)
  aeroData.afY = aeroData.totalAeroForce:dot(M.directionVector)
  aeroData.afZ = aeroData.totalAeroForce:dot(M.directionVectorUp)
  --print(M.afX..' '..M.afY..' '..M.afZ)

  aeroData.totalAeroTorqueVehicle = vec3(aeroData.totalAeroTorque:dot(M.directionVectorLeft), aeroData.totalAeroTorque:dot(M.directionVector), aeroData.totalAeroTorque:dot(M.directionVectorUp))
  aeroData.aTX = aeroData.totalAeroTorque:dot(M.directionVectorLeft)

  aeroData.totalAeroTorqueVehicle = vec3(aeroData.totalAeroTorque:dot(M.directionVectorLeft), aeroData.totalAeroTorque:dot(M.directionVector), aeroData.totalAeroTorque:dot(M.directionVectorUp))
  aeroData.aTX = aeroData.totalAeroTorque:dot(M.directionVectorLeft)

  aeroData.totalAeroTorqueVehicle = vec3(aeroData.totalAeroTorque:dot(M.directionVectorLeft), aeroData.totalAeroTorque:dot(M.directionVector), aeroData.totalAeroTorque:dot(M.directionVectorUp))
  aeroData.aTX = aeroData.totalAeroTorque:dot(M.directionVectorLeft)
  aeroData.totalAeroTorqueVehicle = vec3(aeroData.totalAeroTorque:dot(M.directionVectorLeft), aeroData.totalAeroTorque:dot(M.directionVector), aeroData.totalAeroTorque:dot(M.directionVectorUp))
  aeroData.aTX = aeroData.totalAeroTorque:dot(M.directionVectorLeft)
  aeroData.aTY = aeroData.totalAeroTorque:dot(M.directionVector)
  aeroData.aTX = aeroData.totalAeroTorque:dot(M.directionVectorLeft)
  aeroData.aTY = aeroData.totalAeroTorque:dot(M.directionVector)
  aeroData.aTZ = aeroData.totalAeroTorque:dot(M.directionVectorUp)
  aeroData.aTY = aeroData.totalAeroTorque:dot(M.directionVector)
  aeroData.aTZ = aeroData.totalAeroTorque:dot(M.directionVectorUp)
  --print(M.aTX..' '..M.aTY..' '..M.aTZ)

    aeroData.rearDownForce = -(frontAxleToCOP:cross(aeroData.totalAeroForce) - aeroData.totalAeroTorque):dot(M.directionVectorLeft) / wheelbase
    aeroData.frontDownForce = (rearAxleToCOP:cross(aeroData.totalAeroForce) - aeroData.totalAeroTorque):dot(M.directionVectorLeft) / wheelbase
    aeroData.rearDownForce = -(frontAxleToCOP:cross(aeroData.totalAeroForce) - aeroData.totalAeroTorque):dot(M.directionVectorLeft) / wheelbase
    aeroData.frontDownForce = (rearAxleToCOP:cross(aeroData.totalAeroForce) - aeroData.totalAeroTorque):dot(M.directionVectorLeft) / wheelbase
@/lua/ge/extensions/gameplay/drift/freeroam/driftSpots.lua
  if isPointInsideRectangle(plPos, line.pos, line.scl, line.rot) then
    local dot = plVel:dot(line.startDir)
    if dot > 0 then
    if isPointInsideRectangle(plPos, finishLine.pos, finishLine.scl, finishLine.rot) then
      local dot = plVel:dot(finishLine.startDir)
      if not isInTheConcludingPhase and isInFreeroamChallenge and dot <= 0 then
@/lua/ge/extensions/editor/vehicleEditor/staticEditor/veStaticRenderView.lua
      -- Don't allow picking arrow if its pretty much inline with vector projected out of user's screen
      if arrowVec:dot(vec3(0,-1,0)) < 0.99 then
        local xnorm1, xnorm2 = closestLinePoints(rayStartPos, rayEndPos, zeroVec, arrowVec)
    -- fade out the arrow to be able to see the other arrows
    if math.abs(arrowVec:dot(vec3(0,-1,0))) < 0.99 * vecMult then
      --arrowCol.a = (dotProd - 0.75) * 1 / -0.25 + 1
@/lua/ge/extensions/gameplay/drift/destination.lua
  local desiredDirection = nextWaypointPos - previousWaypointPos
  goingWrongWay = not disableWrongWayAndDist and vel > velThreshold and (desiredDirection:dot(vehData.vel) <= 0 or vel <= velThreshold)
@/lua/ge/extensions/editor/gen/decal.lua
            acurve[#acurve+1] = {d=d, curv=ecurv(rd,i)}
            if (D.epos(rd.body,i+1)-D.epos(rd.body,i)):dot(D.epos(rd.body,i)-D.epos(rd.body,i-1)) < 0 then
                -- decal corrupted
        for i=2,nsstep-1 do
            if (ap[i+1]-ap[i]):dot(ap[i]-ap[i-1]) < 0 then
                askip[#askip+1] = rd.ind
--                                            local rdir = -U.vang(p - pp, D.epos(rd.body, ie) - D.epos(rd.body, ie == 0 and ie+1 or ie-1), true)
                                            local rdir = (p - pp):dot(D.epos(rd.body, ie, 'left') - D.epos(rd.body, ie, 'right'))
                                            if bcross then
                b.list[ndi] = jdesc.p + b.dir*r
                if b.list[ndi]:distance(b.list[ndi+b.io]) < b.w or (b.list[ndi+b.io]-b.list[ndi]):dot(b.dir)<0 then
                    lo('??*************** to_CUT:'..i)
    local pmid = onSide(desc, 'middle', rdlen/2)
    if a.dir:dot(b.dir) > 0 then
        local d,p = U.toLine(pmid, {list[2],list[3]})
    for i,b in pairs(ajunc[rd.ij[1]].list) do
        local cang = U.vang(b.dir, -rd.dir, true) --b.dir:dot(-rd.dir)
        if i ~= rd.ij[2] then
--[[
        if (car.target.p-car.pos):dot(e.list[1]-car.pos)>0 then
            if car.pos:distance(e.list[1]) < dmi then
                for k,n in pairs(rd.list) do
                    if dircar:dot(n-car.pos) > 0 and n:distance(car.pos) >= default.v2tmin then
                        if car.pos:distance(n) < dmi then
            local ito,step = obj:getEdgeCount()-1,1
            local dir = dirroad:dot(dircar) > 0 and 1 or -1
                lo('?? for_dir:'..tostring(dirroad)..':'..tostring(dircar)..':'..dir)
]]
                local ang = (target-car.pos):normalized():dot((target-(car.pos+dircar*1)):normalized())
    --                lo('?? for_ang:'..k..':'..ang)
                if ang > 0.995 then -- math.sqrt(2)/2 then
    --            if dircar:dot((target-(car.pos+dircar*1)):normalized()) > math.sqrt(2)/2 then
                        out.agreen = {target}
                end
    --                lo('?? for_next:'..k..':'..ang) --dircar:dot((target-car.pos):normalized()))
            end
                for k,n in pairs(rd.list) do
                    if dircar:dot(n-car.pos) > 0 and n:distance(car.pos) >= default.v2tmin then
                        if car.pos:distance(n) < dmi then
            local ito,step = obj:getEdgeCount()-1,1
            local dir = dirroad:dot(dircar) > 0 and 1 or -1
            if dir == -1 then
                end
                local ang = (target-car.pos):normalized():dot((target-(car.pos+dircar*1)):normalized())
    --                lo('?? for_ang:'..k..':'..ang)
                if ang > 0.995 then -- math.sqrt(2)/2 then
    --            if dircar:dot((target-(car.pos+dircar*1)):normalized()) > math.sqrt(2)/2 then
                        out.avedit = {target}
                end
    --                lo('?? for_next:'..k..':'..ang) --dircar:dot((target-car.pos):normalized()))
            end
    --                                lo('?? if_nbr:'..i..':'..)
                                local cang = b.dir:dot(-rd.dir)
                                if i ~= rd.ij[2] and cang > ama then
        if true then
            if dirroad:dot(adec[ijmi[1] ].list[ijmi[2] ]-car.pos) > 0 then
                -- goto right lane
                            local k2 = k < #dec.list and k+1 or k
                            local isin = (U.proj2D(dec.list[k])-p):dot(U.proj2D(dec.list[k2])-p)
                            if d < dmi and isin<0 then --and (D.epos(adec[j].body, ie1)-p):dot(D.epos(adec[j].body,ie2)-p)<0 then
                            local isin = (U.proj2D(dec.list[k])-p):dot(U.proj2D(dec.list[k2])-p)
                            if d < dmi and isin<0 then --and (D.epos(adec[j].body, ie1)-p):dot(D.epos(adec[j].body,ie2)-p)<0 then
                                dmi = d
                end
--                    lo('?? for_DIR:'..jmi..':'..ie1..':'..ie2..':'..tostring(D.epos(adec[jmi].body, ie1)-p)..':'..tostring((D.epos(adec[jmi].body,ie2)-p))..':'..tostring(p))-- :dot(D.epos(adec[jmi].body,ie2)-p))
                    lo('?? if_HIT:'..tostring(dmi)..':'..tostring(jmi)) --..':'..nmi..':'..adec[jmi].ind) --..' ie:'..ie1..':'..tostring(adec[jmi].ne))
                            -- TAKE EXIT
--                        if (car.target.exit.p-car.target.p):dot(dir) < 3 or time2exit < 5 then
--                        if toexit < car.pos:distance(car.target.p) + 2 or time2exit < 5 then
@/lua/ge/extensions/core/multiSpawn.lua
    local p1, p2 = mapNodes[n1].pos, mapNodes[n2].pos
    if (p2 - p1):dot(rot) < 0 then
      n1, n2 = n2, n1
      dist = origin:distance(p1)
      lane = rot:z0():cross(vecUp):dot((pos - origin):z0()) >= 0 and 1 or -1
    else
@/lua/ge/extensions/core/cameraModes/orbit.lua
  local nbase = base:normalized()
  return math.atan2(-nbase:dot(nxn), nbase:dot(nyn)), math.asin(nbase:dot(nzn))
end
  local nbase = base:normalized()
  return math.atan2(-nbase:dot(nxn), nbase:dot(nyn)), math.asin(nbase:dot(nzn))
end
  local nbase = base:normalized()
  return math.atan2(-nbase:dot(nxn), nbase:dot(nyn)), math.asin(nbase:dot(nzn))
end
      camdir:set(push3(self.camLastTargetPos) - self.camLastPos2)
      if sign((push3(targetPos) - self.camLastTargetPos):dot(camdir)) < 0 then
        self.camRot.x = self.camRot.x + 180
      moveDir:set(push3(targetPos) - self.camLastTargetPos); moveDir:normalize()
      if math.abs(push3(lastCamPointVec):normalized():dot(moveDir)) > math.abs(push3(lastCamLastPerp):normalized():dot(moveDir)) then
        self.camLastPos2:set(push3(lastCamPointVec):cross(lastCamLastPerp):cross(lastCamLastPerp):normalized() + targetPos)
      moveDir:set(push3(targetPos) - self.camLastTargetPos); moveDir:normalize()
      if math.abs(push3(lastCamPointVec):normalized():dot(moveDir)) > math.abs(push3(lastCamLastPerp):normalized():dot(moveDir)) then
        self.camLastPos2:set(push3(lastCamPointVec):cross(lastCamLastPerp):cross(lastCamLastPerp):normalized() + targetPos)
@/lua/ge/extensions/gameplay/race/startPosition.lua
  local posOffset = (pos - fl)
  local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
  local posOffset = (pos - fl)
  local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
  local posOffset = (pos - fl)
  local localOffset = vec3(xVeh:dot(posOffset), yVeh:dot(posOffset), zVeh:dot(posOffset))
@/lua/ge/extensions/editor/gen/terrain.lua
                local sgn = U.vang(d-c,path[i].p-pp)>0 and -1 or 1
--                local sgn = -1 -- (b-a):dot(d-c) > 0 and -1 or 1
                if angValid(ang) and U.vang(d-U.mod(i-1,path).p,p-U.mod(i-1,path).p,true)>0 then
    table.sort(ahit, function(u,v)
        return (b-a):dot(u.p-a) < (b-a):dot(v.p-a)
    end)
    table.sort(ahit, function(u,v)
        return (b-a):dot(u.p-a) < (b-a):dot(v.p-a)
    end)
        if list[1]:distance(list[2]) > default.SLICE_MIN
            and (list[1]-list[2]):dot(h1.p-h2.p)>0 then
--            aseg[#aseg+1] = list
        if cb and ce then
            dnorm = (dnorm*(ce - cb):dot(dnorm)):normalized()
            local W = math.abs((cb-ce):dot(dnorm))
            dnorm = (dnorm*(ce - cb):dot(dnorm)):normalized()
            local W = math.abs((cb-ce):dot(dnorm))
            local nstep = math.floor(W/space)

                    if (pm-reg.p):dot(pm-c) < 0 then
                        -- set middle boundary node
@/lua/ge/extensions/gameplay/rally/vehicleTracker.lua
        local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
        local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
        table.insert(self.wheelOffsets, pos)
        local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
        local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
        table.insert(self.wheelOffsets, pos)
        local nodePos = vec3(vehicle:getNodePosition(axisNodes[1]))
        local pos = vec3(nodePos:dot(x), nodePos:dot(y), nodePos:dot(z))
        table.insert(self.wheelOffsets, pos)
@/lua/vehicle/extensions/tech/ACC.lua
local function project(a, b)
    return (a:dot(b) / b:dot(b)) * b
end
local function project(a, b)
    return (a:dot(b) / b:dot(b)) * b
end
            local distantPoint = pos + (1e12 * fwd) -- A point on the player vehicle forward vector, far in the distance.
            if fwd:dot(fwdB) > 0.0 and (distantPoint - pos):lenSquared() > (distantPoint - posB):lenSquared() then -- Test that other vehicle is in front hemisphere and has same dir.
                local distToPlayerVehicleSq = (pos - posB):lenSquared() -- The squared distance between the player and other vehicle.
@/lua/ge/extensions/flowgraph/nodes/gameplay/rally/vehicleStoppedNearPlane.lua
--   tmpVec2:setSub2(vehPos, planePos)  -- toVehicle
--   local dist = tmpVec2:dot(tmpVec1)
--   local signedDistance = dist
  tmpToVehicle:setSub2(vehPos, planePos)
  local dist = tmpToVehicle:dot(tmpPlaneNormal)