Wednesday, 26 February 2020

Week 6.2 and 7 - Finally Buildings

After about two not as productive weeks I finally completed the building construction. I had to go back and redo some bits, because I found out, that Unreal can't cook the Python Module nodes.

Looks like a building to me

1 - Roofs redone
Since I initially used Python to create the roof meshes I had to go back and redo the setup, but that turned out to be not that complicated. Instead of using a curve and having to pass the point positions into the coordinate parameter, I used VEX to create a polygon and add the points to it.


float temp[] = detail('op:../../Instance/', 'gfloor_curve_points', 0);
int numPt = len(temp)/3;
int prim = addprim(geoself(), 'poly');
for (int i = 0; i < numPt; i++){
int startIndex = i * 3;
vector pos = set(temp[startIndex], temp[startIndex + 1], temp[startIndex + 2]);
int pt = addpoint(geoself(), pos);
int vert = addvertex(geoself(), prim, pt);
}
I used the following node setup to create the roof meshes and moved each into a separate obj node, so I could use them separately, e.g if I don't need one of them.
EDIT: I added an attribute wrangle node to add a material attribute.


2 - Ground Floor Complete
Since the ground Floor was done in a similar way to the mid floors I won't go into much detail about the process. I cleaned up the code for placing the wall tiles slightly and added a new section for adding unique tiles. I limited the number of unique tiles to 1 per building side, just to simplify things, but in theory it would be possible. I even tried it, but it got a bit buggy.
Here is the code for the unique tiles, nothing special.


//VARIABLES
int addFSep = chi('../../chk_gfloor_sep');
//Points
int points[] = primpoints(geoself(), 0);
int numPt = @numpt;
int cornerPoints[] = points;
int wallPoints[];
int wallPointIndex[];
int basePoints[] = points;
int sepPoints[] = basePoints;
for(int i = 0; i < len(points); i++) {
sepPoints[i] += len(points);
}
append(points, points[0]);
int sortedIndices[] = points;
int numCorners = len(cornerPoints);
int usedBSides[];
//unique pieces
string uniquePieces = chs('../kit_storage/gfloor_kit_unique');
string uniquePieceArray[] = split(uniquePieces);
int numUnique = chi('../../mp_unique_pieces');
float wallHeight = getbbox_size(chs('../../' + uniquePieceArray[0] + '/' + uniquePieceArray[0] + '/file'))[1];;
//separation pieces
string fSep = chs('../kit_storage/fsep_kit_wall');
string sepArray[] = split(fSep);
float sepWidth = getbbox_size(chs('../../' + sepArray[0] + '/' + sepArray[0] + '/file'))[0];
//piece x size
float xWidth[];
vector norm[];
vector pPos[];
//add points
for (int i = 0; i < numUnique; i++){
//Piece Info
int index = chi('../../gfloor_unique_piece_index' + itoa(i+1)) % len(uniquePieceArray);
int side = chi('../../gfloor_unique_building_side' + itoa(i+1));
float offset = chf('../../gfloor_unique_offset' + itoa(i+1));
string pieceName = uniquePieceArray[index];
float pieceWidth = getbbox_size(chs('../../' + pieceName + '/' + pieceName + '/file'))[0];
int startIndex = side;
if(find(usedBSides, side) < 0) {
//Edge Info
int startPoint = sortedIndices[startIndex];
int endPoint = sortedIndices[startIndex + 1];
vector startPos = pointattrib(geoself(), 'P', startPoint, 1);
vector endPos = pointattrib(geoself(), 'P', endPoint, 1);
vector vec = endPos - startPos;
float dist = length(vec) - ( pointattrib(geoself(), 'piece_x_size', startPoint, 1) + pointattrib(geoself(), 'piece_x_size', endPoint, 1));
vector normal = normalize(set(vec[2], vec[1], vec[0] * -1));
if (dist > pieceWidth) {
startPos += normalize(vec) * (pointattrib(geoself(), 'piece_x_size', startPoint, 1) + pieceWidth/2);
dist -= pieceWidth;
vector pos = startPos + offset * dist * normalize(vec);
int pt = addpoint(geoself(), pos);
setpointattrib(geoself(), 'piece_x_size', pt, pieceWidth/2,'set');
setpointattrib(geoself(), 'scale', pt, set(1,1,1),'set');
setpointattrib(geoself(), 'N', pt, normal,'set');
setpointattrib(geoself(), 'instance', pt, '../../'+pieceName,'set');
setpointattrib(geoself(), "row_type", pt, 'wall', "set");
insert(basePoints, startIndex + 1, pt);
append(usedBSides, side);
append(wallPoints, pt);
append(xWidth, pieceWidth);
append(pPos, pos);
append(norm, normal);
append(wallPointIndex, startIndex + 1);
}
}
else{
printf('Side already used. \n');
}
}
//add separation
if(addFSep == 1){
for (int i = 0; i < len(wallPoints); i++) {
float x = xWidth[i];
float scaleX = x / sepWidth;
int index = wallPointIndex[i];
int pt = addpoint(geoself(), pPos[i] + set(0, wallHeight, 0));
setpointattrib(geoself(), 'piece_x_size', pt, xWidth[i],'set');
setpointattrib(geoself(), 'scale', pt, set(scaleX,1,1),'set');
setpointattrib(geoself(), 'N', pt, norm[i],'set');
setpointattrib(geoself(), 'instance', pt, '../../'+sepArray[0],'set');
setpointattrib(geoself(), "row_type", pt, 'sep', "set");
insert(sepPoints, index, pt);
}
}
setdetailattrib(geoself(), 'base_Points', basePoints, 'set');
setdetailattrib(geoself(), 'sep_Points', sepPoints, 'set');
view raw Unique_Tiles.v hosted with ❤ by GitHub

This could and should probably be optimised.
Just for completeness sake I'll add the code for placing the wall tiles, but it is not any different from the middle floor section.

//VARIABLES
int basePoints[] = detail(geoself(), 'base_Points');
append(basePoints, basePoints[0]);
int points[] = primpoints(geoself(), 0);
int numPt = len(points);
int numRows = 2 - (1 - chi('../../chk_gfloor_sep'));
//modular kit piece arrays
//pillars
string pillars = chs('../kit_storage/gfloor_kit_pillar');
string pillarArray[] = split(pillars);
int pillarIndex = int(chi('../../gfloor_pillar_index')%len(pillarArray));
string pillarRef = '../../'+ pillarArray[pillarIndex];
int numPillars = chi('../../gfloor_num_pillars');
float pillarWidth = float(getbbox_size(chs('../../' + pillarArray[0] + '/' + pillarArray[0] + '/file' ))[0]);
//plain wall
string wall = chs('../kit_storage/gfloor_kit_wall');
string wallArray[] = split(wall);
int wallIndex = chi('../../gfloor_wall_index') % len(wallArray);
float wallWidth = getbbox_size(chs('../../' + wallArray[wallIndex] + '/' + wallArray[wallIndex] +'/file'))[0];
float wallHeight = getbbox_size(chs('../../' + wallArray[wallIndex] + '/' + wallArray[wallIndex] +'/file'))[1];
string wallRef = '../../' + wallArray[wallIndex];
int numWallPieces = chi('../../gfloor_num_pieces_btwn_pillars');
//windows
string windows = chs('../kit_storage/gfloor_kit_sw');
string windowArray[] = split(windows);
int windowIndex = chi('../../gfloor_wframe_index') % len(windowArray);
string pieceRef = '../../' + windowArray[windowIndex];
float pieceWidth = getbbox_size(chs('../../' + windowArray[windowIndex] + '/' + windowArray[windowIndex] +'/file'))[0];
// floor separation
string fSep = chs('../kit_storage/fsep_kit_wall');
string fSepPillar = chs('../kit_storage/fsep_kit_pillar');
string fSepRef = '../../' + rstrip(fSep);
string fSepPillarRef = '../../' + rstrip(fSepPillar);
//PLACE PIECES
for (int row = 0; row < numRows; row++){
float offset = row * wallHeight;
//loop through corners
for (int c = 0; c < len(basePoints) - 1; c++) {
int startPoint = basePoints[c];
int endPoint = basePoints[c + 1];
//PREP
vector startPointPos = pointattrib(geoself(), 'P', startPoint, 1);
vector endPointPos = pointattrib(geoself(), 'P',endPoint, 1);
vector dir = normalize(endPointPos - startPointPos);
// start and end position, taking corner piece width into consideration
vector startPos = startPointPos + (pointattrib(geoself(), 'piece_x_size', startPoint, 1)*dir);
vector endPos = endPointPos - (pointattrib(geoself(), 'piece_x_size', endPoint, 1)*dir);
//normal for placing the pieces on the edges
vector n = set(dir[2], 0, dir[0] * -1);
float dist = distance(startPos, endPos);
if ( (pointattrib(geoself(), 'piece_x_size', startPoint, 1) + pointattrib(geoself(), 'piece_x_size', endPoint, 1)) < distance(startPointPos, endPointPos) ) {
//CALCULATE SECTIONS
if (numWallPieces == 0){
numPillars = 1;
}
float sectionWidth = (numWallPieces * wallWidth) * clamp(numPillars - 1, 0, 10) + numPillars * pillarWidth;
sectionWidth *= int(sectionWidth < dist);
int numSections = int((sectionWidth != 0));
//num tiles on each side of pillar section
float restWidth = dist - sectionWidth;
int numPieces;
if (sectionWidth != 0) {
numPieces = int(floor((restWidth/2)/wallWidth));
numPieces -= (numPieces % 2) * (1 - int(sectionWidth < dist));
}
else {
numPieces = int(floor(restWidth / wallWidth));
}
//filler
float fillerWidth;
if (sectionWidth != 0) {
fillerWidth = (restWidth - ((numPieces * 2) * wallWidth))/2;
}
else {
fillerWidth = (restWidth - ((numPieces) * wallWidth))/2;
}
float fillerScaleX = fillerWidth / wallWidth;
//PLACE PIECES
vector tempPos;
vector tempStartPos;
vector tempEndPos;
vector pillarStartPos;
int tempPt;
//filler
if(numSections != 0 || numPieces != 0){
//set ref
string fillerRef = '';
if(row == 0){
fillerRef = wallRef;
}
else if(row == 1){
fillerRef = fSepRef;
fillerScaleX *= 2;
}
if (fillerWidth != 0) {
tempPos = startPos + (fillerWidth/2) * dir + set(0, offset, 0);
tempStartPos = tempPos;
tempPt = addpoint(geoself(), tempStartPos);
setpointattrib(geoself(), 'instance', tempPt, fillerRef, 'set');
setpointattrib(geoself(), 'scale', tempPt, set(fillerScaleX,1,1), 'set');
setpointattrib(geoself(), 'N', tempPt, n, 'set');
tempPos = endPos - (fillerWidth/2) * dir + set(0, offset, 0);
tempEndPos = tempPos;
tempPt = addpoint(geoself(), tempEndPos);
setpointattrib(geoself(), 'instance', tempPt, fillerRef, 'set');
setpointattrib(geoself(), 'scale', tempPt, set(fillerScaleX,1,1), 'set');
setpointattrib(geoself(), 'N', tempPt, n, 'set');
}
}
else {
//set ref
string fillerRef = '';
if(row == 0){
fillerRef = wallRef;
}
else if(row == 1){
fillerRef = fSepRef;
fillerScaleX *= 2;
}
if (fillerWidth != 0) {
tempPos = startPos + (fillerWidth * dir) + set(0, offset, 0);
tempPt = addpoint(geoself(), tempPos);
setpointattrib(geoself(), 'instance', tempPt, fillerRef, 'set');
setpointattrib(geoself(), 'scale', tempPt, set(fillerScaleX * 2,1,1), 'set');
setpointattrib(geoself(), 'N', tempPt, n, 'set');
}
}
// add additional pieces
if (numPieces != 0){
string spareRef = '';
float spareScaleX = 1;
if (row == 0){
spareRef = pieceRef;
}
else if (row == 1){
spareRef = fSepRef;
spareScaleX *= 2;
}
vector start, end;
if (sectionWidth != 0) {
for (int p = 0; p < numPieces; p++){
tempPos = tempStartPos + (pieceWidth * dir)/2 + (fillerWidth * dir)/2 + (pieceWidth * p) * dir;
tempPt = addpoint(geoself(), tempPos);
start = tempPos;
setpointattrib(geoself(), 'instance', tempPt, spareRef, 'set');
setpointattrib(geoself(), 'scale', tempPt, set(spareScaleX,1,1), 'set');
setpointattrib(geoself(), 'N', tempPt, n, 'set');
tempPos = tempEndPos - (pieceWidth * dir)/2 - (fillerWidth * dir)/2 - (pieceWidth * p) * dir;
tempPt = addpoint(geoself(), tempPos);
end = tempPos;
setpointattrib(geoself(), 'instance', tempPt, spareRef, 'set');
setpointattrib(geoself(), 'scale', tempPt, set(spareScaleX,1,1), 'set');
setpointattrib(geoself(), 'N', tempPt, n, 'set');
}
tempStartPos = start;
tempEndPos = end;
pillarStartPos = tempStartPos + pieceWidth/2 * dir;
}
else{
for (int p = 0; p < numPieces; p++) {
tempPos = tempStartPos + (pieceWidth * dir)/2 + (fillerWidth * dir)/2 + (pieceWidth * p) * dir;
tempPt = addpoint(geoself(), tempPos);
setpointattrib(geoself(), 'instance', tempPt, spareRef, 'set');
setpointattrib(geoself(), 'scale', tempPt, set(spareScaleX,1,1), 'set');
setpointattrib(geoself(), 'N', tempPt, n, 'set');
}
}
}
else{
pillarStartPos = tempStartPos + fillerWidth/2 * dir;
}
//add pillar sections
if(numSections != 0){
string wRef, pRef = '';
float xScale = 1;
if (row == 0){
wRef = pieceRef;
pRef = pillarRef;
xScale = 1;
}
else if (row == 1){
wRef = fSepRef;
pRef = fSepPillarRef;
xScale = 1;
}
for(int pl = 0; pl < numPillars; pl++){
vector pillarPos;
xScale = 1;
pillarPos = pillarStartPos + (pillarWidth/2 * dir) + (pillarWidth * pl * dir) + (numWallPieces * pieceWidth * dir * pl);
tempPt = addpoint(geoself(), pillarPos);
setpointattrib(geoself(), 'instance', tempPt, pRef, 'set');
setpointattrib(geoself(), 'scale', tempPt, set(xScale,1,1), 'set');
setpointattrib(geoself(), 'N', tempPt, n, 'set');
for (int sWall = 0; sWall < numWallPieces; sWall++) {
if(pl < numPillars - 1){
if (row == 1) {
xScale = 2;
}
vector wallPos = pillarPos + (pillarWidth/2 * dir) + (wallWidth/2 * dir) + (wallWidth * sWall * dir);
tempPt = addpoint(geoself(), wallPos);
setpointattrib(geoself(), 'instance', tempPt, wRef, 'set');
setpointattrib(geoself(), 'scale', tempPt, set(xScale,1,1), 'set');
setpointattrib(geoself(), 'N', tempPt, n, 'set');
}
}
}
}
}
}
}
And finally the full ground floor section in action:


This is basically how far I got over the last couple of days. From here on I will focus on sorting the material IDs first and then move on to removing wall sections and creating LODs.
But again: It's a building !!!

Building Variation
And it even works in Unreal, that's progress.

Building Generator in UE4

No comments:

Post a Comment