V
tomto tútoriale sa vám zjednodušene pokúsim ukázať ako si postaviť
nakladaciu rampu s generovaním tovaru. Takto by mal vyzerať náš
cieľ.
Použijeme foto-textúru pre samotnú nakladaciu rampu ktorú rozdelíme do viac menších súborov pre lepšie mapovanie. Samozrejme je možné pracovať aj s jednou spoločnou bitmapou, ale textúrovanie je zložitejšie. Vo všeobecnosti však platí, že pokiaľ je to možné je lepšie používať menšie súbory a viac súborov. Plochy sú lepšie zobrazované, kontrastnejšie a ostrejšie pretože môžete použiť väčšie rozlíšenie. Naviac práca je prehľadnejšia. V niektorých prípadoch hlavne u animovaných objektov je lepšie ale použiť spoločné bitmapy. V našom prípade použijem samostatnú bitmapu pre prednú stenu, pre vrch a pre žlto čierny pruh. Tento žlto čierny pruh môže byť samozrejme súčasťou inej textúry ako pri čelnej stene, alebo aj samostatnou bitmapou.
![]() |
![]() |
![]() |
Čo do
textúr pri mnohej stavbe, ktorá nieje postavená presne podľa
nejakého originálu ste v istej výhode, keďže internet je plný volne
šíriteľných
textúr hlavne rôznych betónov, stien, vegetácie, dlažieb, kovov, dreva,
asfaltu
a podobne, Využíva to viac či menej skoro každý tvorca objektov vrátane
mňa. Aj
dve z týchto tu použitých textúr majú svoj pôvod na internete. Tretia
je z
reklamného média k jednému 3D grafickému programu. Je to v mnohom
jednoduchšie
keďže nieje nutné hľadanie vhodného objektu predlohy, čakania na
vhodnú
dobu pre fotenie a následných digitálnych úprav. Prácu sa vždy treba
snažiť
pokiaľ možno si čo najviac zjednodušiť. Nedoporučujem však
používať
textúry z iných objektov a aj u voľne šíriteľných textúr si treba vždy
pozrieť
prípadné licenčné podmienky uvedené niekde na stránke odkiaľ ich
sťahujete.
Niektoré textúry totiž majú obmedzenia (obvykle komerčné
použitie, alebo
uvedenie autora), ktoré treba rozhodne dodržať. Ak si v niektorom
prehliadači zadáte vyhľadať napríklad výraz "texture" a
"download" budete prekvapený koľko stránok venujúcich sa
grafike sa vám objaví. A okrem textúr na mnohej nájdete aj mnoho
cenných
informácii na tému úprav, fotenia a vôbec grafiky.
Ak už fotíte tak vedzte, že sa fotí vždy kolmo na objekt a pri vysokom
rozlíšení.
A hlavne pokiaľ možno nie počas slnka, ale keď je pod
mrakom, keď
je denné svetlo rovnomerne rozptýlené. Inak je textúra v podstate
nepoužiteľná
v pôvodnom tvare a chce to mnohé úpravy, ktoré často viac uškodia než
pomôžu..
Keď máte pripravené textúry, vytvorte si adresár povedzme
NAKLADACIA_RAMPA a do
nej ich prekopírujte. Teraz sa môžete pustiť do modelovania.
Začneme so samotnou nakladacou rampou a ako obvykle pripomínam, že
popísaný
spôsob je samozrejme iba jednou z mnoho možností ako sa dopracovať k
cieľu.
Každopádne sa snažte si zbytočne nekomplikovať život a modelujte čo
najjednoduchšie, najefektnejšie a najrýchlejšie. Vezmite na vedomie, že
aj mnou
popísané kroky je možné spraviť inak a mnohé cielene popisujem tak aby
som
ukázal inú možnosť, alebo v iných tútorialoch mnou ešte nepopísaný a
možný
postup.
Vytvorme si teda najskôr jednoduchý pôdorys buď zo štvoruholníka
ktorému po
konverzii na EDITABLE SPLYNE pridáme príslušný počet bodov, ktoré
presunieme do
finálnych polôh, alebo spájaním liniek do jedného výsledného celku.
Označíme
si vertexy, klikneme na tlačítko REFINE a pridáme do spodnej
časti ešte jeden bod, ktorý bude pre neskôr s extrude vytiahnutú rampu.
Teraz si vyberieme objekt a vytvoríme z neho klon. Ten zmenšíme tak aby vznikla medzera o šírke 0.1m ktorá neskôr bude špeciálnou plochou pre žlto čierny pás okraja nakladacej rampy. Zároveň z tohoto klonu odstránime v predlohe pridaný posledný vertex.
Ako
poznámku k množstvu možností ako prísť k rovnakému výsledku tu
chcem spomenúť, že napríklad k tomuto výsledku je možné prísť aj z
jednej čiary
bez klonovania, keď jej jednoducho dáme šírku 0.1m - hodnote vedľa
tlačítka
OUTLINE. Tak alebo tak z vnútorného okraja vytvoríme ešte jeden klon
ktorý bude
tvoriť vrch nakladacej rampy.
Znovu si označíme vonkajší obvod a pripojíme s ATACH k nemu vnútorný
obvod.
Označíme ho ako povedzme "obvod". Vyberieme čiaru a pravou myšou
SUB-OBJECT S - TOP LEVEL.
Následne v menu MODFIERS - MESH EDITING - EXTRUDE pôdorys vytiahneme do výšky 1.4m.
Tak
dostaneme obvod z ktorého po prevode na EDITABLE MESH a výbere
polygónov odstránime všetky vnútorné a spodné plochy.
Teraz
si vyberieme vyklonovaný vrch rampy a rovnakým postupom ho s
EXTRUDE vytiahneme do výšky 0.0m Tak dostaneme v podstate plane plochu
s
nulovou výškou, ktorú v ose Z zdvihneme ako celok do výšky 1.4m,
pripojíme k
obvodu a vo vertexoch spojíme do jedného celku.
Ako
ďalšie si z druhej strany označíme samostatný polygón na zvislej
stene a pomocou EXTRUDE do vzdialeností 10m vytiahneme túto plochu
smerom von.
Odstránime
spodnú plochu a čelnú plochu vytiahnutého nábehu, ktorá je úž teraz
nepotrebná.
Následne vyberieme polygóny a odstránime z bočných strán nábehu vždy po
jednom
trojuholníku. Nakoniec vyberieme vertexy, označíme krajné vonkajšie
horné
vertexy nábehu a os Z im nastavíme na hodnotu 0.0m. Zároveň ich zvaríme
so
spodnými. Tým máme nábehovú rampu hotovú.
Ostáva
nám spraviť schody na opačnej strane buď ako množinu, alebo
jednoducho opäť z kriviek bočného pohľadu a ich vytiahnutím.
Odstránime
spodnú
a vnútornú plochu a schody pripojíme k nakladacej rampe. Samotná stavba
je
hotová a je čas ju otextúrovať. Načítame teda všetky bitmapy. Teraz si
zvolíme polygóny
a označíme bočné vonkajšie plochy, ktorým pomocou APPLY v materiál
editore
pridelíme textúru pre bok so žlto čiernym pásom. Tú istú aj
schodom.
Potom vyberte vrch nakladacej rampy a prideľte jej textúru
horného
asfaltu . A nakoniec vyberte tenký pás a prideľte mu textúru žlto
čierneho
pruhu, ak je v samostatnej bitmape, alebo tiež čelnú stenu s pasom z
ktorej pri mapovaní vyberieme iba tento pruh.. Nakoniec pomocou
MODIFIERS - UV COORDINATES - UVW MAP ako BOX
namapujete
spoločne textúru. Pomocou MODIFIERS - UV COORDINATES - UNVRAP UVW
postupne
dolaďte
všetky textúry a plochy.
Hlavne
pri žltočiernom páse dbajte na presné sedenie vzorov. Dôležité je aby
ste krajné body mali rovnako posunuté ako vertexy plôch kde sa v rohoch
plochy spájajú. Ak použijete UVW MAP spraví to za vás 3dmax (gmax) a vy
to musíte iba doladiť ak naťahujete oblasť mapovania. Zachovaný musí
byť hlavne uhol vo vzťahu k dĺžke. Používajte na úpravu preto nie ručné
presúvanie bodov, ale hľavne funciu SCALE (tretia ikonka v okne
edit UVWs) v príslušnej oreintácii a vo vzťahu k celu.
Takto
máme
samotnú nakladaciu rampu hotovú a pre kontrolu ju vyexportujeme do TRS
pričom
definovaná bude zatiaľ ako jednoduchý scenery objekt len za použitia
základných
tagov v config.txt.
Ako
ďalšie musíme
definovať pomocné body pre koľaj. Vytvoríme si pomocné plane na dĺžku
rozdelené
na dve plochy a o šírke 2m a dĺžke budúcej koľaje. Pridelíme mu
pracovnú
textúru pražcov s koľajnicami pre lepšie znázornenie. Stredová čiara
rozdeľujúca plane na dve časti nám bude dobre slúžiť ako vodiaca čiara
pre
umiestnenie pomocných bodov koľajnice. Zvolíme si teda v editačnej
oblasti
HELPERS
- POINT
Body
"a"
a "e" sú k pripojeniu externej koľaje a tri stredné na definovanie
triggra nakladania a vykladania. Dôležitá je orientácia osí. Na
krajných bodov
musí os Y smerovať vždy smerom von z koľaje.
To isté spravíme aj na
opačnej
strane kde body pomenujeme ako a.track1a, a.track1b, a.track1c,
a.track1d a
a.track1e. Body sú vo výške (os Z) na hodneote 0.0
Objekt môžeme opäť vyexportovať pre kontrolu správneho
umiestnenia koľají a prípadne body upraviť. Ak sú koľaje korektné,
zmažeme
pomocné koľaje a vytvoríme si nové pomocné plane o rozmeroch hornej
plochy a
rozdelené podľa počtu krabíc tovaru ktoré sa nám budú generovať na
rampe. Ich
rozmer pôdorysu záleží od typu tovaru. V našom prípade počítajme 1.2 x
1.2m.
Do krížov
potom umiestnime pomocné body ktoré označíme ako a.goods_in01 až
a.goods_in25 pre nakládku a goods_out01 až a.goods_out25 pre vykládku
(podľa
počtu bodov). To sú miesta kde sa v hre bude generovať tovar.
kuid
<kuid:XXXXXX:XXXXXX> region TUTORIAL type "Priemysel" kind "industry" category-class "BIN" kuid-table { gen_goods <kuid:-3:10013> } light 1 rotstep 0.3 script "goodsshed_gengoods" class "goodsshed_gengoods" icon-texture "ico_rampa.bmp" mesh-table { default { mesh "rampa.im" auto-create 1 effects { arrow0 { kind "attachment" att "a.track0a" default-mesh <kuid:-3:10092> surveyor-only 1 } arrow1 { kind "attachment" att "a.track0e" default-mesh <kuid:-3:10092> surveyor-only 1 } arrow2 { kind "attachment" att "a.track1a" default-mesh <kuid:-3:10092> surveyor-only 1 } arrow3 { kind "attachment" att "a.track1e" default-mesh <kuid:-3:10092> surveyor-only 1 } } } } attached-track { out_track { track <kuid:-1:15> vertices { 0 "a.track0a" 1 "a.track0b" 2 "a.track0c" 3 "a.track0d" 4 "a.track0e" } } in_track { track <kuid:-1:15> vertices { 0 "a.track1a" 1 "a.track1b" 2 "a.track1c" 3 "a.track1d" 4 "a.track1e" } } } queues { goods_in_q { size 25 initial-count 8 product-kuid <kuid:-3:10013> attachment-points { 0 "a.goods_in01" 1 "a.goods_in02" 2 "a.goods_in03" 3 "a.goods_in04" 4 "a.goods_in05" 5 "a.goods_in06" 6 "a.goods_in07" 7 "a.goods_in08" 8 "a.goods_in09" 9 "a.goods_in10" 10 "a.goods_in11" 11 "a.goods_in12" 12 "a.goods_in13" 13 "a.goods_in14" 14 "a.goods_in15" 15 "a.goods_in16" 16 "a.goods_in17" 17 "a.goods_in18" 18 "a.goods_in19" 19 "a.goods_in20" 20 "a.goods_in21" 21 "a.goods_in22" 22 "a.goods_in23" 23 "a.goods_in24" 24 "a.goods_in25" } } goods_out_q { size 25 initial-count 12 product-kuid <kuid:-3:10013> attachment-points { 0 "a.goods_out01" 1 "a.goods_out02" 2 "a.goods_out03" 3 "a.goods_out04" 4 "a.goods_out05" 5 "a.goods_out06" 6 "a.goods_out07" 7 "a.goods_out08" 8 "a.goods_out09" 9 "a.goods_out10" 10 "a.goods_out11" 11 "a.goods_out12" 12 "a.goods_out13" 13 "a.goods_out14" 14 "a.goods_out15" 15 "a.goods_out16" 16 "a.goods_out17" 17 "a.goods_out18" 18 "a.goods_out19" 19 "a.goods_out20" 20 "a.goods_out21" 21 "a.goods_out22" 22 "a.goods_out23" 23 "a.goods_out24" 24 "a.goods_out25" } } } processes { goodsshed_consumer { start-enabled 1 duration 30 inputs { 0 { amount 3 queue "goods_in_q" } } outputs { 0 { amount 3 queue "goods_out_q" } } } } attached-trigger { goods_out_t0 { att "a.track0b" radius 5 } goods_out_t1 { att "a.track0c" radius 5 } goods_out_t2 { att "a.track0d" radius 5 } goods_in_t0 { att "a.track1b" radius 5 } goods_in_t1 { att "a.track1c" radius 5 } goods_in_t2 { att "a.track1d" radius 5 } } icon0 <kuid:-3:10164> asset-filename "rampa" |
include "GenericIndustry.gs" class goodsshed_gengoods isclass GenericIndustry { ProductQueue goodsOutQueue, goodsInQueue; bool scriptletEnabled = true; int lumberWBRemain = 0; thread void ViewDetails(void) { if (!info) { info = Constructors.NewBrowser(); info.LoadHTMLString(HTMLWindow.GetCompleteIndustryViewDetailsHTMLCode(me, scriptletEnabled)); info.SetWindowRect(100, 80, 500, 545); } } bool TriggerSupportsStoppedLoad(Vehicle vehicle, string triggerName) { if (itc.IsTrainCommand(vehicle.GetMyTrain(), Industry.LOAD_COMMAND)) { bool vehicleToTrain = vehicle.GetFacingRelativeToTrain(); int direction = vehicle.GetRelationToTrack(me, "out_track"); if (!vehicleToTrain) direction = -direction; if (direction == Vehicle.DIRECTION_BACKWARD and triggerName == "goods_out_t0") return true; if (direction == Vehicle.DIRECTION_FORWARD and triggerName == "goods_out_t2") return true; if (triggerName == "goods_out_t0" or triggerName == "goods_out_t1" or triggerName == "goods_out_t2") if (vehicle.GetMyTrain().IsStopped()) return true; } if (itc.IsTrainCommand(vehicle.GetMyTrain(), Industry.UNLOAD_COMMAND)) { bool vehicleToTrain = vehicle.GetFacingRelativeToTrain(); int direction = vehicle.GetRelationToTrack(me, "in_track"); if (!vehicleToTrain) direction = -direction; if (direction == Vehicle.DIRECTION_BACKWARD and triggerName == "goods_in_t2") return true; if (direction == Vehicle.DIRECTION_FORWARD and triggerName == "goods_in_t0") return true; if (triggerName == "goods_in_t0" or triggerName == "goods_in_t1" or triggerName == "goods_in_t2") if (vehicle.GetMyTrain().IsStopped()) return true; } return false; } void PerformStoppedLoad(Vehicle vehicle, string triggerName) { if (triggerName == "goods_out_t0" or triggerName == "goods_out_t1" or triggerName == "goods_out_t2") { int available = goodsOutQueue.GetQueueCount(); LoadingReport report = CreateLoadingReport(goodsOutQueue, available); vehicle.LoadProduct(report); } if (triggerName == "goods_in_t0" or triggerName == "goods_in_t1" or triggerName == "goods_in_t2") { int available = goodsInQueue.GetQueueSpace(); LoadingReport report = CreateUnloadingReport(goodsInQueue, available); vehicle.UnloadProduct(report); } } thread void GoodsShedMain(void) { Message msg; wait() { Vehicle vehicle; string triggerName; on "Scriptlet-Enabled", "1": { if (!scriptletEnabled) { scriptletEnabled = true; SetProcessEnabled("goodsshed_consumer", true); } continue; } on "Scriptlet-Enabled", "0": { if (scriptletEnabled) { scriptletEnabled = false; SetProcessEnabled("goodsshed_consumer", false); } continue; } } } public void Init(void) { inherited(); goodsOutQueue = GetQueue("goods_out_q"); goodsInQueue = GetQueue("goods_in_q"); AddAssetToIndustryProductInfo("gen_goods", "goods_in_q", "goodsshed_consumer", true); AddAssetToIndustryProductInfo("gen_goods", "goods_out_q", "goodsshed_consumer", false); GoodsShedMain(); } public Requirement[] GetRequirements(void) { Requirement[] ret = new Requirement[0]; if (goodsInQueue.GetQueueCount() < 4 or lumberWBRemain > 0) { ResourceRequirement req = new ResourceRequirement(); req.resource = goodsInQueue.GetProductFilter().GetProducts()[0]; req.amount = 10; if (goodsInQueue.GetQueueCount() < 2 and lumberWBRemain == 0) lumberWBRemain = 10; req.dst = me; req.dstQueue = goodsInQueue; ret[ret.size()] = req; } return ret; } public void AppendDriverDestinations(string[] destNames, string[] destTracks) { destNames[destNames.size()] = "General Goods Pickup"; destTracks[destTracks.size()] = "out_track"; destNames[destNames.size()] = "General Goods Drop off"; destTracks[destTracks.size()] = "in_track"; } }; |
A
preto aj tu sa
nebudem opakovať. Snáď iba znova pripomeniem, že sa jedná o
programovací jazyk
a preto je dobré si o ňom naštudovať čo najviac.
Ako ďalšie aby naša prekladacia rampa bola kompletná si ešte vytvorme
vlastný
tovar, ktorým bude jednoduchá paleta reziva.
Ako textúru som opäť použil volne dostupnú textúru z jednej
internetovej stránky, pričom čelnú stranu som ručne vytvoril z časti
bočnej ako novú textúru.
![]() |
![]() |
bočno-vrchnú | a čelnú |
kuid
<kuid:XXXXXX:XXXXXX> instance-type "resource" kind "product" product-category <kuid:-3:10042> category-class "IC" icon-texture "ico_tovar.bmp" mass 500 trainz-build 2 mesh-table { default { mesh "tovar.im" } } allows-mixing 0 asset-filename "tovar" username "Paleta s drevom" |
A rovnako ikonu 64x64 pixelov ico_rampa.bmp tiež definovanú v config.txt pre našu rampu pre TRS a zobrazovanú v cestovnom poriadku, ktorú nahráme do adresáru rampy.
Teraz vymeníme kuid tovaru v configu prekladacej rampy (pôvodne kuid:-3:10013) za kuid nášho tovaru a výsledok je vidieť na nasledovných obrázkoch. Samozrejme je možné našu rampu ešte rozšíriť o nočný mód, animovaný žeriav a ďalšie detaily. Ale to už je vecou vašej fantázie.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |