Blockland Custom .blb Brick Making Tutorial
For Blender 2.49b.
Note: All of those are most likely possible in later versions of Blender as well, however, the methods of doing things is sightly different. Someone familiar with Blender should however not have a problem with the way things work.
Table of Contents:
-Creating the 1x1F Brick Asset
-Using COL Correctly; resizing COL and BOUNDS
This tutorial does not cover basic Blender functions. The tutorial works on the premise that you already acknowledge how to use at least basic blender functions. The being, extruding, rotating etc. The tutorial will call to those functions, but will not teach you how to model directly.
W (Edit mode) - Specials
S - Scale
R - Rotate
E (Edit mode) - Extrude
Shift + S - Snap
U (Edit mode) - UV Calculation
P (Edit mode) - Separate
N (Hovering mouse over 3D view) - Open transform propreties
Shift + D - Duplicate
I highly recomend downloading the 1x1F brick in order to have a base for your work. The .blend file also includes basic UV Texturing for TOP, RAMP and SIDE textures, includes a COL and a BOUNDS box (We'll get to that later, but it's important that it's there.).
If you have a custom Blender layout, here's how to make the 1x1F brick itself from scratch:
Make a cube, S, type .5, enter, go into Edit Mode with the cube selected, S, Z, type .4.
This translates into a cube (that generally spawns in a 20x20x20 size) that is resized to a size of 10x10x4.
Press N and in OB, type either of the following: C 0 0 0 1 or Brick.
We'll get to the use of "C R G B A" in the texturing chapter.
Finally, let's create the Collision and Bounds (Note: Both of those are calculated by the converter using the bounding box of the whole brick, however, using custom COL and BOUNDS is recommended.).
In Object Mode, Shift + D, Enter, Shift + D, Enter. You now should have 3 overlapping plates. Select each one separately and name them "COL0" and "BOUNDS". Make sure you still have the one named "Brick" or "C 0 0 0 1"
Note: Make sure that the Bounding Box of COL and BOUNDS are in the origin. You shall never move those two, only resize them. You'll find out how to resize them correctly in the next chapter.
That makes the basic of the brick. This brick can already be exported into a 1x1F plate without textures.
If you intend to use textures on your brick, make sure you have SIDE and/or TOP and/or RAMP and/or PRINT .png or .jpg textures at hand and then:
Make the materials and insert the names to MA: from Links and Pipeline, use whichever combinations you want, but you must do them separately: SIDE, TOP, RAMP and PRINT, go to Texture Buttons in each of them and add "Add New", set Texture Type as Image and select the Image from the Browser window (I recommend using the ARROW print for the print texture.).
For UV Texturing convenience:
Go back to Material Buttons and on the last pane, go to Map Input and set to UV (Instead of Orco.). This will allow you to view the texture correctly as you UV Texture. Regardless of which option you have selected though, the exporter will still use the UV option nonetheless.
Now, for the UV Texturing itself, make sure you have a UV/Image Editor pane, then:
In Edit Mode with the Brick selected (Not the COL or BOUNDS.) select all verticles, press U and click Reset.
After that, you will have to manually adjust the rotation and scale (Primarily rotation.) for each face aside, to make sure the lightning corners are always to the Top-Left of the face.
In order to make sure this is set correctly from within Blender, make a camera and a light source, parenting the light source to the camera and move the camera to the respective faces, then render the image.
[image of Camera and light source and a rendered image example]
You now have a fully exportable 1x1F brick with side textures on all faces. This covers the basic creation for a 1x1F Brick in Blender. You should save this file under any "default" name in order to use this brick as a base for any bricks you want to make, since you can easily use this brick, for ease of access, in the creation of other bricks.
If you want to test if the default asset works fine, skip to the Exporting chapter and give it a shot.
A COL object shall be the host of a single cube. A very important factor in this is that COL should always be a prism that is never rotated (This also applies to BOUNDS). In order for a ramp-like rotation for the collision, we're going to use .DTS Collision, but we'll get to that in the final chapters.
If you want 2 COL boxes, you will have to make multiple different objects, namely COL0, COL1 and so on.
The COL object can be resized indifinetely. You can use the scale as you see fit. For precision scaling, after doing a uneven (off the grid) scale, you can use Shift + S then 'Selection -> Grid' to snap vertexes on the grid.
This is very important on the BOUNDS scaling: the BOUNDS shall always have a natural number modifier on the X/Y/Z. That means, that while the 1x1F brick has 1x1x0.4, a 1x2F brick would have 1x2x0.8. Something like 1x1.5x0.5 will not work. Additionally, after scaling through moving the faces, you should move the BOUNDS back to the origin.
While using the Scale function, you can simply type in a multiplier from the default 1x1F BOUNDS while, if you want, using locking (While in scale mode, press X/Y or Z to snap to a certain direction.) in order to only resize a certain part of the brick. Resizing to 2 will make a 2x2FF brick, 3 will make a 3x3x1 brick, while locking to Z and using multiplier will only modify the height. Same goes for X and Y.
The image above shows the creation of a 2x3xFF BOUNDS.
Note: If you plan on making the COL the exact same location and size as BOUNDS, you can remove the COL and let the converter generate the COL after the BOUNDS.
There are multiple notions you need to understand here regarding how coloring works. Each color (not necessarily texture) needs a different OB. For instance, if I wanted to have a brick in paint color and red, I would need two OBs. In order to separate part of the bricks into other OBs, select verticles/faces you want to separate and then press P and click Selected. You will now have 2 OBs, the newly created OBs inheriting the name with a .001 at the end. The other way around, combining 2 OBs, you would select the OBs and press Ctrl+J. The name will be inherited to the last selected OB.
The coloring works by naming the OB in a "C R G B A" pattern. Each custom color will need to start as C or the exporter will think it's a paintable color. R G B and A are variables.
A object that is named different from "C R G B A" where A is a value higher than 0 will be colored based on the paint color.
If A is between -1 and 0, the object will inherit a variation of the paint color.
A stands for alpha, so if alpha consists of decimals, the OB will be exported as transparent, based on the A value. To make a face that looks like the window from the default window you would use "C 0.7 0.7 0.7 0.4".
Same as A, R G B can be between 0 and 1 if A is between 0 and 1, and -1 and 1 if A is between -1 and 0.
That means that "C 1 1 1 1" is valid while "C -1 -1 -1 1" isn't, but "C -1 -1 -1 -1" is, as well as "C 1 1 1 -1". Use of decimals is also availible and recommended for when A is between -1 and 0.
For paint coloring variation, the value of the R G B depends wether it's negative or not. If you use "C -0.5 -0.5 -0.5 -1" it will be a paint darker than the paint color and "C 0.5 0.5 0.5 -1" will be a paint lighter than the paint color. Please note that using "C -1 -1 -1 -1", "C 1 1 1 -1" and "C 0 0 0 -1" is practically useless, as it translates to maximizing the darkness (black) or whiteness (white) of the paint color, or nullifying the variation altogether, having the same effect as naming the OB anythign else.
If you are not familiar with using RGB values, you can use the material options in Blender as a guide.
Note: You can also substitute '0.n' with '.n', allowing you to have two or more OBs with the same color or color variation. Example: "C 0.4 0.4 0.4 1", "C .4 0.4 0.4 1" and "C .4 .4 .4 1" will be the exact same thing, while making two OBs with the same name would make the previous one have .001 added at the ending, which will break the coloring.
Unlike coloring the brick, a OB can have multiple textures for the same color. For instance, the same OB can have SIDE, TOP, RAMP and PRINT textures. Please note you do not write those in OB, but in ME. If you use the assets, there should already be materials for those.
To do so, go to the Editing tab, and in Link and Materials and manually Assign materials to the respective faces. If you only see a single material (1 Mat 1), in Edit Mode use the drop-down to add materials to the OB. You can add anything you want, but they will not show up unless you Assign them to faces separately.
For UV Texturing, you can select faces in Edit Mode, press U and reset. However, for rotation convenience, you can select a single face and use 'Project from View (Bounds)' in order to rotate the UV correctly. This is most required when dealing with Prints, or multiple combined faces. Please note that using Project from View, you should use Ortographic planar view. (Use Num7/1/3, and if you still see perspective, press Num5 to toggle.).
If you intend on texturing corners, you should not have the two corners tangent, but be separated by a common line for both ends of the brick. This will make them fuse more correctly.
For UV texturing a cylinder correctly, select one whole side and use 'Project from View (Bounds)' and manually move each verticle from UV/Image Editor to the edge of the UV Map.
In the case of rectangular faces, the texturing is going to be stretched. You need to manually adjust the UV texture in UV/Image Editor per face. There is no actual algorithm for this, so you will need to use manual editing with the combination of camera and rendering in order to do this correctly. By moving the verticles outside of the map, you will make the edges stretched more, while moving it inside the map, it will move them away from the face. Please note that
Using the same method above, if you want a face to not have any textures, you would move all the verticles in the middle of the map.
For RAMP and TOP, the texture is tiled instead, and using multipliers is suggested. For instance, to make the top texture for 1x2 studs, you would need to move a side of the texture outside the map, twice the size of the current UV. The top-left corner of the UV while tiling shall always be on the top-left of the map.
The converter automatically configures culling, so there's nothing to worry about regarding coverage and culling.
It's recommended to look for any hidden faces and remove them using Face Select Mode. Delete then 'Only Faces' option. A example would be when a brick is tangent to another, unless the tangent face is outside the edge, it's recommended to remove the face that would never be seen in-game by the player.
Unlike .DTS, .BLB supports Quads. Make note of that when modelling. If you made a cylinder, you can remove the interior faces and manually create the faces as quads. (Any and all cylinder will spawn with a verticle in the middle on each side that is connected to the edges by traingles.).
Lastly, and this is particularly important, you should fix the normals. To see if you have bad normals, switch draw type to textured. If through a face you can see the other side, it's a broken normal. To fix it, you can select the face, press W then 'Flip Normals'. You will now see the face correctly. In bigger cases, if many normals are broken, you can also select them, go to Mesh, Normals then select either recalculations. You may still need to manually adjust those with flipping based on what the result is, but it is rarely the case. If you do not fix the normals, and there are broken normals, the face will not appear in-game correctly.
Exporting is by default based on selection, which is just what we need since we will not want to export Camera & Lamp anyway, so, select all the components of the brick, then:
File, Export, 'Wavefront (.obj)...', put in a path and a name then click Export Wavefront OBJ, Untick 'Rotate X90', Tick 'Normals' and 'HQ' and finally tick all 'Blender Objects as OBJ' options.
Go to the .OBJ file exported, ignore the .MTL file and make sure you have 'blbtoobj22.exe' accessbile on the same window and drag the .OBJ file to the .EXE file. You should now have a .BLB file that has the same name as the .OBJ file.
You would want to use a DTS Collision for any collision that would be rotated. This is a particular case in any bricks that would need to have ramp collision. It should however be avoided if the ramp collision is minor (i.e. A chair with a trapeziod top: It's not by any means necessary to have a ramp collision there.).
For DTS Collision, you need to know the basic means of making DTS models in general. If you don't, check out a .DTS Exporting tutorial in the forums.
All you have to do is make your custom collision, and scale it entirely to 0.5 value, then export it with the .DTS Exporter, making sure that the Detail level is Collision, and that in the Editing tab, under Mesh, 'Double Sided' is unticked. The name of the OB is not important in this case.
Make sure to configure the .DTS name in the Packaging chapter correctly.
Given you have downloaded the Packaging asset:
Open the .ZIP, you will have a folder named Packaging_Base. Rename this folder however you want your Add-On to show up in the Add-Ons selector when starting a server. Since it's a brick, you must start with Brick_.
In description.txt, fill in the title and author.
In server.cs, duplicate the datablock as many times as bricks you plan on having in the back, and rename all "XYZ" to what you need:
The XYZ between 'brick' and 'Data' should be named as the datablock. It should be a complex name so it does not overlap with other datablocks. If two datablocks have the same name, it will simply not show up. Anything goes, as this will not show up in-game outside of the console. It should still be something identifiable for debugging.
The XYZ in 'brickFile' should be named the same as the .blb of the brick.
The XYZ in 'category' should be named based on what tab you want the brick to appear in. You should avoid creating tabs for small amount of bricks. And even for bigger amounts, you should resume to using the "Special" tab. The default tabs are Bricks, Plates, Ramps, Rounds, Special and Baseplates.
The XYZ in 'subCategory' should be named on what category you want under the tab you assigned. Unless it's a general brick extension, you should create a custom subCategory, and have all the bricks in the same kind under it. Add-ons can share both category and subCategory name. If multiple bricks in the same .cs have the same subCategory, they will appear in the order you order the datablocks in.
The XYZ in 'uiName' should be named on how you want the name of your brick to appear in-game. This should not overlap with any other brick names, inside the pack or not, otherwise it will not work.
The XYZs in 'iconName', in order, should be the name of the intended .zip file and the name of the .PNG file for the icon. Do not add ".png" at the end. We will cover icon creation in the next chapter.
Regarding the '//'s: Depending if your brick has prints or not, remove the '//'s (If it has prints.) or the whole lines (If it doesn't have prints).
The XYZ in 'printAspectRatio' should be named to what Print_XYZ you want to use for your brick. For instance, there is "Print_1x2f_Default" for the 1x2F brick, which translates to the ratio of "1x2f" to use those prints. You can use anything in there, specially if you want custom prints that have nothing to do with the default print ratios, in which case you will have to manually create prints under that name (Print_XYZ_Something), which is not covered by this tutorial.
OrientationFix determines the amount of times the brick is rotated. This is done for modeling errors. A modeling error, particularly in Blender, is that the Num7/1/3 views are positioned wrongly in the .blb itself. If you use the frontal plane in Blender as the actual frontal plane of the brick, the brick will be spawned sideways in-game; orientationFix however fixes that. There is nothing that orientationFix breaks, so it's there for ease of modelling. Modelling sideways in Blender could be quite confusing.
The final // covers DTS Collision. If you have DTS Collision, remove // and rename the XYZ to the name of the .DTS. Otherwise, remove the whole line.
Note: It's not required to remove //'s, as they are commenters, and the game will not read them anyway. Removing the whole lines is simply done for cleaniness.
After you have everything put in and saved, simply create a .ZIP with the folder, naming it accordingly to what you have put in the .CS.
Note: For an optimal full packaging, you would need to package twice. First, when you make the brick itself, then after you made the icons, since making the icon from within Blender itself would not come out as authentic and optimal for brick icons, but you can go for it if you can get the settings right.
With the brick in-game, making sure it works and is orientated correctly, type "/iconinit" in chat, then "/doicon XYZ", where XYZ is the name of the datablock (between brick and Data in the .CS).
Depending on the case, it's sometimes recommended to zoom in on the brick. This is particularly necessary for smaller bricks. Additionally, make sure you have the Default Colorset, and have shaders disabled.
The screenshot will be created in the "iconShots" folder in the Blockland installation directory.
After that, use your favorite image editing program to remove the pink background, make the brick Black & White, then resize the brick from it's borders to 96x96. It's common that the brick would not be square, so make sure to anchor-resize the largest size to 96, then resize the whole canvas from the middle to 96x96.
Save the file under what name you put in 'iconName' in the .CS, based on what brick you have made.
This is a method that should be very rarely used, as it basically requires the creation of 2 bricks per brick. It means making one brick, then in order for it to either have two different paint colors, or two different prints (Or both.), would be separated on two bricks which then would be stacked ontop of each other, creating a single brick.
What you need to do after you have the finished product is split the objects you want to have a second paint color from the main body, and giving them a different name.
If you want to use color variation or set colors, use the name cutting trick. So, the first brick would use "C -0.5 -0.5 -0.5 -1", however if you want the same darkness level to be attained on the other one, you would use something like "C -.5 -0.5 -0.5 -1".
A unfortunate part is that you will have to manually modify the BOUNDS for both bricks, as BOUNDS1, BOUNDS2 etc. is not applicable for bricks unlike collision.
Also remember that you need to put the BOUNDS bounding box in the origin.
If you made a 1x1FF brick, and you want to split it into 2 1x1F bricks that combine eachother through coloring but have content in both bounds, you would make the bounding box 1x1F, move it's bounding box origin to middle and then move the bottom
of the first brick to the bottom of the bounding box, then the top
of the second brick to the top of the bounding box like so:
For something bigger, like 1x1x5, it's recommended to do 1x1x4FF size for the bottom brick, in which case you would still do the above, and then 1x1F for the top brick, with the same case.
Note: It's normal for either bricks to get out of the BOUNDS.
Important: Please note that this will mess with culling, after exporting, it's recommended to remove culling, manually moving each North/West etc. Quad from the .BLB to Omni Quads.
Door bricks are solely multiple normal bricks. There is not much to say here except that you need to rotate the COL as you rotate the model itself, keeping the frame in place.
Remember that the frame can't consist of a single COL, but from 4 COLs, all prisms.
You would in the end export 3 variations. If you already done the optimization on the inside of the door for the non-visible faces, remember to add them back when making the CW and CCW versions.
For scripting, extract and use the .cs from the default doors, renaming them to your instances. For a simple switch door, you can only have Closed and CW, in the .cs directing all CCW instances to the CW ones.