1 /** 2 Copyright: Copyright (c) 2016-2018 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module railroad.rail.mesh; 7 8 import voxelman.log; 9 import std.range; 10 import std.conv : to; 11 import voxelman.container.buffer; 12 import voxelman.math; 13 14 import voxelman.model.vertex; 15 import voxelman.graphics; 16 import voxelman.geometry; 17 18 import voxelman.world.mesh.chunkmesh; 19 import voxelman.world.mesh.sidemeshers.full; 20 import voxelman.world.mesh.sidemeshers.utils; 21 import voxelman.world.block; 22 import voxelman.world.blockentity.blockentityaccess; 23 import voxelman.world.blockentity.blockentitydata; 24 import voxelman.world.blockentity.utils; 25 26 import railroad.rail.utils; 27 28 void makeRailMesh(BlockEntityMeshingData meshingData) 29 { 30 auto railData = RailData(meshingData.data); 31 if (meshingData.data.type == BlockEntityType.localBlockEntity && 32 meshingData.entityPos == ivec3(0,0,0)) 33 { 34 putRailMesh!MeshVertex( 35 meshingData.output[Solidity.solid], 36 meshingData.chunkPos, 37 railData); 38 } 39 40 if (railData.isSlope) 41 { 42 CubeSide sideToMesh; 43 if (isSlopeUpSideBlock(railData, meshingData.entityPos, sideToMesh)) 44 { 45 if (meshingData.sides & (1 << sideToMesh)) 46 { 47 ubyte[4] occlusions = meshingData.occlusionHandler(meshingData.blockIndex, sideToMesh); 48 SideParams sideParams = SideParams( 49 ubvec3(meshingData.chunkPos), 50 calcColor(meshingData.blockIndex, meshingData.color), 51 [0,0], 52 0, 53 &meshingData.output[Solidity.solid]); 54 meshFullSideOccluded(sideToMesh, occlusions, sideParams); 55 } 56 } 57 } 58 59 if (meshingData.sides & SideMask.yneg) 60 { 61 ubyte[4] occlusions = meshingData.occlusionHandler(meshingData.blockIndex, CubeSide.yneg); 62 SideParams sideParams = SideParams( 63 ubvec3(meshingData.chunkPos), 64 calcColor(meshingData.blockIndex, meshingData.color), 65 [0,0], 66 0, 67 &meshingData.output[Solidity.solid]); 68 meshFullSideOccluded(CubeSide.yneg, occlusions, sideParams); 69 } 70 } 71 72 void putRailMesh(Vert, Sink)(ref Sink sink, ivec3 chunkPos, RailData data) 73 { 74 ivec3 tilePos = railTilePos(chunkPos); 75 auto chunkPosF = vec3(tilePos); 76 77 foreach(segment; data.getSegments()) 78 { 79 auto meshIndex = railSegmentMeshId[segment]; 80 auto mesh = railMeshes[meshIndex]; 81 ubyte rotation = railSegmentMeshRotation[segment]; 82 auto rotator = getCCWRotationShiftOriginFunction!vec3(rotation); 83 vec3 offset = chunkPosF + vec3(railSegmentOffsets[segment]); 84 vec3 meshSize = vec3(meshSizes[meshIndex]); 85 86 sink.reserve(mesh.length); 87 88 foreach(v; mesh) 89 { 90 vec3 pos = rotator(v.position, meshSize) + offset; 91 sink.put(Vert(pos, [0,0], v.color.r)); 92 } 93 } 94 } 95 96 alias RailVertexT = VertexPosColor!(float, 3, ubyte, 3); 97 __gshared RailVertexT[][3] railMeshes; 98 ivec3[3] meshSizes = [ 99 ivec3(4, 1, 8), 100 ivec3(6, 1, 6), 101 ivec3(4, 1, 8)]; 102 103 104 void putRailPreview( 105 ref Buffer!ColoredVertex buffer, 106 RailPos railPos0, RailPos railPos1, 107 CubeSide side0, CubeSide side1, 108 bool flipEndOffset, 109 Colors color) 110 { 111 assert(side0 < 4); 112 assert(side1 < 4); 113 vec3 startOff = vec3(railPos0.x * RAIL_TILE_SIZE, railPos0.y, railPos0.z * RAIL_TILE_SIZE); 114 vec3 endOff = vec3(railPos1.x * RAIL_TILE_SIZE, railPos1.y, railPos1.z * RAIL_TILE_SIZE); 115 116 vec3[4] sideOffsets = [ 117 vec3(RAIL_TILE_SIZE/2-0.25, 0, 0), // zneg 118 vec3(RAIL_TILE_SIZE/2-0.25, 0, RAIL_TILE_SIZE-0.5), // zpos 119 vec3(RAIL_TILE_SIZE-0.5, 0, RAIL_TILE_SIZE/2 - 0.25), // xpos 120 vec3(0, 0, RAIL_TILE_SIZE/2 - 0.25)]; // xneg 121 122 vec3[4] sideOffsetAxis = [ 123 vec3(-1, 0, 0), // zneg 124 vec3(-1, 0, 0), // zpos 125 vec3( 0, 0, 1), // xpos 126 vec3( 0, 0, 1)];// xneg 127 128 vec3[4] getSideGeometry(CubeSide side, vec3 offset, float mult) { 129 return [ 130 vec3(cubeVerticies[cubeSideVertIndices[side][0]]) * mult + offset, // zneg 131 vec3(cubeVerticies[cubeSideVertIndices[side][1]]) * mult + offset, // zpos 132 vec3(cubeVerticies[cubeSideVertIndices[side][2]]) * mult + offset, // xpos 133 vec3(cubeVerticies[cubeSideVertIndices[side][3]]) * mult + offset];// xneg 134 } 135 136 vec3[4] start0 = getSideGeometry(side0, sideOffsets[side0] + sideOffsetAxis[side0] + startOff, 0.5f); 137 vec3[4] start1 = getSideGeometry(side0, sideOffsets[side0] - sideOffsetAxis[side0] + startOff, 0.5f); 138 139 vec3 endOffsetAxis = sideOffsetAxis[side1]; 140 if (flipEndOffset) endOffsetAxis = -endOffsetAxis; 141 vec3[4] end0 = getSideGeometry(side1, sideOffsets[side1] + endOffsetAxis + endOff, 0.5f); 142 vec3[4] end1 = getSideGeometry(side1, sideOffsets[side1] - endOffsetAxis + endOff, 0.5f); 143 144 const vec3[8] corners0 = [ 145 vec3(start0[1]), vec3(end0[2]), vec3(start0[2]), vec3(end0[1]), 146 vec3(start0[0]), vec3(end0[3]), vec3(start0[3]), vec3(end0[0])]; 147 buffer.put4gonalPrismTris(corners0, vec3(0,0,0), color); 148 149 const vec3[8] corners1 = [ 150 vec3(start1[1]), vec3(end1[2]), vec3(start1[2]), vec3(end1[1]), 151 vec3(start1[0]), vec3(end1[3]), vec3(start1[3]), vec3(end1[0])]; 152 buffer.put4gonalPrismTris(corners1, vec3(0,0,0), color); 153 }