Added initial media and code
parent
0c4b04f0db
commit
e7ddf5e94e
|
@ -0,0 +1,594 @@
|
||||||
|
-----------------‐---------------------------------------------------------------------------------
|
||||||
|
-- Advanced Vehicles II API by Andrey01
|
||||||
|
-----‐---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
vehicles = {}
|
||||||
|
|
||||||
|
gravity = -9.8
|
||||||
|
|
||||||
|
local showed_seats_fspecs = {} -- pair: ["playername"] and objectref
|
||||||
|
|
||||||
|
local ngroups_friction_coefs = { -- friction coefficients of some groups of nodes.
|
||||||
|
["sand"] = 1.5,
|
||||||
|
["soil"] = 0.6,
|
||||||
|
["snowy"] = 0.9,
|
||||||
|
["slippery"] = 0.1,
|
||||||
|
["default"] = 0.8
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Air resistance force is calculated for now only along the horizontal plane!
|
||||||
|
local air_rcoef = 0.3 -- air resistance coefficient
|
||||||
|
|
||||||
|
|
||||||
|
-----‐---------------------------------------------------------------------
|
||||||
|
-- API functions
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
vehicles.set_gravity = function(self)
|
||||||
|
local obj = self.object
|
||||||
|
local acc = obj:get_acceleration()
|
||||||
|
local vel = obj:get_velocity()
|
||||||
|
local m = minetest.registered_entities[self.name].mass
|
||||||
|
obj:set_acceleration({x=acc.x, y=gravity, z=acc.z})
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[ Registers new vehicle (base and wheel)
|
||||||
|
base_props and wheel_props should contain def props for entity ('obj') and its item ('item')
|
||||||
|
]]
|
||||||
|
vehicles.register_vehicle = function(name, base_props, wheel_props)
|
||||||
|
minetest.register_entity(MOD_NAME .. ":" .. name .. "_base", {
|
||||||
|
vehicle_type = base_props.obj.vehicle_type,
|
||||||
|
physical = true,
|
||||||
|
mass = base_props.obj.mass or 2000, -- in kgs
|
||||||
|
collide_with_objects = true,
|
||||||
|
collisionbox = base_props.obj.bounding_box or {-0.5, 0.0, -0.5, 0.5, 1.0, 0.5},
|
||||||
|
selectionbox = base_props.obj.bounding_box or {-0.5, 0.0, -0.5, 0.5, 1.0, 0.5},
|
||||||
|
visual = base_props.obj.visual,
|
||||||
|
visual_size = base_props.obj.visual_size or {x=1, y=1, z=1},
|
||||||
|
mesh = (base_props.obj.visual == "mesh" and base_props.obj.mesh),
|
||||||
|
textures = base_props.obj.textures or {""},
|
||||||
|
use_texture_alpha = base_props.obj.use_texture_alpha,
|
||||||
|
seats = base_props.obj.seats, -- table fields: {["is_busy"] = playername, ["pos"] = position, ["rot"] = rotation, ["type"] = ("driver" or "passenger"), ["model"] = <name>}
|
||||||
|
--ctrl_vals = base_props.ctrl_vals, -- table fields: {["move"] = float (acc_len), ["turn"] = float (degs)}
|
||||||
|
traction_force = base_props.obj.traction_force or 5000, -- in Neutons
|
||||||
|
wheels = base_props.obj.wheels, -- table fields: {["type"] = ("front" or "rear"), ["pos"] = position, ["rot"] = rotation, ["radius"] = wheel radius}
|
||||||
|
max_speed = base_props.obj.max_speed or 25000, -- in m/s
|
||||||
|
stepheight = base_props.obj.stepheight or 0.5,
|
||||||
|
on_activate = function(self, staticdata, dtime_s)
|
||||||
|
self.seats = table.copy(base_props.obj.seats)
|
||||||
|
|
||||||
|
for i, seat in ipairs(self.seats) do
|
||||||
|
seat.rot = seat.rot or {x=0, y=0, z=0}
|
||||||
|
seat.radius = seat.radius or 0.5
|
||||||
|
end
|
||||||
|
self.wheels = {}
|
||||||
|
self.tracf_dir = 0 -- specifies a modulo and direction of the vehicle traction force (> 0 on forward, < 0 on backward, = 0 on stay)
|
||||||
|
|
||||||
|
--[[if base_props.obj.player_model_def then
|
||||||
|
self.player_models = {}
|
||||||
|
if base_props.obj.player_model_def.driver then
|
||||||
|
player_api.register_model(base_props.obj.player_model_def.driver.name, table.derive_elems(base_props.obj.player_model_def.driver, 2, #base_props.obj.player_model_def.driver))
|
||||||
|
self.player_models.driver = base_props.obj.player_model_def.driver.name
|
||||||
|
end
|
||||||
|
if base_props.obj.player_model_def.passenger then
|
||||||
|
player_api.register_model(base_props.obj.player_model_def.passenger.name, table.derive_elems(base_props.obj.player_model_def.passenger, 2, #base_props.obj.player_model_def.passenger))
|
||||||
|
self.player_models.passenger = base_props.obj.player_model_def.passenger.name
|
||||||
|
end
|
||||||
|
end]]
|
||||||
|
local rel_vehpos = self.object:get_pos()
|
||||||
|
local vehrot = self.object:get_rotation()
|
||||||
|
for i, whl in ipairs(base_props.obj.wheels) do
|
||||||
|
local whl_obj = minetest.add_entity({x=rel_vehpos.x+whl.pos.x, y=rel_vehpos.y+whl.pos.y, z=rel_vehpos.z+whl.pos.z}, MOD_NAME .. ":" .. name .. "_wheel")
|
||||||
|
whl_obj:set_attach(self.object, "", whl.pos, whl.rot or {0, 0, 0})
|
||||||
|
self.wheels[i] = {object=whl_obj, type=whl.type, pos=whl.pos, rot=whl.rot or {0, 0, 0}, radius=whl.radius}
|
||||||
|
end
|
||||||
|
vehicles.set_gravity(self)
|
||||||
|
--self.acc_v2d = vehicles.v2d_coords(base_props.traction_force/base_props.mass, vehrot.y) -- keep own vehicle 2d acceleration along horizontal plane that doesn`t depend to external impacts
|
||||||
|
end,
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
local max_fcoef = vehicles.max_fric_coef(self)
|
||||||
|
local edef = minetest.registered_entities[self.name]
|
||||||
|
local acc = self.object:get_acceleration()
|
||||||
|
local sf_fforce = vehicles.surface_fric_force(max_fcoef, edef.mass, acc.y*edef.mass)
|
||||||
|
local vel = self.object:get_velocity()
|
||||||
|
local v2d_vl = vehicles.v2d_length(vel)
|
||||||
|
local air_rforce = vehicles.air_resist_force(v2d_vl)
|
||||||
|
vehicles.on_move(self)
|
||||||
|
if v2d_vl == 0 then self.tracf_dir = 0 sf_fforce = 0 end
|
||||||
|
if self.tracf_dir > 0 then sf_fforce = -sf_fforce air_rforce = -air_rforce end
|
||||||
|
|
||||||
|
local acc_sum = (self.tracf_dir + sf_fforce + air_rforce)/edef.mass
|
||||||
|
local acc2d = vehicles.v2d_coords(acc_sum, self.object:get_yaw())
|
||||||
|
minetest.debug(dump(acc2d))
|
||||||
|
self.object:set_acceleration({x=acc2d.x, y=acc.y, z=acc2d.z})
|
||||||
|
|
||||||
|
for i, d in ipairs(self.wheels) do
|
||||||
|
d.object:set_rotation(vehicles.calc_angle_vel(vel, d.radius))
|
||||||
|
end
|
||||||
|
|
||||||
|
end,
|
||||||
|
on_death = function(self, killer)
|
||||||
|
for i, sdata in ipairs(self.seats) do
|
||||||
|
vehicles.get_out(self, sdata.is_busy and minetest.get_player_by_name(sdata.is_busy))
|
||||||
|
end
|
||||||
|
for n, obj in pairs(showed_seats_fspecs) do
|
||||||
|
if obj == self.object then
|
||||||
|
vehicles.close_seats_formspec(self, n, MOD_NAME .. ":vehicle_seats")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i, whl in ipairs(self.wheels) do
|
||||||
|
whl.object:remove()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_rightclick = function(self, clicker)
|
||||||
|
vehicles.show_seats_formspec(self, MOD_NAME .. ":vehicle_seats", clicker:get_player_name())
|
||||||
|
end
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_craftitem(MOD_NAME .. ":" .. name .. "_base", {
|
||||||
|
description = base_props.item.description or "",
|
||||||
|
inventory_image = base_props.item.inv_image or "",
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
if pointed_thing.type =="node" and pointed_thing.above.y >= pointed_thing.under.y then
|
||||||
|
minetest.add_entity(pointed_thing.above, itemstack:get_name())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_entity(MOD_NAME .. ":" .. name .. "_wheel", {
|
||||||
|
visual_size = wheel_props.obj.visual_size or {x=1, y=1, z=1},
|
||||||
|
pointable = false,
|
||||||
|
visual = wheel_props.obj.visual,
|
||||||
|
mesh = (wheel_props.obj.visual == "mesh" and wheel_props.obj.mesh),
|
||||||
|
textures = wheel_props.obj.textures or {""},
|
||||||
|
use_texture_alpha = wheel_props.obj.use_texture_alpha
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem(MOD_NAME .. ":" .. name .. "_wheel", {
|
||||||
|
description = wheel_props.item.description or "",
|
||||||
|
inventory_image = wheel_props.item.inventory_image or ""
|
||||||
|
})
|
||||||
|
|
||||||
|
if base_props.obj.player_mdefs then
|
||||||
|
if base_props.obj.player_mdefs.driver then
|
||||||
|
player_api.register_model(base_props.obj.player_mdefs.driver.model_name, base_props.obj.player_mdefs.driver.def)
|
||||||
|
elseif base_props.obj.player_mdefs.passenger then
|
||||||
|
player_api.register_model(base_props.obj.player_mdefs.passenger.model_name, base_props.obj.player_mdefs.passenger.def)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vehicles.show_seats_formspec = function(self, formspec_name, playername)
|
||||||
|
local seats_n = #self.seats
|
||||||
|
local sbut_size = {x=4, y=1.5}
|
||||||
|
local pad = 0.5
|
||||||
|
local visible_cbuts_n = (seats_n <= 4 and seats_n or 4)
|
||||||
|
local scontainer_size = {x=2*0.3 + sbut_size.x, y=visible_cbuts_n*sbut_size.y + (visible_cbuts_n+1)*0.3}
|
||||||
|
|
||||||
|
local wsize_x = pad*2 + scontainer_size.x
|
||||||
|
local is_player_sit = vehicles.is_player_sit(minetest.get_player_by_name(playername))
|
||||||
|
local wsize_y = 2 + scontainer_size.y + (is_player_sit and 2.5 or pad) -- + 2.5 units for 'Get Up' button placement
|
||||||
|
|
||||||
|
local formspec = "formspec_version[3]size[" .. wsize_x .. ", " .. wsize_y .. "]" ..
|
||||||
|
"label[" .. pad + 0.2 .. "," .. pad + 0.5 .. ";" .. minetest.formspec_escape("Select a seat to sit down or press to get up:") .. "]" ..
|
||||||
|
"box[" .. pad .. ",2;" .. scontainer_size.x .. "," .. scontainer_size.y .. ";#000]" ..
|
||||||
|
"scrollbaroptions[thumbsize=1000]" ..
|
||||||
|
"scrollbar[" .. scontainer_size.x + pad .. ",2;0.3," .. scontainer_size.y .. ";vertical;vseats_scrollbar;0]" ..
|
||||||
|
"scroll_container[" .. pad .. ",2;" .. scontainer_size.x .. "," .. scontainer_size.y .. ";vseats_scrollbar;vertical;]"
|
||||||
|
|
||||||
|
local butpos_y = 0.3
|
||||||
|
for i, sdata in ipairs(self.seats) do
|
||||||
|
local i_busy = sdata.is_busy
|
||||||
|
formspec = formspec .. (i_busy and "style[seat_" .. i .. ";bgcolor=#FF0000]" or "") .. "button[0.3," .. butpos_y .. ";" .. sbut_size.x .. "," .. sbut_size.y ..
|
||||||
|
";seat_" .. i .. ";" .. minetest.formspec_escape("#" .. i .. ((i_busy and "\n(busy by " .. playername .. ")") or "")) .. "]"
|
||||||
|
|
||||||
|
butpos_y = butpos_y + sbut_size.y + 0.3
|
||||||
|
end
|
||||||
|
|
||||||
|
formspec = formspec .. "scroll_container_end[]" ..
|
||||||
|
(is_player_sit and "button[" .. wsize_x/2 - sbut_size.x/2 .. "," .. (wsize_y - (2.5/4*3)) .. ";4,1.5;get_up;" .. minetest.formspec_escape("Get up") .. "]" or "")
|
||||||
|
|
||||||
|
|
||||||
|
showed_seats_fspecs[playername] = self.object
|
||||||
|
minetest.show_formspec(playername, formspec_name, formspec)
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[vehicles.show_seats_formspec = function(self, formspec_name, playername)
|
||||||
|
local seats_n = #self.seats
|
||||||
|
local min_sbut_s = {x=1, y=0.5} -- min seat button size
|
||||||
|
local max_sbut_s = {x=4, y=2}
|
||||||
|
local buts_space_w = 0.3 -- space button size doesn`t depend on buttons` sizes
|
||||||
|
local buts_space_h = 0.2
|
||||||
|
local w_sbut, h_sbut = 0.5, 0.5 -- distance between window edge and button doesn`t depend on buttons` sizes
|
||||||
|
|
||||||
|
local sizedowns_n = math.ceil(math.sqrt(seats_n)) -- number of button sizedowns
|
||||||
|
local but_new_x_s = max_sbut_s.x-0.5*sizedowns_n
|
||||||
|
local but_new_y_s = max_sbut_s.y-0.5*sizedowns_n
|
||||||
|
|
||||||
|
local wsize_chx = 0
|
||||||
|
local wsize_chy = 0
|
||||||
|
if but_new_x_s < min_sbut_s.x or but_new_y_s < min_sbut_s.y then
|
||||||
|
but_new_x_s = min_sbut_s.x
|
||||||
|
but_new_y_s = min_sbut_s.y
|
||||||
|
|
||||||
|
wsize_chx = 1.5*sizedowns_n-(max_sbut_s.x-min_sbut_s.x)
|
||||||
|
wsize_chy = 1.5*sizedowns_n-(max_sbut_s.y-min_sbut_s.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
local wsize_x = sizedowns_n*but_new_x_s + 2*w_sbut + (sizedowns_n-1)*buts_space_w + wsize_chx
|
||||||
|
local wsize_y = sizedowns_n*but_new_y_s + 2*h_sbut + (sizedowns_n-1)*buts_space_h + wsize_chy + 2 -- '+ 2' is a space for label text
|
||||||
|
local is_player_sit = vehicles.is_player_sit(minetest.get_player_by_name(playername))
|
||||||
|
wsize_y = is_player_sit and wsize_y + 2 or wsize_y
|
||||||
|
|
||||||
|
local formspec = "formspec_version[3]size[" .. wsize_x .. ", " .. wsize_y .. "]label[" .. wsize_x/4 .. ",1;" .. minetest.formspec_escape("Select a seat to sit down or press to get up:") .. "]"
|
||||||
|
|
||||||
|
local bpos_x = w_sbut
|
||||||
|
local bpos_y = 2
|
||||||
|
|
||||||
|
for i = 1, seats_n do
|
||||||
|
minetest.debug(i)
|
||||||
|
bpos_x = ((i <= sizedowns_n or i > (math.pow(sizedowns_n, 2)-sizedowns_n)) and bpos_x + w_sbut) or bpos_x + buts_space_w
|
||||||
|
bpos_y = ((i%sizedowns_n == 0) and bpos_y + h_sbut) or (((i-1)%sizedowns_n == 0) and 2 + h_sbut) or bpos_y + buts_space_h
|
||||||
|
|
||||||
|
local i_busy = self.seats[i].is_busy
|
||||||
|
formspec = formspec .. ((i_busy and "style[seat_" .. i .. ";bgcolor=#FF0000]") or "")
|
||||||
|
formspec = formspec .. "button[" ..
|
||||||
|
bpos_x .. "," .. bpos_y .. ";" ..
|
||||||
|
but_new_x_s .. "," .. but_new_y_s ..
|
||||||
|
";seat_" .. i .. ";" .. minetest.formspec_escape("#" .. i .. ((i_busy and "\n" .. playername) or "")) .. "]"
|
||||||
|
|
||||||
|
bpos_x = (i ~= 1 and (i-1)%sizedowns_n == 0 and bpos_x + but_new_x_s) or bpos_x
|
||||||
|
bpos_y = bpos_y + but_new_y_s
|
||||||
|
|
||||||
|
bpos_x = i == (math.pow(sizedowns_n, 2)-sizedowns_n+1) and bpos_x + w_sbut or (i-1)%sizedowns_n == 0 and bpos_x + buts_space_w
|
||||||
|
bpos_y = i%sizedowns_n == 0 and 2 or bpos_y + buts_space_h
|
||||||
|
end
|
||||||
|
|
||||||
|
formspec = (is_player_sit and (formspec .. "button[" ..
|
||||||
|
wsize_x/2 - ((but_new_x_s+2)/2) .. "," .. bpos_y .. ";" ..
|
||||||
|
but_new_x_s+2 .. "," .. wsize_y - bpos_y - (buts_space_h + 0.5 + h_sbut) ..
|
||||||
|
";get_up;" .. minetest.formspec_escape("Get up") .. "]")) or formspec
|
||||||
|
|
||||||
|
|
||||||
|
showed_seats_fspecs[playername] = self.object
|
||||||
|
minetest.show_formspec(playername, formspec_name, formspec)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end]]
|
||||||
|
--[[vehicles.show_seats_formspec = function(self, formspec_name, playername)
|
||||||
|
local seats_n = #self.seats
|
||||||
|
--minetest.debug(seats_n)
|
||||||
|
local buts_space_w = 0.2
|
||||||
|
local buts_space_h = 0.3 -- space between buttons along width and height
|
||||||
|
local int = math.modf(seats_n/8)
|
||||||
|
local columns_n = (seats_n % 8 == 0 and int) or int + 1
|
||||||
|
local max_col_cells_n = (seats_n >= 8 and 8) or seats_n
|
||||||
|
local w_sbut, h_sbut = 2, 0.5
|
||||||
|
local fspec_size_w = columns_n * w_sbut + (columns_n + 1) * buts_space_w
|
||||||
|
local fspec_size_h = max_col_cells_n * h_sbut + (max_col_cells_n+1) * buts_space_h + 2 -- + 2 is a space for label text
|
||||||
|
local is_player_sit = vehicles.is_player_sit(minetest.get_player_by_name(playername))
|
||||||
|
fspec_size_h = (is_player_sit and fspec_size_h + 2) or fspec_size_h -- if player sits the vehicle, heighten the formspec window still at 2 units
|
||||||
|
local formspec = "size[" .. fspec_size_w .. ", " .. fspec_size_h .. "]label[2,1;" .. minetest.formspec_escape("Select a vacant seat inside the vehicle below:") .. "]"
|
||||||
|
|
||||||
|
local bpos_x = buts_space_w
|
||||||
|
minetest.debug(bpos_x)
|
||||||
|
local bpos_y = buts_space_h+2
|
||||||
|
for i = 1, seats_n do
|
||||||
|
formspec = formspec .. "button[" ..
|
||||||
|
tostring(bpos_x) .. "," .. bpos_y .. ";" ..
|
||||||
|
w_sbut .. "," .. h_sbut ..
|
||||||
|
";seat_" .. i .. ";" .. minetest.formspec_escape("Seat #" .. i) .. "]"
|
||||||
|
bpos_x = ((i - 1) % 8 == 0) and bpos_x + w_sbut + buts_space_w
|
||||||
|
bpos_y = (((i - 1) % 8 == 0) and buts_space_h+2) or bpos_y + h_sbut + buts_space_h
|
||||||
|
end
|
||||||
|
|
||||||
|
formspec = (is_player_sit and (formspec .. "button[" .. fspec_size_w / 2 - w_sbut / 2 .. ", " .. fspec_size_h - 1.5 .. ";" .. w_sbut .. ", " .. h_sbut .. ";get_out;" .. minetest.formspec_escape("Get out") .. "]")) or formspec
|
||||||
|
--minetest.debug(formspec)
|
||||||
|
showed_seats_fspecs[playername] = self.object
|
||||||
|
minetest.show_formspec(playername, formspec_name, formspec)
|
||||||
|
end]]
|
||||||
|
|
||||||
|
vehicles.sit = function(self, player, seat_id) -- seat_id is an id of a seat table of 'self.seats'
|
||||||
|
local sel_seat = self.seats[seat_id]
|
||||||
|
local plname = player:get_player_name()
|
||||||
|
if type(sel_seat.is_busy) == "string" and sel_seat.is_busy ~= plname then
|
||||||
|
minetest.chat_send_player(plname, "Seat #" .. seat_id .. " is busy by " .. sel_seat.is_busy .. "!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local cur_seat = vehicles.is_player_sit(player)
|
||||||
|
if cur_seat then
|
||||||
|
self.seats[cur_seat.seat_id].is_busy = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
sel_seat.is_busy = player:get_player_name()
|
||||||
|
local plmeta = player:get_meta()
|
||||||
|
local anim = player_api.get_animation(player)
|
||||||
|
local pl_mdefs = minetest.registered_entities[self.name].player_mdefs
|
||||||
|
local pl_data = {}
|
||||||
|
if pl_mdefs then
|
||||||
|
if sel_seat.type == "driver" and pl_mdefs.driver then
|
||||||
|
pl_data.prev_model = anim.model
|
||||||
|
pl_data.prev_anim = anim.animation
|
||||||
|
player_api.set_model(player, pl_mdefs.driver.model_name)
|
||||||
|
elseif sel_seat.type == "passenger" and pl_mdefs.passenger then
|
||||||
|
pl_data.prev_model = anim.model
|
||||||
|
pl_data.prev_anim = anim.animation
|
||||||
|
player_api.set_model(player, pl_mdefs.passenger.model_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pl_data.prev_pos = player:get_pos()
|
||||||
|
pl_data.prev_rot = player:get_rotation()
|
||||||
|
pl_data.seat_id = seat_id
|
||||||
|
plmeta:set_string("prev_data", minetest.serialize(pl_data))
|
||||||
|
player:set_attach(self.object, "", sel_seat.pos, sel_seat.rot)
|
||||||
|
player:set_eye_offset(sel_seat.pos, sel_seat.pos)
|
||||||
|
player:set_look_horizontal(self.object:get_yaw()+180)
|
||||||
|
player_api.player_attached[player:get_player_name()] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
vehicles.get_out = function(self, player)
|
||||||
|
if not player or not self.object:get_luaentity() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
player:set_detach()
|
||||||
|
local plmeta = player:get_meta()
|
||||||
|
local pl_data = minetest.deserialize(plmeta:get_string("prev_data"))
|
||||||
|
if pl_data.prev_model then
|
||||||
|
player_api.set_model(player, pl_data.prev_model)
|
||||||
|
end
|
||||||
|
if pl_data.prev_anim then
|
||||||
|
player_api.set_animation(player, pl_data.prev_anim)
|
||||||
|
end
|
||||||
|
local seat = self.seats[pl_data.seat_id]
|
||||||
|
seat.is_busy = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
vehicles.on_formspec_event = function(player, formname, fields)
|
||||||
|
if formname ~= MOD_NAME .. ":vehicle_seats" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local plname = player:get_player_name()
|
||||||
|
local obj = showed_seats_fspecs[plname]
|
||||||
|
local self = obj:get_luaentity()
|
||||||
|
if self then
|
||||||
|
for i, sdata in ipairs(self.seats) do
|
||||||
|
local but_name = "seat_" .. i
|
||||||
|
if fields[but_name] then
|
||||||
|
vehicles.close_seats_formspec(self, plname, formname, "sit", i)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["get_up"] then
|
||||||
|
vehicles.close_seats_formspec(self, plname, formname, "get_up")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
else -- supposed that vehicle is died while the player is viewing the formspec
|
||||||
|
vehicles.close_seats_formspec(self, plname, formname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns traction force along according direction or nil if no player as a driver or any driving keys are not pressed
|
||||||
|
vehicles.on_move = function(self)
|
||||||
|
local drv_name = self.seats[vehicles.get_driver_i(self)].is_busy
|
||||||
|
if not drv_name then return end
|
||||||
|
minetest.debug("Driver is available!")
|
||||||
|
local player = minetest.get_player_by_name(drv_name)
|
||||||
|
local ctrls = player:get_player_control()
|
||||||
|
local entity_def = minetest.registered_entities[self.name]
|
||||||
|
if ctrls.up then
|
||||||
|
self.tracf_dir = entity_def.traction_force
|
||||||
|
end
|
||||||
|
if ctrls.down then
|
||||||
|
self.tracf_dir = -entity_def.traction_force
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
--[[if ctrls.up and vehicles.v2d_length(self.acc_v2d) == 0 then
|
||||||
|
local new_acc = vector.add(acc, {x=self.acc_v2d.x, y=0, z=self.acc_v2d.z})
|
||||||
|
self.object:set_acceleration(new_acc)
|
||||||
|
else
|
||||||
|
self.acc_v2d = {x=0, z=0}
|
||||||
|
end
|
||||||
|
|
||||||
|
if ctrls.down and vehicles.v2d_length(self.acc_v2d) == 0 then
|
||||||
|
local new_acc = vector.add(acc, {x=-self.acc_v2d.x, y=0, z=-self.acc_v2d.z})
|
||||||
|
self.object:set_acceleration(new_acc)
|
||||||
|
else
|
||||||
|
self.acc_v2d = {x=0, z=0}
|
||||||
|
end]]
|
||||||
|
--[[ local acc_len = vector.length(acc)
|
||||||
|
if acc_len <= ctrl_vals.up then
|
||||||
|
new_acc.x = acc.x
|
||||||
|
new_acc.z = acc.z
|
||||||
|
local v_and_a_codir = vehicles.are_horiz_codirectional(acc, vel)
|
||||||
|
if type(v_and_a_codir) == "number" then]]
|
||||||
|
|
||||||
|
--[[vehicles.force_brake = function(self)
|
||||||
|
local max_fcoef = vehicles.max_fric_coef(self)
|
||||||
|
local edef = minetest.registered_entities[self.name]
|
||||||
|
local fric_force = vehicles.friction_force(max_fcoef, edef.mass, math.abs(self.object:get_acceleration().y))
|
||||||
|
local acc = self.object:get_acceleration()
|
||||||
|
local tracforce = edef.mass*vehicles.v2d_length({x=acc.x, z=acc.z})
|
||||||
|
local new_acc_len = (tracforce-fric_force)/edef.mass
|
||||||
|
local new_acc_coords = vector
|
||||||
|
|
||||||
|
local brake_vec = vehicles.get_acc_vect(vehicles.v2d_length({x=acc.x, z=acc.z})/max_fcoef, acc.y, self.object:get_yaw()+math.rad(180))]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-------‐---------------------------------------------------------------------
|
||||||
|
-- Helper functions
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Derives the elements from range 'i1' up to 'i2' of 't' table into new one
|
||||||
|
-- i1 and i2 can be only positive
|
||||||
|
-- NOTE: table keys can be not only integral
|
||||||
|
table.derive_elems = function(t, i1, i2)
|
||||||
|
local new_t = {}
|
||||||
|
local elem_c = 0
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
elem_c = elem_c + 1
|
||||||
|
if elem_c > i2 then
|
||||||
|
return new_t
|
||||||
|
end
|
||||||
|
new_t[k] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
return new_t
|
||||||
|
end
|
||||||
|
|
||||||
|
vehicles.is_player_sit = function(player)
|
||||||
|
local obj = player:get_attach()
|
||||||
|
if not obj then return false end
|
||||||
|
|
||||||
|
local prev_data = minetest.deserialize(player:get_meta():get_string("prev_data"))
|
||||||
|
return prev_data
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 'seat_id' is optional
|
||||||
|
-- 'action' is supposed what to do with the player after closing (sit or go out off the vehicle) [optional]
|
||||||
|
vehicles.close_seats_formspec = function(self, playername, formname, action, seat_id)
|
||||||
|
local player = minetest.get_player_by_name(playername)
|
||||||
|
if action == "sit" then
|
||||||
|
local is_busy = self.seats[seat_id].is_busy
|
||||||
|
if is_busy then return end
|
||||||
|
vehicles.sit(self, player, seat_id)
|
||||||
|
elseif action == "get_up" then
|
||||||
|
vehicles.get_out(self, player)
|
||||||
|
local pl_meta = player:get_meta()
|
||||||
|
local pl_data = minetest.deserialize(pl_meta:get_string("prev_data"))
|
||||||
|
player:set_pos(pl_data.prev_pos)
|
||||||
|
player:set_rotation(pl_data.prev_rot)
|
||||||
|
pl_data = nil
|
||||||
|
pl_meta:set_string("prev_data", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.close_formspec(playername, formname)
|
||||||
|
showed_seats_fspecs[playername] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns index in seats table where driver data is.
|
||||||
|
vehicles.get_driver_i = function(self)
|
||||||
|
if not self then return end
|
||||||
|
for i, sdata in ipairs(self.seats) do
|
||||||
|
if sdata.type == "driver" then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- checks if given vectors are co-directional along the horizontal plane; returns true, if they are, otherwise angle between them
|
||||||
|
--[[vehicles.are_horiz_codirectional = function(acc, vel)
|
||||||
|
local vec1 = vector.new(acc.x, 0, acc.z)
|
||||||
|
local vec2 = vector.new(vel.x, 0, vel.z)
|
||||||
|
local angle = math.deg(vector.angle(vec1, vec2))
|
||||||
|
|
||||||
|
return (angle == 0) or (angle
|
||||||
|
end]]
|
||||||
|
|
||||||
|
-- Calculates an angle speed (in rads) of the wheel
|
||||||
|
vehicles.calc_angle_vel = function(vel, radius)
|
||||||
|
return {x=vel.x/radius, y=vel.y/radius, z=vel.z/radius}
|
||||||
|
end
|
||||||
|
|
||||||
|
--vehicles.rotate_acc_vect = function(old_acc, turn_ang)
|
||||||
|
-- Calculates new (relative) coords of the acceleration vector
|
||||||
|
vehicles.v2d_coords = function(a_len, yaw)
|
||||||
|
local x = -a_len * math.sin(yaw)
|
||||||
|
local z = a_len * math.cos(yaw)
|
||||||
|
return {x=x, z=z}
|
||||||
|
end
|
||||||
|
|
||||||
|
vehicles.v2d_length = function(v2d)
|
||||||
|
return math.sqrt(v2d.x^2 + v2d.z^2)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find out max friction coefficient of nodes locating beneath the entity
|
||||||
|
vehicles.max_fric_coef = function(self)
|
||||||
|
local max_friction_coef = 0
|
||||||
|
local vehpos = self.object:get_pos()
|
||||||
|
for i, whl in ipairs(self.wheels) do
|
||||||
|
local pos = whl.object:get_pos()
|
||||||
|
pos = vehicles.convert_pos_to_absolute(vehpos, pos)
|
||||||
|
local undernode = minetest.get_node({x=pos.x, y=pos.y-whl.radius-0.1, z=pos.z})
|
||||||
|
local group = vehicles.get_node_groupname(undernode.name)
|
||||||
|
if max_friction_coef < ngroups_friction_coefs[group] then
|
||||||
|
max_friction_coef = ngroups_friction_coefs[group]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return max_friction_coef
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculates a modulo of a friction force of the surface under the vehicle
|
||||||
|
vehicles.surface_fric_force = function(fric_coef, mass, g)
|
||||||
|
return fric_coef*mass*-g
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Convert the relative pos coords to absolute
|
||||||
|
vehicles.convert_pos_to_absolute = function(origin, pos)
|
||||||
|
return {x=origin.x+pos.x, y=origin.y+pos.y, z=origin.z+pos.z}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert the absolute pos coords to relative (relatively to 'origin')
|
||||||
|
vehicles.convert_pos_to_relative = function(origin, pos)
|
||||||
|
return {x=pos.x-origin.x, y=pos.y-origin.y, z=pos.z-origin.z}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a node group that associated with its certain type (e.g. sand/desert sand are "sand" group, snow block/snow with grass are "snowy" group)
|
||||||
|
vehicles.get_node_groupname = function(name)
|
||||||
|
local groups = minetest.registered_nodes[name].groups
|
||||||
|
--minetest.debug("nodename:" .. name)
|
||||||
|
--minetest.debug("nodegroups:" .. dump(groups))
|
||||||
|
for group, coef in pairs(ngroups_friction_coefs) do
|
||||||
|
if groups[group] then
|
||||||
|
return group
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "default"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculates a modulo of an air resistance force (only along horizontal plane currently)
|
||||||
|
vehicles.air_resist_force = function(v_l)
|
||||||
|
return air_rcoef * math.abs(v_l)^2
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Callback Registrations
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_player_receive_fields(vehicles.on_formspec_event)
|
||||||
|
|
||||||
|
minetest.register_on_leaveplayer(function(obj, timed_out)
|
||||||
|
local is_player_sit = vehicles.is_player_sit(obj:get_luaentity())
|
||||||
|
if is_player_sit then
|
||||||
|
local parent = obj:get_attach()
|
||||||
|
local self = parent:get_luaentity()
|
||||||
|
self.seats[is_player_sit.seat_id].is_busy = nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
MOD_NAME = "adv_vehicles2" -- global macro
|
||||||
|
local modpath = minetest.get_modpath(MOD_NAME)
|
||||||
|
dofile(modpath .. "/api.lua")
|
||||||
|
|
||||||
|
--[[minetest.register_entity("cars_api:car", {
|
||||||
|
mass = 2000, -- in kg
|
||||||
|
physical = true,
|
||||||
|
visual = "cube",
|
||||||
|
on_activate = function(self, staticdata, dtime_s)
|
||||||
|
self.mass = 2000
|
||||||
|
self.step = function(self, dtime)
|
||||||
|
cars.set_gravity(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("cars_api:car", {
|
||||||
|
description = "Car",
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
if pointed_thing.type == "node" then
|
||||||
|
minetest.add_entity(pointed_thing.above, "cars_api:car")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_globalstep(function(dtime)
|
||||||
|
minetest.debug(dump(minetest.luaentities))
|
||||||
|
for i, self in pairs(minetest.luaentities) do
|
||||||
|
minetest.debug(i .. ": " .. dump(self))
|
||||||
|
if self.step then
|
||||||
|
self.step(self, dtime)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)]]
|
||||||
|
|
||||||
|
-- Test car
|
||||||
|
--[[vehicles.register_vehicle("cube_car", {
|
||||||
|
vehicle_type = "ground",
|
||||||
|
visual = "cube",
|
||||||
|
mass = 2000,
|
||||||
|
bounding_box = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||||
|
seats = {{type = "driver", pos = {0, 0.3, 0}}}
|
||||||
|
}, {
|
||||||
|
description = "Cube car"
|
||||||
|
}
|
||||||
|
)]]
|
||||||
|
|
||||||
|
vehicles.register_vehicle("bmw", {
|
||||||
|
obj = {
|
||||||
|
vehicle_type = "ground",
|
||||||
|
mass = 2000,
|
||||||
|
bounding_box = {-1.7, -0.5, -4.5, 1.6, 2.2, 2.7},
|
||||||
|
visual = "mesh",
|
||||||
|
visual_size = {x=3.5, y=3.5, z=3.5},
|
||||||
|
mesh = "bmw_fw.b3d",
|
||||||
|
textures = {"bmw.png"},
|
||||||
|
seats = {
|
||||||
|
{
|
||||||
|
["pos"] = {x=-2.5, y=-1.5, z=-3.0},
|
||||||
|
["type"] = "driver"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
["pos"] = {x=2.5, y=-1.5, z=-3.0},
|
||||||
|
["type"] = "passenger"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
["pos"] = {x=0.0, y=-1.5, z=5.5},
|
||||||
|
["type"] = "passenger"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
traction_force = 5000,
|
||||||
|
wheels = {
|
||||||
|
{
|
||||||
|
["type"] = "front",
|
||||||
|
["pos"] = {x=-3.1, y=-0.05, z=-7.55},
|
||||||
|
["radius"] = 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
["type"] = "front",
|
||||||
|
["pos"] = {x=2.9, y=-0.05, z=-7.55},
|
||||||
|
["rot"] = {x=0, y=180, z=0},
|
||||||
|
["radius"] = 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
["type"] = "rear",
|
||||||
|
["pos"] = {x=-3.1, y=-0.05, z=4.85},
|
||||||
|
["radius"] = 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
["type"] = "rear",
|
||||||
|
["pos"] = {x=2.9, y=-0.05, z=4.85},
|
||||||
|
["rot"] = {x=0, y=180, z=0},
|
||||||
|
["radius"] = 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
max_speed = 50000,
|
||||||
|
stepheight = 0.5
|
||||||
|
},
|
||||||
|
item = {
|
||||||
|
description = "BMW Spawner",
|
||||||
|
inv_image = "bmw_inv.png"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
obj = {
|
||||||
|
visual = "mesh",
|
||||||
|
visual_size = {x=1, y=1, z=1},
|
||||||
|
mesh = "bmw_wheel.b3d",
|
||||||
|
textures = {"bmw.png"}
|
||||||
|
},
|
||||||
|
item = {
|
||||||
|
description = "BMW wheel",
|
||||||
|
inventory_image = "bmw_wheel.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,13 @@
|
||||||
|
# Blender MTL File: 'bmw_fw.blend'
|
||||||
|
# Material Count: 1
|
||||||
|
|
||||||
|
newmtl bmw
|
||||||
|
Ns 0.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.800000 0.800000 0.800000
|
||||||
|
Ks 0.000000 0.000000 0.000000
|
||||||
|
Ke 0.0 0.0 0.0
|
||||||
|
Ni 1.450000
|
||||||
|
d 1.000000
|
||||||
|
illum 1
|
||||||
|
map_Kd /home/andrey/minetest-5.3.0-dev_built/mods/adv_vehicles2/textures/bmw.png
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,13 @@
|
||||||
|
# Blender MTL File: 'bmw_wheel.blend'
|
||||||
|
# Material Count: 1
|
||||||
|
|
||||||
|
newmtl bmw
|
||||||
|
Ns 0.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.800000 0.800000 0.800000
|
||||||
|
Ks 0.000000 0.000000 0.000000
|
||||||
|
Ke 0.0 0.0 0.0
|
||||||
|
Ni 1.450000
|
||||||
|
d 1.000000
|
||||||
|
illum 1
|
||||||
|
map_Kd /home/andrey/minetest-5.3.0-dev_built/mods/adv_vehicles2/textures/bmw.png
|
|
@ -0,0 +1,238 @@
|
||||||
|
# Blender v2.80 (sub 75) OBJ File: 'bmw_wheel.blend'
|
||||||
|
# www.blender.org
|
||||||
|
mtllib bmw_wheel.mtl
|
||||||
|
o BMW_wheel_Cube.001
|
||||||
|
v 0.455955 -0.000000 1.446572
|
||||||
|
v -0.806332 0.000000 1.446572
|
||||||
|
v 0.455955 0.850273 1.170301
|
||||||
|
v -0.806332 0.850274 1.170302
|
||||||
|
v 0.455955 1.375771 0.447015
|
||||||
|
v -0.806332 1.375771 0.447015
|
||||||
|
v 0.455955 1.375771 -0.447015
|
||||||
|
v -0.806332 1.375771 -0.447015
|
||||||
|
v 0.455955 0.850273 -1.170301
|
||||||
|
v -0.806332 0.850274 -1.170300
|
||||||
|
v 0.455955 -0.000000 -1.446571
|
||||||
|
v -0.806332 -0.000000 -1.446571
|
||||||
|
v 0.455955 -0.850274 -1.170301
|
||||||
|
v -0.806332 -0.850273 -1.170300
|
||||||
|
v 0.455955 -1.375772 -0.447016
|
||||||
|
v -0.806332 -1.375771 -0.447015
|
||||||
|
v 0.455955 -1.375772 0.447015
|
||||||
|
v -0.806332 -1.375771 0.447016
|
||||||
|
v 0.455954 -0.850273 1.170301
|
||||||
|
v -0.806332 -0.850273 1.170302
|
||||||
|
v 0.455955 -0.000000 1.168653
|
||||||
|
v 0.455955 0.686917 0.945460
|
||||||
|
v 0.455955 1.111455 0.361134
|
||||||
|
v 0.455955 1.111455 -0.361134
|
||||||
|
v 0.455955 0.686917 -0.945459
|
||||||
|
v 0.455955 -0.000000 -1.168653
|
||||||
|
v 0.455955 -0.686917 -0.945459
|
||||||
|
v 0.455955 -1.111455 -0.361134
|
||||||
|
v 0.455955 -1.111455 0.361134
|
||||||
|
v 0.455955 -0.686917 0.945460
|
||||||
|
v 0.368532 0.000000 1.076892
|
||||||
|
v 0.368532 0.632981 0.871225
|
||||||
|
v 0.368532 1.024185 0.332778
|
||||||
|
v 0.368532 1.024185 -0.332778
|
||||||
|
v 0.368532 0.632981 -0.871223
|
||||||
|
v 0.368532 0.000000 -1.076890
|
||||||
|
v 0.368532 -0.632980 -0.871223
|
||||||
|
v 0.368532 -1.024184 -0.332778
|
||||||
|
v 0.368532 -1.024184 0.332778
|
||||||
|
v 0.368532 -0.632980 0.871225
|
||||||
|
v -1.518813 -0.197756 -0.197756
|
||||||
|
v -1.518813 0.197756 -0.197756
|
||||||
|
v -1.518813 -0.197756 0.197756
|
||||||
|
v -1.518813 0.197756 0.197756
|
||||||
|
v -0.806332 -0.197755 -0.197756
|
||||||
|
v -0.806332 0.197756 -0.197756
|
||||||
|
v -0.806332 -0.197755 0.197756
|
||||||
|
v -0.806332 0.197756 0.197756
|
||||||
|
v 0.455955 0.000000 1.076892
|
||||||
|
v 0.455955 0.632981 0.871225
|
||||||
|
v 0.455955 1.024185 0.332778
|
||||||
|
v 0.455955 1.024185 -0.332778
|
||||||
|
v 0.455955 0.632981 -0.871223
|
||||||
|
v 0.455955 0.000000 -1.076890
|
||||||
|
v 0.455955 -0.632980 -0.871223
|
||||||
|
v 0.455955 -1.024184 -0.332778
|
||||||
|
v 0.455955 -1.024184 0.332778
|
||||||
|
v 0.455955 -0.632980 0.871225
|
||||||
|
vt 0.638389 0.748982
|
||||||
|
vt 0.638389 0.718726
|
||||||
|
vt 0.681107 0.718726
|
||||||
|
vt 0.681107 0.748982
|
||||||
|
vt 0.638389 0.688470
|
||||||
|
vt 0.681107 0.688470
|
||||||
|
vt 0.638389 0.991026
|
||||||
|
vt 0.638389 0.960771
|
||||||
|
vt 0.681107 0.960771
|
||||||
|
vt 0.681107 0.991026
|
||||||
|
vt 0.638389 0.930515
|
||||||
|
vt 0.681107 0.930515
|
||||||
|
vt 0.638389 0.900260
|
||||||
|
vt 0.681107 0.900260
|
||||||
|
vt 0.638389 0.870004
|
||||||
|
vt 0.681107 0.870004
|
||||||
|
vt 0.638389 0.839748
|
||||||
|
vt 0.681107 0.839748
|
||||||
|
vt 0.638389 0.809493
|
||||||
|
vt 0.681107 0.809493
|
||||||
|
vt 0.462868 0.753337
|
||||||
|
vt 0.479261 0.775900
|
||||||
|
vt 0.479261 0.803789
|
||||||
|
vt 0.462868 0.826352
|
||||||
|
vt 0.436344 0.834970
|
||||||
|
vt 0.409820 0.826352
|
||||||
|
vt 0.393428 0.803789
|
||||||
|
vt 0.393428 0.775900
|
||||||
|
vt 0.409820 0.753338
|
||||||
|
vt 0.436344 0.744719
|
||||||
|
vt 0.638389 0.779237
|
||||||
|
vt 0.681107 0.779237
|
||||||
|
vt 0.531421 0.742461
|
||||||
|
vt 0.531329 0.754142
|
||||||
|
vt 0.509564 0.761019
|
||||||
|
vt 0.502769 0.751514
|
||||||
|
vt 0.559923 0.751978
|
||||||
|
vt 0.552980 0.761372
|
||||||
|
vt 0.577387 0.776431
|
||||||
|
vt 0.566247 0.779947
|
||||||
|
vt 0.577143 0.806478
|
||||||
|
vt 0.566062 0.802772
|
||||||
|
vt 0.502130 0.830180
|
||||||
|
vt 0.509079 0.820777
|
||||||
|
vt 0.530730 0.828007
|
||||||
|
vt 0.530632 0.839697
|
||||||
|
vt 0.559284 0.830644
|
||||||
|
vt 0.552495 0.821130
|
||||||
|
vt 0.484666 0.805727
|
||||||
|
vt 0.495812 0.802202
|
||||||
|
vt 0.484910 0.775680
|
||||||
|
vt 0.495997 0.779376
|
||||||
|
vt 0.616807 0.714659
|
||||||
|
vt 0.616807 0.680148
|
||||||
|
vt 0.610058 0.680148
|
||||||
|
vt 0.610058 0.714659
|
||||||
|
vt 0.616807 0.956237
|
||||||
|
vt 0.616807 0.921726
|
||||||
|
vt 0.610058 0.921726
|
||||||
|
vt 0.610058 0.956237
|
||||||
|
vt 0.616807 0.852704
|
||||||
|
vt 0.616807 0.818193
|
||||||
|
vt 0.610058 0.818193
|
||||||
|
vt 0.610058 0.852704
|
||||||
|
vt 0.616807 0.749170
|
||||||
|
vt 0.610058 0.749170
|
||||||
|
vt 0.616807 0.990749
|
||||||
|
vt 0.610058 0.990749
|
||||||
|
vt 0.616807 0.887215
|
||||||
|
vt 0.610058 0.887215
|
||||||
|
vt 0.616807 0.783681
|
||||||
|
vt 0.610058 0.783681
|
||||||
|
vt 0.616807 0.645637
|
||||||
|
vt 0.610058 0.645637
|
||||||
|
vt 0.491076 0.697958
|
||||||
|
vt 0.491076 0.666712
|
||||||
|
vt 0.497469 0.668793
|
||||||
|
vt 0.497469 0.695886
|
||||||
|
vt 0.558413 0.938188
|
||||||
|
vt 0.558435 0.891375
|
||||||
|
vt 0.530937 0.853490
|
||||||
|
vt 0.486422 0.839003
|
||||||
|
vt 0.441894 0.853449
|
||||||
|
vt 0.414360 0.891308
|
||||||
|
vt 0.414338 0.938121
|
||||||
|
vt 0.441836 0.976006
|
||||||
|
vt 0.486351 0.990493
|
||||||
|
vt 0.530880 0.976048
|
||||||
|
vt 0.741486 0.858324
|
||||||
|
vt 0.708724 0.858324
|
||||||
|
vt 0.708724 0.840137
|
||||||
|
vt 0.741486 0.840137
|
||||||
|
vt 0.708724 0.803763
|
||||||
|
vt 0.741486 0.803763
|
||||||
|
vt 0.741486 0.821950
|
||||||
|
vt 0.708724 0.821950
|
||||||
|
vt 0.741486 0.785576
|
||||||
|
vt 0.708724 0.785576
|
||||||
|
vt 0.509442 0.641433
|
||||||
|
vt 0.513394 0.646876
|
||||||
|
vt 0.539159 0.631778
|
||||||
|
vt 0.539160 0.638505
|
||||||
|
vt 0.568876 0.641434
|
||||||
|
vt 0.564926 0.646877
|
||||||
|
vt 0.587242 0.666713
|
||||||
|
vt 0.580850 0.668794
|
||||||
|
vt 0.587242 0.697959
|
||||||
|
vt 0.580850 0.695886
|
||||||
|
vt 0.568877 0.723237
|
||||||
|
vt 0.564926 0.717804
|
||||||
|
vt 0.539159 0.732893
|
||||||
|
vt 0.539160 0.726176
|
||||||
|
vt 0.509442 0.723237
|
||||||
|
vt 0.513394 0.717804
|
||||||
|
vn 0.0000 0.3090 0.9511
|
||||||
|
vn 0.0000 0.8090 0.5878
|
||||||
|
vn 0.0000 1.0000 0.0000
|
||||||
|
vn -0.0000 0.8090 -0.5878
|
||||||
|
vn -0.0000 0.3090 -0.9511
|
||||||
|
vn -0.0000 -0.3090 -0.9511
|
||||||
|
vn -0.0000 -0.8090 -0.5878
|
||||||
|
vn -0.0000 -1.0000 0.0000
|
||||||
|
vn -1.0000 -0.0000 -0.0000
|
||||||
|
vn 0.0000 -0.8090 0.5878
|
||||||
|
vn 0.0000 -0.3090 0.9511
|
||||||
|
vn 1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 1.0000
|
||||||
|
vn 0.0000 0.0000 -1.0000
|
||||||
|
usemtl bmw
|
||||||
|
s off
|
||||||
|
f 1/1/1 3/2/1 4/3/1 2/4/1
|
||||||
|
f 3/2/2 5/5/2 6/6/2 4/3/2
|
||||||
|
f 5/7/3 7/8/3 8/9/3 6/10/3
|
||||||
|
f 7/8/4 9/11/4 10/12/4 8/9/4
|
||||||
|
f 9/11/5 11/13/5 12/14/5 10/12/5
|
||||||
|
f 11/13/6 13/15/6 14/16/6 12/14/6
|
||||||
|
f 13/15/7 15/17/7 16/18/7 14/16/7
|
||||||
|
f 15/17/8 17/19/8 18/20/8 16/18/8
|
||||||
|
f 4/21/9 6/22/9 8/23/9 10/24/9 12/25/9 14/26/9 16/27/9 18/28/9 20/29/9 2/30/9
|
||||||
|
f 17/19/10 19/31/10 20/32/10 18/20/10
|
||||||
|
f 19/31/11 1/1/11 2/4/11 20/32/11
|
||||||
|
f 13/33/12 27/34/12 28/35/12 15/36/12
|
||||||
|
f 11/37/12 26/38/12 27/34/12 13/33/12
|
||||||
|
f 9/39/12 25/40/12 26/38/12 11/37/12
|
||||||
|
f 7/41/12 24/42/12 25/40/12 9/39/12
|
||||||
|
f 1/43/12 21/44/12 22/45/12 3/46/12
|
||||||
|
f 5/47/12 23/48/12 24/42/12 7/41/12
|
||||||
|
f 3/46/12 22/45/12 23/48/12 5/47/12
|
||||||
|
f 19/49/12 30/50/12 21/44/12 1/43/12
|
||||||
|
f 17/51/12 29/52/12 30/50/12 19/49/12
|
||||||
|
f 15/36/12 28/35/12 29/52/12 17/51/12
|
||||||
|
f 31/53/6 32/54/6 50/55/6 49/56/6
|
||||||
|
f 34/57/10 35/58/10 53/59/10 52/60/10
|
||||||
|
f 37/61/2 38/62/2 56/63/2 55/64/2
|
||||||
|
f 40/65/5 31/53/5 49/56/5 58/66/5
|
||||||
|
f 33/67/8 34/57/8 52/60/8 51/68/8
|
||||||
|
f 36/69/1 37/61/1 55/64/1 54/70/1
|
||||||
|
f 39/71/4 40/65/4 58/66/4 57/72/4
|
||||||
|
f 32/54/7 33/73/7 51/74/7 50/55/7
|
||||||
|
f 35/58/11 36/69/11 54/70/11 53/59/11
|
||||||
|
f 25/75/12 24/76/12 52/77/12 53/78/12
|
||||||
|
f 31/79/12 40/80/12 39/81/12 38/82/12 37/83/12 36/84/12 35/85/12 34/86/12 33/87/12 32/88/12
|
||||||
|
f 38/62/3 39/71/3 57/72/3 56/63/3
|
||||||
|
f 43/89/13 47/90/13 48/91/13 44/92/13
|
||||||
|
f 45/93/14 41/94/14 42/95/14 46/96/14
|
||||||
|
f 43/97/8 41/94/8 45/93/8 47/98/8
|
||||||
|
f 48/91/3 46/96/3 42/95/3 44/92/3
|
||||||
|
f 24/76/12 23/99/12 51/100/12 52/77/12
|
||||||
|
f 23/99/12 22/101/12 50/102/12 51/100/12
|
||||||
|
f 22/101/12 21/103/12 49/104/12 50/102/12
|
||||||
|
f 21/103/12 30/105/12 58/106/12 49/104/12
|
||||||
|
f 30/105/12 29/107/12 57/108/12 58/106/12
|
||||||
|
f 29/107/12 28/109/12 56/110/12 57/108/12
|
||||||
|
f 28/109/12 27/111/12 55/112/12 56/110/12
|
||||||
|
f 27/111/12 26/113/12 54/114/12 55/112/12
|
||||||
|
f 26/113/12 25/75/12 53/78/12 54/114/12
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
Loading…
Reference in New Issue