Vitaro

гайд
Гайд по визуальным грузам

7 сообщений в этой теме

0. Вступление

В игре существует 4 способа прописать груз в транспорт:
1. Невидимый груз
2. Груз с подъемом (Анимация насыпного груза)
3. Анимация груза заполнения
4. Анимация груза с заменой
Я распишу на примерах каждый тип,  а также отдельным заголовком распишу как его правильно размещать в транспорте. Также отдельно распишу как правильно писать матконфиги.
Для точного подсчета id и проверки id по лодам, крайне рекомендую скачать вам это программку - TF-ID_Viewer.zip (не могу найти оригинальную ссылку)

1. Невидимый груз

На данный момент это самый простой способ прописать груз в транспорт. Вы просто указываете тип груза и его объем.
Хочу напомнить, что указанный вами объем будет делиться игрой на 4, т.е. вы укажите 72 единицы в файлах, то в игре увидите 18 (72/4)

Прописывается очень просто:

capacities = {
	{ type = "LOGS", capacity = 80 },
	{ type = "LIVESTOCK", capacity = 80 },
	...
}

 

2. Груз с подъемом

Начиная с этого типа груза и последующих, вам уже надо прописывать msh для грузов в теле самого транспорта, а затем проводить их точный подсчет id.
Пример:

 

{
	id = "industry/cargo/truck/studebaker_us6_freight_content.msh",
	transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
	type = "MESH",
},
	-- interior
{
	id = "vehicle/truck/studebaker_us6/lod_0_interior.msh",
	transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
	type = "MESH",
},

В данном примере первым идет визуальный груз, затем прописывается салон. Отсчет id для msh в теле файла mdl начинается с единицы, т.е. 1, 2, 3 и т.д.
Порядок id для всех лодов должен быть абсолютно одинаковым!! Это очень важно, иначе игра грозит вылететь на рабочий стол при выпуске транспорта из депо.
Зачастую если у меня идут в начале фары, салон, и другие объекты до самих грузов, и они не планируются использоваться в других лодах, то я просто ставлю заглушку в виде msh от камня и уменьшаю его до микроскопических размеров. Чтобы id для грузов совпадал на всех лодах.

И так код самих насыпных грузов:

 

capacities = {
	{ type = "COAL", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 7, maxHeight = 0.45 } } },
	{ type = "IRON_ORE", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 8, maxHeight = 0.45 } } },
	{ type = "STONE", capacity = 52 , loadIndicator = { type = "LEVEL", params = { id = 9, maxHeight = 0.45 } } },
	{ type = "SLAG", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 10, maxHeight = 0.45 } } },
	{ type = "GRAIN", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 11, maxHeight = 0.45 } } },
	{ type = "WASTE", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 12, maxHeight = 0.45 } } },
	{ type = "MINERALS", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 13, maxHeight = 0.45 } } },
	{ type = "LIMESTONE", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 14, maxHeight = 0.45 } } },
	{ type = "FILINGS", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 15, maxHeight = 0.45 } } },
	{ type = "BAUXITE", capacity = 52, loadIndicator = { type = "LEVEL", params = { id = 16, maxHeight = 0.45 } } },
},


Нас тут по большей части интересует правильность указания id и высота подъема = 0.45. При полной загрузке, ваш груз со дна, поднимется на 0.45 метра.
Для каждого груза можно указывать свою персональную высоту подъема.

3. Анимация груза заполнением

Этой анимацией применяется точно такой же принцип подсчета id как и для предыдущего, но разница лишь в том, что количество msh увеличивается ровно на столько, сколько вы хотите увидеть груза на своем транспорте.
К примеру 3 коробки с одеждой, значит вам надо под каждую коробку писать 3 msh с их точными расположением.

 

-- Clothes 54, 55, 56
{
	id = "asset/industry/lod_0_wooden_box_02.msh",
	transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.784, 0, 0.6419, 1 },
	type = "MESH",
}, 
{
	id = "asset/industry/lod_0_wooden_box_02.msh",
	transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1.8152, 0, 0.6419, 1 },
	type = "MESH",
}, 
{
	id = "asset/industry/lod_0_wooden_box_02.msh",
	transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.784, 0, 1.5456, 1 },
	type = "MESH",
},

Для себя я комментирую номера id и название груза, это в последствии очень сильно упростит вам поиск ошибок.
Ну и для груза пишем:

 

capacities = {
	...
	{ type = "CHEMICAL", capacity = 20, loadIndicators = { { type = "DISCRETE", params = { items = { 53 } } } } },
	{ type = "CLOTHES", capacity = 20, loadIndicators = { { type = "DISCRETE", params = { items = { 54, 55, 56 } } } } },
	{ type = "MINERALS", capacity = 20, loadIndicators = { { type = "DISCRETE", params = { items = { 57 } } } } },
	...
}

msh для груза вы можете указывать 1 или более.
Также вы можете комбинировать различные типы загрузки (подъем/подмена/заполнение), главное чтобы грузы четко соответствовали своим id.

 

4. Анимация груза с подменой.

Пожалуй самая сложная анимация, но и дающая наиболее интересные результаты.
Здесь применяется такойже принцип как и у анимации заполнения - для каждой коробки надо писать свои msh. Но вы к примеру захотите при полной загрузке рисовать не коробки, а контейнер. Да не беда, также поверх коробок позиционируете msh для контейнера, остальное уже пишется в конфиге грузов.

 

 


	-- Construction materials (id 56-63)
		{
			id = "industry/cargo/lod_0_cargo_construction_goods.msh",
			transf = transf.rotZYXTransl(transf.degToRad(90 * math.random(1,4), 0, 0), vec3.new(0 + xx, 0 - y, 0)),
			type = "MESH"
		},
		{
			id = "industry/cargo/lod_0_cargo_construction_goods.msh",
			transf = transf.rotZYXTransl(transf.degToRad(90 * math.random(1,4), 0, 0), vec3.new(0 + xx, 0 + y, 0)),
			type = "MESH"
		},
		{
			id = "industry/cargo/lod_0_cargo_construction_goods.msh",
			transf = transf.rotZYXTransl(transf.degToRad(90 * math.random(1,4), 0, 0), vec3.new(0 + x, 0 - y, 0)),
			type = "MESH"
		},
		{
			id = "industry/cargo/lod_0_cargo_construction_goods.msh",
			transf = transf.rotZYXTransl(transf.degToRad(90 * math.random(1,4), 0, 0), vec3.new(0 + x, 0 + y, 0)),
			type = "MESH"
		},
		{
			id = "industry/cargo/lod_0_cargo_construction_goods.msh",
			transf = transf.rotZYXTransl(transf.degToRad(90 * math.random(1,4), 0, 0), vec3.new(0 - x, 0 - y, 0)),
			type = "MESH"
		},
		{
			id = "industry/cargo/lod_0_cargo_construction_goods.msh",
			transf = transf.rotZYXTransl(transf.degToRad(90 * math.random(1,4), 0, 0), vec3.new(0 - x, 0 + y, 0)),
			type = "MESH"
		},
		{
			id = "industry/cargo/lod_0_cargo_construction_goods.msh",
			transf = transf.rotZYXTransl(transf.degToRad(90 * math.random(1,4), 0, 0), vec3.new(0 - xx, 0 - y, 0)),
			type = "MESH"
		},
		{
			id = "industry/cargo/lod_0_cargo_construction_goods_large.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(1.14, 1.03, 1), transf.degToRad(0, 0, 0), vec3.new(0.2, -0.1, 0)),
			type = "MESH"
		},

В конфиге мы уже начинаем крутить эти id под уровни загрузки.

 

capacities = {
	... ,
	{ type = "CONSTRUCTION_MATERIALS", capacity = cap, loadIndicators = {
		{ type = "DISCRETE", params = { levels = {
			{ 56, 57, 58, 59, 60, 61, 62, 63 },
			{ 57, 58, 59, 60, 61, 62, 63  },
			{ 58, 59, 60, 61, 62, 63 },
			{ 59, 60, 61, 62, 63 },
			{ 60, 61, 62, 63 },
			{ 61, 62, 63 },
			{ 62, 63 },
			{ 63 },
			{ 56, 57, 58, 59, 60, 62, 62 }
		} } },
	} },
	... ,
}

И так поехали по строкам, так будет проще понять что к чему:

первая строка:
{ 56, 57, 58, 59, 60, 61, 62, 63 },
Пустая загрузка, но выбран тип в транспорте строительные материалы. т.е. игра не отображает эти msh;

вторая строка:
{ 57, 58, 59, 60, 61, 62, 63 },
первый уровень загрузки. Мы рисуем только msh c id 56;

третья строка:
{ 58, 59, 60, 61, 62, 63 },
второй уровень загрузки. Мы рисуем только msh  с id 56 и 57;

И так далее до самой последней строки. тут начинается самое интересное.
{ 56, 57, 58, 59, 60, 62, 62 }
Здесь мы перестали рисовать мелкие грузы, и сделали только один большой под id 63. Т.е. при полной загрузке у вас отображается только один большой груз.

Важно понимать, что первая строка, грубо говоря, дает понять игре, что вы будете работать именно с данными id.
Последняя строка дает понять, что это полная загрузка. Количество строк не ограниченно. В одном сделаном мной транспорте их было более 100.
Также вы можете осуществлять подмену на разных этапах погрузкеи. Тут уж как ваша фантазия сработает.

 

5. Позиционирование груза.

Для того, чтобы ваш груз спозиционировать на вашем транспорте, можно использовать два способа:

1. использовать стандартную матрицу

{
	id = "vehicle/truck/tractor/Scep_gkb817_lod1.grp",
	transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -6.35, 0, 0, 1 },
	type = "GROUP"
}

Где последние 4 цифры отвечают за позиционирование по координатной сетке X, Y, Z.  Но самое интересное, что последнюю цифру трогать нельзя, она должна быть всегда 1.
В данном примере группа подвинута по оси х назад на 6.35 метра.

2. Использовать функции размещения. Их всего три. Для этого в самом начале файла вам надо прописать строки:

local vec3 = require "vec3"
local transf = require "transf"

Сами функции:


Простое позиционирование по осям X, Y, Z

 

transf = transf.transl(vec3.new(20, -10 , 0))

Груз сдвинут на 20 метров по оси X и на -10 метров по оси Y

Позиционирование по осям X, Y, Z и вращение по осям X, Y, Z:

 

transf = transf.rotZYXTransl(transf.degToRad(90, 0, 0), vec3.new(0, 0, 0)),

Груз не сдвинут по осям, однако повернут на 90 градусов против часовой стрелки по оси X

Позиционирование, вращение и масштаб по осям X, Y, Z

 

transf = transf.scaleRotZYXTransl(vec3.new(1.1, 1.1, 1.1), transf.degToRad(180, 0, 0), vec3.new(0.1, 0, 0))

Мы увеличили груз по всем осям в 1.1 раза, повернули его на 180 градусов вокруг оси X и сдвинули вперед на 0.1 метра.

Прописывается все это достаточно легко:

{
		id = "industry/cargo/paper_cargo_small_lod_0.msh",
		transf = transf.scaleRotZYXTransl(vec3.new(0.7,0.7,0.7),transf.degToRad(180, 0, 0), vec3.new(-1.8, 0, 0.6419)),
		type = "MESH",
},

Просто подставляете удобную для вас функцию.

 

6. Трансформация груза.

Трансформация/масштабирование груза происходит также двумя путями. Один выше я уже упомянул в последней функции. Это самый просто способ.
Второй дает вам больше свободы, но он достаточно сложен для восприятия.
Вот его стандартный вид. Обращаем внимание на единички. Это исходный (базовый) вариант

{
	id = "industry/cargo/cargo_aluminium_small_lod_0.msh",
	transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.8, 0, 0.6419, 1 },
	type = "MESH",
},

Разобьем для удобства по строкам
 

{
	id = "industry/cargo/cargo_aluminium_small_lod_0.msh",
	transf = {
		1, 0, 0, 0,			--строка странсформации по оси X
		0, 1, 0, 0,			--строка странсформации по оси Y
		0, 0, 1, 0,			--строка странсформации по оси Z
		-0.8, 0, 0.6419, 1		--положение объекта по осям X, Y, Z
	},
	type = "MESH",
},

Нас интересуют только первые три цифры в каждой строке. Каждая цифра соответствуют свой оси, т.е. в первой строке цифра один в первой позиции говорит, что размер объекта по оси X будет равен 1, но по другим осям ноль. Вторая строка это ось Y, и там цифра один во втором положении будет говорить, что по оси Y объект равен 1. дальше по аналогии.
Кстати никто не мешает вам писать цифру со знаком минус ;) Это дает отражение объекта.

Вот наглядный пример того, как я рисовал повернутые колеса для трактора.

 

-- Передние колеса
{
	id = "vehicle/truck/tractor/tractor_t28_wheels_front_lod_0.msh",
	transf = { 0.9, 0.4, 0, 0, -0.4, 0.9, 0, 0, 0, 0, 1, 0, 1.11623, 0.59480, 0.43169, 1 },
	type = "MESH"
},
{
	id = "vehicle/truck/tractor/tractor_t28_wheels_front_lod_0.msh",
	transf = { -0.9, -0.4, 0, 0, 0.4, -0.9, 0, 0, 0, 0, 1, 0, 1.11623, -0.59480, 0.43169, 1 },
	type = "MESH"
}


7. Matconfig и с чем его матерят

Для чего вообще они нужны эти матконфиги? Если вы не хотите копировать по 100 раз один и тот же объект, а вам нужно просто менять для него текстуру, то это ваш вариант. На самом деле тут все очень легко если разобраться, куда больше вы будете еб...мучаться с трансформациями и позиционированием.

Исток матконфигов кроется в самих файлах msh. Там прописываются сразу несколько разных фалов mtl для одного объекта.
Вот пример:

 

 


function data()
return {
	animations = { },
	matConfigs = {
		{ 0 },
		{ 1 },
		{ 2 },
		{ 3 },
		{ 4 },
	},
	subMeshes = {
		{
			indices = {
				position = { count = 1584, offset = 0 },
				normal = { count = 1584, offset = 1584 },
				uv0 = { count = 1584, offset = 3168 },
				tangent = { count = 1584, offset = 4752 }
			},
			materials = { 
				"industry/cargo/minerals.mtl",
				"industry/cargo/limestone.mtl",
				"industry/cargo/filings.mtl",
				"industry/cargo/garbage.mtl",
				"industry/cargo/bauxites.mtl",
			}
		}
	},
	vertexAttr = {
		position = { count = 4752, numComp = 3, offset = 6336 },
		normal = { count = 4752, numComp = 3, offset = 11088 },
		uv0 = { count = 3168, numComp = 2, offset = 15840 },
		tangent = { count = 6336, numComp = 4, offset = 19008 }
	}
}
end

Каждый пункт в msh соответствует своему файлу mtl. В дальнейшем вы будете вызывать файл msh с порядковым номером matconfig. Выглядит это так - вы прописываете один и тот же msh несколько раз подряд. Столько, сколько вам нужно грузов. Считаете их id, затем прописываете соответствующий matConfigs для msh по его порядковому id.
ID matConfigs должно соответсвовать ID от msh !!! Отсчет начинается с нуля - 0, 1, 2, 3 ....

 

	-- Coal (id 19)
		{
			id = "vehicle/truck/mack_ac/lod_0_freight_cargo_load.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(1.225,1.11,0.4),transf.degToRad(0.0, 0.0, 0.0), vec3.new(1.44, 0, -0.41)),
			type = "MESH"
		},
	-- Iron (id 20)
		{
			id = "vehicle/truck/mack_ac/lod_0_freight_cargo_load.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(1.225,1.11,0.4),transf.degToRad(0.0, 0.0, 0.0), vec3.new(1.44, 0, -0.41)),
			type = "MESH"
		},
	-- Stone (id 21)
		{
			id = "vehicle/truck/mack_ac/lod_0_freight_cargo_load.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(1.225,1.11,0.4),transf.degToRad(0.0, 0.0, 0.0), vec3.new(1.44, 0, -0.41)),
			type = "MESH"
		},
	-- Grain (id 22)
		{
			id = "vehicle/truck/mack_ac/lod_0_freight_cargo_load.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(1.225,1.11,0.4),transf.degToRad(0.0, 0.0, 0.0), vec3.new(1.44, 0, -0.41)),
			type = "MESH"
		},
	-- Slag (id 23)
		{
			id = "vehicle/truck/mack_ac/lod_0_freight_cargo_load.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(1.225,1.11,0.4),transf.degToRad(0.0, 0.0, 0.0), vec3.new(1.44, 0, -0.49)),
			type = "MESH"
		},
	-- Minerals (id 24)
		{
			id = "industry/cargo/open/cargo_bulk_big_lod_0.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(0.93,0.734,0.4),transf.degToRad(90.0, 0.0, 0.0), vec3.new(-0.09, 0, -0.565)),
			type = "MESH"
		},
	-- Limestone (id 25)
		{
			id = "industry/cargo/open/cargo_bulk_big_lod_0.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(0.93,0.734,0.4),transf.degToRad(90.0, 0.0, 0.0), vec3.new(-0.09, 0, -0.565)),
			type = "MESH"
		},
	-- Filings (id 26)
		{
			id = "industry/cargo/open/cargo_bulk_big_lod_0.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(0.93,0.734,0.4),transf.degToRad(90.0, 0.0, 0.0), vec3.new(-0.09, 0, -0.565)),
			type = "MESH"
		},
	-- Waste (id 27)
		{
			id = "industry/cargo/open/cargo_bulk_big_lod_0.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(0.93,0.734,0.4),transf.degToRad(90.0, 0.0, 0.0), vec3.new(-0.09, 0, -0.565)),
			type = "MESH"
		},
	-- Waste (id 28)
		{
			id = "industry/cargo/open/cargo_bulk_big_lod_0.msh",
			transf = transf.scaleRotZYXTransl(vec3.new(0.93,0.734,0.4),transf.degToRad(90.0, 0.0, 0.0), vec3.new(-0.09, 0, -0.565)),
			type = "MESH"
		},
	},
	events = { },
	matConfigs = {
		{
  		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0,
		0, 1, 2, 3, 4,
		0, 1, 2, 3, 4
		}
	}


В итоге у вас вполне спокойно может выйти вот такая штука:

 

matConfigs = {
	{
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
		0, 0, 0, 0, 0, 0, 0,
		0, 1, 2, 3, 4,
		0, 0,
		0, 0, 0, 0, 0, 0, 0, 0,
		0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  -- milk
		0, 0,
		0, 0,
		1, 2,
		0, 0,
		3,
		0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, -- Alcohol
		4,						-- Bauxites
		0, 0, 0,				-- Aluminium
		--
		0, 0 -- lights
	}, 
},


Итог

Система визуализации в игре достаточно гибкая, вы можете сделать практически все что угодно. Есть только одно ограничение, которое меня очень сильно огорчает - нельзя добавлять удерживающие стойки для пустых вагонов при выбранном грузе. К примеру для платформ. А так вы можете сделать визуализацию, вплоть до того, что будет меняться текстура цистерны в зависимости от того, какую жидкость она перевозит.

4

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Если ты имеешь ввиду (про стойки), что, вот она, голая платформа, и мы выбираем тип груза - брёвна. При покупке вагона, и выхода его из депо, хотелось бы, чтобы он вышел со стойками, но, разумеется, без брёвен (которые грузятся впоследствии)... а когда брёвна разгружаются - стойки остаются... верно? А при смене у вагона типа груза (например, на ящики) стойки удаляются. Я правильно понимаю? Если правильно - таки легко так сделать. Я делал такую платформу ещё для Трэйн Фивера. Единственное. чего я не помню - так это то, что стойки сразу появляются, или для этого нужна первая загрузка. Похожая анимация у меня была на платформах с танками Т-34, и Тигр (тут, на сайте, где-то есть скрины) . В составах с танками появлялись часовые (у русских - братуха с автоматом... у немцев - чел с овчаркой)... так, вот... часовые появлялись лишь у кормы самого последнего загружаемого танка (не у каждого танка). Танки грузились по одному на платформу, разумеется.

Если тебе это нужно, то я могу покопаться, и вспомнить - что там к чему.

Изменено пользователем olegmontana
2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@olegmontana можешь поискать. Актуальность конечно уже отпала, но информация лишней никогда не будет.

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А груэы только отдельными мешами прописываются ? А группами можно ?

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Можно запихать в группу, но учтите, что сложнее будет считать ID

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Удалено:D

 

Изменено пользователем DeD_Shurik
0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Vitaro  , огромное спасибо за гайд ! С пятой попытки прочтения и второй пива :rolleyes:  понял смысл . Не всё пока , но заработало . 

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу