UNPKG

io3fix

Version:

toolkit for interior apps

1,382 lines (1,183 loc) 62.8 kB
'use strict'; // dependencies import getSchema from './common/get-schema.js' import getMaterial from './common/get-material.js' import updateSchema from './common/update-schema.js' import generateNormals from '../../../utils/data3d/buffer/get-normals' import generateUvs from '../../../utils/data3d/buffer/get-uvs' import cloneDeep from 'lodash/cloneDeep' export default { schema: getSchema('stairs'), init: function () {}, updateSchema: updateSchema, update: function (oldData) { var this_ = this var data = this_.data // remove old mesh this.remove() // get defaults and this.attributes = cloneDeep(data) // get meshes and materials from el3d modules var meshes = this.generateMeshes3d() // clean up empty meshes to prevent errors var meshKeys = Object.keys(meshes) meshKeys.forEach(key => { if (!meshes[key].positions || !meshes[key].positions.length) { // console.warn('no vertices for mesh', key) delete meshes[key] } }) // setup materials // defaults var materials = { steps: 'basic-wall', tread: 'wood_parquet_oak', railing: { colorDiffuse: [0.85, 0.85, 0.85] } } // check for adapted materials var materialKeys = Object.keys(data).filter(function(key) { return key.indexOf('material_') > -1 }) // add materials to instance materialKeys.forEach(function(key) { var mesh = key.replace('material_', '') materials[mesh] = data[key] }) // fetch materials from mat library Object.keys(materials).forEach(mat => { materials[mat] = getMaterial(materials[mat]) }) // construct data3d object var data3d = { meshes: meshes, materials: materials } // create new one this_.mesh = new THREE.Object3D() this_.data3dView = new io3d.aFrame.three.Data3dView({parent: this_.mesh}) // update view this_.data3dView.set(data3d) this_.el.setObject3D('mesh', this_.mesh) // emit event this_.el.emit('mesh-updated'); }, remove: function () { if (this.data3dView) { this.data3dView.destroy() this.data3dView = null } if (this.mesh) { this.el.removeObject3D('mesh') this.mesh = null } }, generateMeshes3d: function () { var a = this.attributes // settings for step ratio var stepRatioMax = 2.6, stepRatioMin = 1.15, // internals stepsVertices = [], svPos = 0, treadVertices = [], tvPos = 0, railingVertices = [], rvPos = 0, // internal settings handrailThickness = 0.02, stairWidth = a.w, stairLength = a.l, flipStair = a.circulation === 'left', stepWidth = a.stepWidth, stairWell = 0.3, nosing = 0.02, riserExt = a.stepThickness var aX, aY, aZ, bY, cX, cY, cZ, dY, eX, eY, eZ, fX, fZ, gZ, hX, hZ, // BASE kX, kY, kZ, lY, mX, mZ, oX, oZ, qX, qZ, // TREAD runA, runB, runC, // RUN stepNumber, calcRiser, tread, calcTread, stepsLength // STAIR Configurations if (a.stairType === 'straight') { // Straight // reset stairWidth a.w = stepWidth stepWidth = a.w a.circulation = 'right' if ((a.l/ a.h)<=stepRatioMin) a.l = a.h*stepRatioMin if ((a.l/ a.h)>=stepRatioMax) a.l = a.h*stepRatioMax stairLength = a.l calcTread = ((stairLength/a.h + 1.2321)/0.10357)/100 stepNumber = Math.round(stairLength/calcTread) calcRiser = a.h/stepNumber tread = stairLength/stepNumber runA = stepNumber _straightRun(0, 0, 0, runA, tread) } else if (a.stairType === 'straightLanding') { // Straight + Platform var platformLength = 1 // reset stairWidth a.w = a.stepWidth stepWidth = a.w a.circulation = 'right' if (((a.l-platformLength) / a.h)<stepRatioMin) a.l = a.h*stepRatioMin + platformLength if (((a.l-platformLength) / a.h)>stepRatioMax) a.l = a.h*stepRatioMax + platformLength stepsLength = a.l-platformLength calcTread = ((stepsLength / a.h + 1.2321)/0.10357)/100 stepNumber = Math.round(stepsLength/calcTread) calcRiser = a.h/stepNumber tread = stepsLength/stepNumber runA = Math.ceil(stepNumber/2) runB = stepNumber - runA _straightRun(0, 0, 0, runA, tread) _platform(runA*tread, runA*calcRiser, 0, stepWidth, platformLength) _straightRun(runA*tread+platformLength, runA*calcRiser, 0, runB, tread) } else if (a.stairType === 'lShaped') { // L-Shaped if (a.w<stepWidth+0.3) a.w=stepWidth+0.3 if (a.l<stepWidth+0.3) a.l=stepWidth+0.3 stepsLength = a.l + a.w - (2*stepWidth) calcTread = ((stepsLength / a.h + 1.2321)/0.10357)/100 stepNumber = Math.round(stepsLength/calcTread) calcRiser = a.h/stepNumber tread = stepsLength/stepNumber runA = Math.floor((a.l-stepWidth)/tread) runB = stepNumber - runA if (!flipStair) { _straightRun(0, 0, 0, runA, (a.l-stepWidth)/runA) _platform(a.l-stepWidth, runA*calcRiser, 0, stepWidth, stepWidth) _straightRun(a.l, runA*calcRiser, stepWidth, runB, tread = (a.w-stepWidth)/runB, 90) } else { _straightRun(0, 0, a.w-stepWidth, runA, (a.l-stepWidth)/runA) _platform(a.l, runA*calcRiser, a.w-stepWidth, stepWidth, stepWidth, 90) _straightRun(a.l-stepWidth, runA*calcRiser, a.w-stepWidth, runB, tread = (a.w-stepWidth)/runB, -90) } } else if (a.stairType === 'halfLanding') { // Half Landing if (a.w<stepWidth*2+0.05) a.w=stepWidth*2+0.05 stairWidth = a.w //stepsLength = (a.l-stepWidth) if (((a.l-stepWidth)*2 / a.h)<stepRatioMin) a.l = a.h/2*stepRatioMin + stepWidth if (((a.l-stepWidth)*2 / a.h)>stepRatioMax) a.l = a.h/2*stepRatioMax + stepWidth stepsLength = a.l-stepWidth calcTread = ((stepsLength / (a.h/2) + 1.2321)/0.10357)/100 stepNumber = Math.round(stepsLength/calcTread) calcRiser = (a.h/2)/stepNumber tread = stepsLength/stepNumber runA = stepNumber runB = stepNumber if (!flipStair) { _straightRun(0, 0, 0, runA, tread) _platform(runA * tread, runA * calcRiser, 0, stairWidth, stepWidth) _straightRun(runA * tread, runA * calcRiser, stairWidth, runB, tread, 180) } else { _straightRun(0, 0, stairWidth - stepWidth, runA, tread) _platform(runA * tread, runA * calcRiser, 0, stairWidth, stepWidth) _straightRun(runA * tread, runA * calcRiser, stepWidth, runB, tread, 180) } } else if (a.stairType === '2QuarterLanding') { // 2 Quarter Landing if (a.w<stepWidth*2+0.3) a.w=stepWidth*2+0.3 if (a.l<stepWidth+0.3) a.l=stepWidth+0.3 stairWidth = a.w stepsLength = (a.l-stepWidth)*2+a.w-stepWidth*2 calcTread = ((stepsLength / a.h + 1.2321)/0.10357)/100 stepNumber = Math.round(stepsLength/calcTread) calcRiser = a.h/stepNumber tread = stepsLength/stepNumber runA = Math.round((a.l-stepWidth)/tread) runC = runA runB = stepNumber - runA*2 // maintain full Length by altering tread Length for runA & runC tread = (a.l-stepWidth)/runA // Workaround for misconfiguration if (runB < 1 && stairWidth > stepWidth * 2) { runB = 1 runC = runC - 1 } if (!flipStair) { _straightRun(0, 0, 0, runA, (a.l - stepWidth) / runA) _platform(a.l - stepWidth, runA * calcRiser, 0, stepWidth, stepWidth) _straightRun(a.l, runA * calcRiser, stepWidth, runB, (a.w - stepWidth * 2) / runB, 90) _platform(a.l, (runA + runB) * calcRiser, stairWidth - stepWidth, stepWidth, stepWidth, 90) _straightRun(runA * tread, (runA + runB) * calcRiser, stairWidth, runC, (a.l - stepWidth) / runA, 180) } else { _straightRun(0, 0, stairWidth - stepWidth, runA, (a.l - stepWidth) / runA) _platform(a.l - stepWidth, (runA + runB) * calcRiser, 0, stepWidth, stepWidth) _straightRun(a.l - stepWidth, runA * calcRiser, stairWidth - stepWidth, runB, (a.w - stepWidth * 2) / runB, -90) _platform(a.l, runA * calcRiser, stairWidth - stepWidth, stepWidth, stepWidth, 90) _straightRun(runA * tread, (runA + runB) * calcRiser, stepWidth, runC, (a.l - stepWidth) / runA, 180) } } else if (a.stairType === 'winder') { // Winder if (a.w<stepWidth+stairWell+0.5) a.w=stepWidth+stairWell+0.5 if (a.l<stepWidth+stairWell+0.5) a.l=stepWidth+stairWell+0.5 stepsLength = a.l + a.w - stepWidth calcTread = ((stepsLength / a.h + 1.2321)/0.10357)/100 stepNumber = Math.round(stepsLength/calcTread) calcRiser = a.h/stepNumber tread = stepsLength/stepNumber //console.log("Winder") runB = 2*Math.round((stepWidth/2+stairWell)/tread) runA = Math.round((a.l-stepWidth-stairWell)/tread) runC = stepNumber - runA - runB if (!flipStair) { _straightRun(0, 0, 0, runA, (a.l - stepWidth - stairWell) / runA) _winder(a.l - stepWidth - stairWell, runA * calcRiser, 0, runB) if (runC > 0) _straightRun(a.l, (runA + runB) * calcRiser, stepWidth + stairWell, runC, (a.w - stepWidth - stairWell) / runC, 90) } else { _straightRun(0, 0, a.w-stepWidth, runA, (a.l - stepWidth - stairWell) / runA) _winder(a.l - stepWidth - stairWell, runA * calcRiser, a.w-stepWidth, runB, 0, flipStair) if (runC > 0) _straightRun(a.l - stepWidth, (runA + runB) * calcRiser, a.w - stepWidth - stairWell, runC, (a.w - stepWidth - stairWell) / runC, -90) } } else if (a.stairType === 'doubleWinder') { // Double Winder if (a.w<(stepWidth+0.15)*2) a.w=(stepWidth+0.15)*2 if (a.l<stepWidth+stairWell) a.l=stepWidth+stairWell stepsLength = a.l*2 + a.w - stepWidth*2 calcTread = ((stepsLength / a.h + 1.2321)/0.10357)/100 stepNumber = Math.round(stepsLength/calcTread) calcRiser = a.h/stepNumber tread = stepsLength/stepNumber runB = 4*Math.round((stepWidth/2+stairWell)/tread) runC = Math.round((a.w-(stepWidth+stairWell)*2)/tread) runA = Math.round((stepNumber - runB - runC) / 2) if (runA < 1) { stairWell = a.l-stepWidth runA = 0 } if (runC < 1) { stairWell = a.w/2-stepWidth runC = 0 } if (!flipStair) { if (runA > 0) _straightRun(0, 0, 0, runA, (a.l - stepWidth - stairWell) / runA) _winder(a.l - stepWidth - stairWell, runA * calcRiser, 0, runB / 2) if (runC > 0) _straightRun(a.l, (runA + runB / 2) * calcRiser, stepWidth + stairWell, runC, (a.w - (stepWidth + stairWell) * 2) / runC, 90) _winder(a.l, (runA + runB / 2 + runC) * calcRiser, a.w - stepWidth - stairWell, runB / 2, 90) if (runA > 0) _straightRun(a.l - stepWidth - stairWell, (runA + runB + runC) * calcRiser, a.w, runA, (a.l - stepWidth - stairWell) / runA, 180) } else { if (runA > 0) _straightRun(0, 0, a.w - stepWidth, runA, (a.l - stepWidth - stairWell) / runA) _winder(a.l - stepWidth - stairWell, runA * calcRiser, a.w - stepWidth, runB / 2, 0, flipStair) if (runC > 0) _straightRun(a.l - stepWidth, (runA + runB / 2) * calcRiser, a.w - stepWidth - stairWell, runC, (a.w - (stepWidth + stairWell) * 2) / runC, -90) _winder(a.l - stepWidth, (runA + runB / 2 + runC) * calcRiser, stepWidth + stairWell, runB / 2, -90, flipStair) if (runA > 0) _straightRun(a.l - stepWidth - stairWell, (runA + runB + runC) * calcRiser, stepWidth, runA, (a.l - stepWidth - stairWell) / runA, 180) } } else if (a.stairType === 'spiral') { // Spiral stairWidth = a.w if (stairWidth < stepWidth) { stairWidth = stepWidth a.w = stepWidth } if ((a.l/ a.h)<=stepRatioMin) a.l = a.h*stepRatioMin if ((a.l/ a.h)>=stepRatioMax) a.l = a.h*stepRatioMax stairLength = a.l calcTread = ((stairLength/a.h + 1.2321)/0.10357)/100 stepNumber = Math.round(stairLength/calcTread) calcRiser = a.h/stepNumber tread = stairLength/stepNumber runA = stepNumber _spiralRun(0, 0, 0, runA, flipStair) } // Geometry Generation Functions function _straightRun(xCursor, yCursor, zCursor, stepNumber, tread, angle) { ////// BASE var vs, ve, ts, te, rs, re, xRotate, i, offsetX = xCursor, offsetZ = zCursor vs = stepsVertices.length ts = treadVertices.length rs = railingVertices.length // Left Railing if (a.railing === 'left'||a.railing === 'both') _railing(xCursor, yCursor+calcRiser, zCursor+handrailThickness+0.01, xCursor+stepNumber*tread, yCursor+stepNumber*calcRiser+calcRiser, zCursor+handrailThickness+0.01) if (a.railing === 'right'||a.railing === 'both') _railing(xCursor, yCursor+calcRiser, zCursor+stepWidth-0.01, xCursor+stepNumber*tread, yCursor+stepNumber*calcRiser+calcRiser, zCursor+stepWidth-0.01) for (var k = 0; k < stepNumber; k++) { // F----I // |\ |\ // G \ H \ // |\ A----D // J \| | // B C // | / // E aX = xCursor aY = yCursor + calcRiser - a.treadHeight aZ = zCursor + stepWidth bY = yCursor cX = xCursor + tread cY = yCursor + calcRiser - riserExt cZ = aZ eY = yCursor - riserExt fX = aX fZ = zCursor hX = cX hZ = fZ _step(aX, aY, aZ, bY, cY, cX, cZ, eY, fX, fZ, hX, hZ) xCursor += tread yCursor += calcRiser } ve = stepsVertices.length te = treadVertices.length re = railingVertices.length if (angle) { var cosAngle = Math.cos(angle / 180 * Math.PI), sinAngle = Math.sin(angle / 180 * Math.PI) for (i=vs;i<ve-2; i = i + 3){ xRotate=stepsVertices[i]-offsetX stepsVertices[i+2]=stepsVertices[i+2]-offsetZ stepsVertices[i]=xRotate*cosAngle-stepsVertices[i+2]*sinAngle+offsetX stepsVertices[i+2]=stepsVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } for (i=ts;i<te-2; i = i + 3){ xRotate=treadVertices[i]-offsetX treadVertices[i+2]=treadVertices[i+2]-offsetZ treadVertices[i]=xRotate*cosAngle-treadVertices[i+2]*sinAngle+offsetX treadVertices[i+2]=treadVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } for (i=rs;i<re-2; i = i + 3){ xRotate=railingVertices[i]-offsetX railingVertices[i+2]=railingVertices[i+2]-offsetZ railingVertices[i]=xRotate*cosAngle-railingVertices[i+2]*sinAngle+offsetX railingVertices[i+2]=railingVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } } } function _platform(xCursor, yCursor, zCursor, width, length, angle) { // F-------I // |\ |\ // G \-----H \ // \ A-------D // \| \| // B-------C var platformExt = length, vs, ve, ts, te, rs, re, xRotate, i, offsetX = xCursor, offsetZ = zCursor vs = stepsVertices.length ts = treadVertices.length rs = railingVertices.length aX = xCursor aY = yCursor - a.treadHeight aZ = zCursor+ width bY = yCursor - riserExt //cY = yCursor - riserExt cX = xCursor + platformExt eX = aX eY = yCursor - riserExt fZ = zCursor // Straight Platform Railing if (a.stairType === 'straightLanding') { if (a.railing === 'left'||a.railing === 'both') _railing(xCursor, yCursor+calcRiser, zCursor+handrailThickness+0.01, xCursor+length, yCursor+calcRiser, zCursor+handrailThickness+0.01) if (a.railing === 'right'||a.railing === 'both') _railing(xCursor, yCursor+calcRiser, zCursor+width-0.01, xCursor+length, yCursor+calcRiser, zCursor+width-0.01) } // L-Shape Platform Railing if (a.stairType === 'lShaped'||a.stairType === '2QuarterLanding') { if ((a.railing === 'left' && !flipStair) || (a.railing === 'right' && flipStair) || a.railing === 'both') { _railing(xCursor, yCursor+calcRiser, zCursor+handrailThickness+0.01, xCursor+length-handrailThickness-0.01, yCursor+calcRiser, zCursor+handrailThickness+0.01, 0, true) _railing(xCursor+length-handrailThickness-0.01, yCursor+calcRiser, zCursor+0.01, xCursor+length+width-handrailThickness-0.02, yCursor+calcRiser, zCursor+0.01, 90, true) } } // Half Landing Platform Railing if (a.stairType === 'halfLanding' ){ if ((a.railing === 'left' && !flipStair) || (a.railing === 'right' && flipStair) || a.railing === 'both') { _railing(xCursor, yCursor+calcRiser, zCursor+handrailThickness+0.01, xCursor+length-handrailThickness-0.01, yCursor+calcRiser, zCursor+handrailThickness+0.01, 0, true) _railing(xCursor+length-handrailThickness-0.01, yCursor+calcRiser, zCursor+0.01, xCursor+length+width-handrailThickness*2-0.03, yCursor+calcRiser, zCursor+0.01, 90, true) _railing(xCursor+length-0.01, yCursor+calcRiser, zCursor+width-0.01-handrailThickness, xCursor+length+length-handrailThickness, yCursor+calcRiser, zCursor+width-0.01-handrailThickness, 180, true) } if ((a.railing === 'left' && flipStair) || (a.railing === 'right' && !flipStair) || a.railing === 'both') { _railing(xCursor, yCursor+calcRiser, zCursor+stepWidth-0.01-handrailThickness, xCursor+width-stepWidth*2+(0.01+handrailThickness)*2, yCursor+calcRiser, zCursor+stepWidth-0.01-handrailThickness, 90) } } // Platform Base if (a.stairType === 'halfLanding' && stairWell) { // FRONT //F stepsVertices[svPos] = stepsVertices[svPos + 9] = aX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = fZ + stepWidth //G stepsVertices[svPos + 3] = aX stepsVertices[svPos + 4] = bY stepsVertices[svPos + 5] = fZ + stepWidth //B stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = aX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = bY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = aZ - stepWidth //A stepsVertices[svPos + 15] = aX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = aZ - stepWidth svPos += 18 } if (a.stairType === 'lShaped'||a.stairType === 'halfLanding' ||a.stairType === '2QuarterLanding') { // BACK //D stepsVertices[svPos] = stepsVertices[svPos + 9] = cX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = aZ //C stepsVertices[svPos + 3] = cX stepsVertices[svPos + 4] = bY stepsVertices[svPos + 5] = aZ //H stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = cX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = bY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = fZ //I stepsVertices[svPos + 15] = cX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = fZ svPos += 18 } // RIGHT //A stepsVertices[svPos] = stepsVertices[svPos + 9] = aX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = aZ //B stepsVertices[svPos + 3] = aX stepsVertices[svPos + 4] = bY stepsVertices[svPos + 5] = aZ //C stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = cX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = bY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = aZ //D stepsVertices[svPos + 15] = cX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = aZ svPos += 18 // LEFT //I stepsVertices[svPos] = stepsVertices[svPos + 9] = cX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = fZ //H stepsVertices[svPos + 3] = cX stepsVertices[svPos + 4] = bY stepsVertices[svPos + 5] = fZ //G stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = aX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = bY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = fZ //F stepsVertices[svPos + 15] = aX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = fZ svPos += 18 // BOTTOM //C stepsVertices[svPos] = stepsVertices[svPos + 9] = cX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = bY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = aZ //B stepsVertices[svPos + 3] = aX stepsVertices[svPos + 4] = bY stepsVertices[svPos + 5] = aZ //G stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = aX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = bY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = fZ //H stepsVertices[svPos + 15] = cX stepsVertices[svPos + 16] = bY stepsVertices[svPos + 17] = fZ svPos += 18 if (!a.treadHeight) { // TOP //A stepsVertices[svPos] = stepsVertices[svPos + 9] = aX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = aZ //D stepsVertices[svPos + 3] = cX stepsVertices[svPos + 4] = aY stepsVertices[svPos + 5] = aZ //I stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = cX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = aY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = fZ //F stepsVertices[svPos + 15] = aX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = fZ svPos += 18 } if (a.treadHeight > 0) { // O----R // P\---Q\ // \\ \\ // \K----N // L----M kX = aX kY = aY + a.treadHeight kZ = zCursor+ width lY = aY mX = aX + platformExt oZ = zCursor if (a.stairType === 'lShaped'||a.stairType === 'halfLanding' ||a.stairType === '2QuarterLanding') { // BACK //M treadVertices[tvPos] = treadVertices[tvPos + 9] = mX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = kZ //N treadVertices[tvPos + 3] = mX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = kZ //Q treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = mX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = oZ //R treadVertices[tvPos + 15] = mX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = oZ tvPos += 18 } // TOP //R treadVertices[tvPos] = treadVertices[tvPos + 9] = mX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = oZ //O treadVertices[tvPos + 3] = kX treadVertices[tvPos + 4] = kY treadVertices[tvPos + 5] = oZ //K treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = kX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = kY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = kZ //N treadVertices[tvPos + 15] = mX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = kZ tvPos += 18 // RIGHT //K treadVertices[tvPos] = treadVertices[tvPos + 9] = kX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = kZ //L treadVertices[tvPos + 3] = kX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = kZ //M treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = mX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = kZ //N treadVertices[tvPos + 15] = mX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = kZ tvPos += 18 // FRONT //O treadVertices[tvPos] = treadVertices[tvPos + 9] = kX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = oZ //P treadVertices[tvPos + 3] = kX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = oZ //L treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = kX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = kZ //K treadVertices[tvPos + 15] = kX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = kZ tvPos += 18 // LEFT //R treadVertices[tvPos] = treadVertices[tvPos + 9] = mX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = oZ //Q treadVertices[tvPos + 3] = mX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = oZ //P treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = kX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = oZ //O treadVertices[tvPos + 15] = kX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = oZ tvPos += 18 // Show Back and Bottom Face if Stair is not massive /* if (a.construction !== 0) { // BACK //N treadVertices[tvPos] = treadVertices[tvPos + 9] = mX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = kZ //M treadVertices[tvPos + 3] = mX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = kZ //Q treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = mX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = oZ //R treadVertices[tvPos + 15] = mX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = oZ tvPos += 18 // BOTTOM //M treadVertices[tvPos] = treadVertices[tvPos + 9] = mX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = lY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = kZ //L treadVertices[tvPos + 3] = kX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = kZ //P treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = kX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = oZ //Q treadVertices[tvPos + 15] = mX treadVertices[tvPos + 16] = lY treadVertices[tvPos + 17] = oZ tvPos += 18 } */ ve = stepsVertices.length te = treadVertices.length re = railingVertices.length if (angle) { var cosAngle = Math.cos(angle / 180 * Math.PI), sinAngle = Math.sin(angle / 180 * Math.PI) for (i=vs;i<ve-2; i = i + 3){ xRotate=stepsVertices[i]-offsetX stepsVertices[i+2]=stepsVertices[i+2]-offsetZ stepsVertices[i]=xRotate*cosAngle-stepsVertices[i+2]*sinAngle+offsetX stepsVertices[i+2]=stepsVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } for (i=ts;i<te-2; i = i + 3){ xRotate=treadVertices[i]-offsetX treadVertices[i+2]=treadVertices[i+2]-offsetZ treadVertices[i]=xRotate*cosAngle-treadVertices[i+2]*sinAngle+offsetX treadVertices[i+2]=treadVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } for (i=rs;i<re-2; i = i + 3){ xRotate=railingVertices[i]-offsetX railingVertices[i+2]=railingVertices[i+2]-offsetZ railingVertices[i]=xRotate*cosAngle-railingVertices[i+2]*sinAngle+offsetX railingVertices[i+2]=railingVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } } } } function _step(aX, aY, aZ, bY, cY, cX, cZ, eY, fX, fZ, hX, hZ) { // F----I // |\ |\ // G \ H \ // L\ A----D // J \| | // B C // K / // E ///// BASE // add extra face to create a watertight mesh var kY = bY - a.treadHeight if (aY >= a.h-calcRiser) { // BACK > LAST STEP //D stepsVertices[svPos] = stepsVertices[svPos + 9] = cX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = cZ //C stepsVertices[svPos + 3] = cX stepsVertices[svPos + 4] = cY stepsVertices[svPos + 5] = cZ //H stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = hX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = cY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = hZ //I stepsVertices[svPos + 15] = hX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = hZ svPos += 18 } if (!a.treadHeight) { // TOP //I stepsVertices[svPos] = stepsVertices[svPos + 9] = hX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = hZ //F stepsVertices[svPos + 3] = fX stepsVertices[svPos + 4] = aY stepsVertices[svPos + 5] = fZ //A stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = aX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = aY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = aZ //D stepsVertices[svPos + 15] = cX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = cZ svPos += 18 } // SIDE RIGHT //A stepsVertices[svPos] = stepsVertices[svPos + 9] = aX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = aZ //B stepsVertices[svPos + 3] = aX stepsVertices[svPos + 4] = bY stepsVertices[svPos + 5] = aZ //C stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = cX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = cY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = cZ //D stepsVertices[svPos + 15] = cX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = cZ svPos += 18 if (bY === kY) { //B stepsVertices[svPos] = aX stepsVertices[svPos + 1] = bY stepsVertices[svPos + 2] = aZ //E stepsVertices[svPos + 3] = aX stepsVertices[svPos + 4] = eY stepsVertices[svPos + 5] = aZ //C stepsVertices[svPos + 6] = cX stepsVertices[svPos + 7] = cY stepsVertices[svPos + 8] = cZ svPos += 9 } else { //C stepsVertices[svPos] = stepsVertices[svPos + 9] = cX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = cY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = cZ //B stepsVertices[svPos + 3] = aX stepsVertices[svPos + 4] = bY stepsVertices[svPos + 5] = aZ //K stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = aX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = kY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = aZ //E stepsVertices[svPos + 15] = aX stepsVertices[svPos + 16] = eY stepsVertices[svPos + 17] = aZ svPos += 18 } //Front //F stepsVertices[svPos] = stepsVertices[svPos + 9] = fX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = fZ //G stepsVertices[svPos + 3] = fX stepsVertices[svPos + 4] = bY stepsVertices[svPos + 5] = fZ //B stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = aX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = bY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = aZ //A stepsVertices[svPos + 15] = aX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = aZ svPos += 18 //SIDE LEFT //I stepsVertices[svPos] = stepsVertices[svPos + 9] = hX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = aY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = hZ //H stepsVertices[svPos + 3] = hX stepsVertices[svPos + 4] = cY stepsVertices[svPos + 5] = hZ //G stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = fX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = bY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = fZ //F stepsVertices[svPos + 15] = fX stepsVertices[svPos + 16] = aY stepsVertices[svPos + 17] = fZ svPos += 18 if (bY === kY) { //H stepsVertices[svPos] = hX stepsVertices[svPos + 1] = cY stepsVertices[svPos + 2] = hZ //J stepsVertices[svPos + 3] = fX stepsVertices[svPos + 4] = eY stepsVertices[svPos + 5] = fZ //G stepsVertices[svPos + 6] = fX stepsVertices[svPos + 7] = bY stepsVertices[svPos + 8] = fZ svPos += 9 } else { //H stepsVertices[svPos] = stepsVertices[svPos + 9] = hX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = cY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = hZ //J stepsVertices[svPos + 3] = fX stepsVertices[svPos + 4] = eY stepsVertices[svPos + 5] = fZ //L stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = fX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = kY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = fZ //G stepsVertices[svPos + 15] = fX stepsVertices[svPos + 16] = bY stepsVertices[svPos + 17] = fZ svPos += 18 } // BOTTOM //H stepsVertices[svPos] = stepsVertices[svPos + 9] = hX stepsVertices[svPos + 1] = stepsVertices[svPos + 10] = cY stepsVertices[svPos + 2] = stepsVertices[svPos + 11] = hZ //C stepsVertices[svPos + 3] = cX stepsVertices[svPos + 4] = cY stepsVertices[svPos + 5] = cZ //E stepsVertices[svPos + 6] = stepsVertices[svPos + 12] = aX stepsVertices[svPos + 7] = stepsVertices[svPos + 13] = eY stepsVertices[svPos + 8] = stepsVertices[svPos + 14] = aZ //J stepsVertices[svPos + 15] = fX stepsVertices[svPos + 16] = eY stepsVertices[svPos + 17] = fZ svPos += 18 if (a.treadHeight) { // TREAD // O----R // P\---Q\ // \\ \\ // \K----N // L----M kX = aX - nosing kY = aY + a.treadHeight kZ = aZ lY = aY mX = cX mZ = cZ oX = fX - nosing oZ = fZ qX = hX qZ = hZ if (kX!==oX&&kZ!==oZ) { var radAngle = Math.atan2(kZ - oZ, kX-oX); var degAngle = Math.round(radAngle * 180 / Math.PI * 100)/100; if (a.stairType === 'winder' || a.stairType === 'doubleWinder' ){ if (degAngle >= 135) { kX = aX kZ = aZ - nosing oX = fX oZ = fZ - nosing } if (degAngle <= 45 ) { //>= 45 && degAngle < 90) { kX = aX kZ = aZ + nosing oX = fX oZ = fZ + nosing } } else if (a.stairType === 'spiral') { kX = aX - nosing*Math.cos(radAngle-Math.PI/2) kZ = aZ - nosing*Math.sin(radAngle-Math.PI/2) oX = fX - nosing*Math.cos(radAngle-Math.PI/2) oZ = fZ - nosing*Math.sin(radAngle-Math.PI/2) } } if (aY >= a.h-calcRiser) { // BACK > LAST STEP //N treadVertices[tvPos] = treadVertices[tvPos + 9] = mX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = mZ //M treadVertices[tvPos + 3] = mX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = mZ //Q treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = qX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = qZ //R treadVertices[tvPos + 15] = qX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = qZ tvPos += 18 } // TOP //R treadVertices[tvPos] = treadVertices[tvPos + 9] = qX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = qZ //O treadVertices[tvPos + 3] = oX treadVertices[tvPos + 4] = kY treadVertices[tvPos + 5] = oZ //K treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = kX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = kY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = kZ //N treadVertices[tvPos + 15] = mX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = mZ tvPos += 18 // RIGHT //K treadVertices[tvPos] = treadVertices[tvPos + 9] = kX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = kZ //L treadVertices[tvPos + 3] = kX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = kZ //M treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = mX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = mZ //N treadVertices[tvPos + 15] = mX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = mZ tvPos += 18 // FRONT //O treadVertices[tvPos] = treadVertices[tvPos + 9] = oX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = oZ //P treadVertices[tvPos + 3] = oX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = oZ //L treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = kX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = kZ //K treadVertices[tvPos + 15] = kX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = kZ tvPos += 18 // LEFT //R treadVertices[tvPos] = treadVertices[tvPos + 9] = qX treadVertices[tvPos + 1] = treadVertices[tvPos + 10] = kY treadVertices[tvPos + 2] = treadVertices[tvPos + 11] = qZ //Q treadVertices[tvPos + 3] = qX treadVertices[tvPos + 4] = lY treadVertices[tvPos + 5] = qZ //P treadVertices[tvPos + 6] = treadVertices[tvPos + 12] = oX treadVertices[tvPos + 7] = treadVertices[tvPos + 13] = lY treadVertices[tvPos + 8] = treadVertices[tvPos + 14] = oZ //O treadVertices[tvPos + 15] = oX treadVertices[tvPos + 16] = kY treadVertices[tvPos + 17] = oZ tvPos += 18 } } function _winder(xCursor, yCursor, zCursor, stepNumber, angle, flip) { var vs, ve, ts, te, rs, re, xRotate, i, offsetX = xCursor, offsetZ = zCursor vs = stepsVertices.length ts = treadVertices.length rs = railingVertices.length var winderOffset = stairWell var treadWinderNum = stepNumber/2 var treadWinderMax = (stepWidth+winderOffset)/treadWinderNum var treadWinderMin = winderOffset/treadWinderNum var stepMin = 0 var stepMax = 0 // Railing adapted to stair direction if (!flip) { if (a.railing === 'left' || a.railing === 'both') _railing(xCursor, yCursor + calcRiser, zCursor + handrailThickness + 0.01, xCursor + treadWinderNum * treadWinderMax - 0.01, yCursor + treadWinderNum * calcRiser + calcRiser, zCursor + handrailThickness + 0.01, 0, true) if (a.railing === 'right' || a.railing === 'both') _railing(xCursor, yCursor + calcRiser, zCursor + stepWidth - 0.01, xCursor + treadWinderNum * treadWinderMin, yCursor + treadWinderNum * calcRiser + calcRiser, zCursor + stepWidth - 0.01, 0, true) } else { if (a.railing === 'left' || a.railing === 'both') _railing(xCursor, yCursor + calcRiser, zCursor + handrailThickness + 0.01, xCursor + treadWinderNum * treadWinderMin, yCursor + treadWinderNum * calcRiser + calcRiser, zCursor + handrailThickness + 0.01, 0, true) if (a.railing === 'right' || a.railing === 'both') _railing(xCursor, yCursor + calcRiser, zCursor + stepWidth - 0.01, xCursor + treadWinderNum * treadWinderMax - 0.01, yCursor + treadWinderNum * calcRiser + calcRiser, zCursor + stepWidth - 0.01, 0, true) } for (var c=0; c<treadWinderNum; c++){ // F----I // |\ |\ // G \ H \ // |\ A----D // J \| | // B C // | / // E aX = flip ? xCursor + stepMax : xCursor + stepMin aY = yCursor + calcRiser - a.treadHeight aZ = zCursor + stepWidth bY = yCursor cY = yCursor + calcRiser - riserExt cX = flip ? xCursor + stepMax + treadWinderMax : xCursor + stepMin + treadWinderMin cZ = aZ fX = flip ? xCursor + stepMin : xCursor + stepMax eY = yCursor - riserExt fZ = zCursor hX = flip ? xCursor + stepMin + treadWinderMin : xCursor + stepMax + treadWinderMax hZ = fZ _step(aX, aY, aZ, bY, cY, cX, cZ, eY, fX, fZ, hX, hZ) yCursor += calcRiser stepMin += treadWinderMin stepMax += treadWinderMax } xCursor += stepMin stepMin = 0 stepMax = 0 // Railing adapted to stair direction if (!flip) { if (a.railing === 'left'||a.railing === 'both') _railing(offsetX+treadWinderNum*treadWinderMax-handrailThickness-0.01, yCursor+calcRiser, zCursor+0.01, offsetX+treadWinderNum*treadWinderMax*2-handrailThickness-0.01, yCursor+treadWinderNum*calcRiser+calcRiser, zCursor+0.01, 90, true) if (a.railing === 'right'||a.railing === 'both') _railing(xCursor+0.01, yCursor+calcRiser, zCursor+stepWidth-0.01, xCursor+treadWinderNum*treadWinderMin+0.01, yCursor+treadWinderNum*calcRiser+calcRiser, zCursor+stepWidth-0.01, 90, true) } else { if (a.railing === 'left'||a.railing === 'both') _railing(xCursor+0.01, yCursor+calcRiser, zCursor+0.01, xCursor+treadWinderNum*treadWinderMin+0.01, yCursor+treadWinderNum*calcRiser+calcRiser, zCursor+0.01, -90, true) if (a.railing === 'right'||a.railing === 'both') _railing(offsetX+treadWinderNum*treadWinderMax-handrailThickness-0.01, yCursor+calcRiser, zCursor+stepWidth-0.01, offsetX+treadWinderNum*treadWinderMax*2-handrailThickness-0.01, yCursor+treadWinderNum*calcRiser+calcRiser, zCursor+stepWidth-0.01, -90, true) } for (var c=0; c<treadWinderNum; c++){ // F----I // |\ |\ // G \ H \ // |\ A----D // J \| | // B C // | / // E if (!flip) { aX = xCursor aY = yCursor + calcRiser - a.treadHeight aZ = zCursor + stepWidth + stepMin bY = yCursor cY = yCursor + calcRiser - riserExt cX = aX cZ = aZ + treadWinderMin eY = yCursor - riserExt fX = xCursor + stepWidth fZ = zCursor + stepMax hX = fX hZ = zCursor + stepMax + treadWinderMax } else { aX = xCursor + stepWidth aY = yCursor + calcRiser - a.treadHeight aZ = zCursor + stepWidth - stepMax bY = yCursor cY = yCursor + calcRiser - riserExt cX = aX cZ = aZ - treadWinderMax eY = yCursor - riserExt fX = xCursor fZ = zCursor - stepMin hX = fX hZ = fZ - treadWinderMin } _step(aX, aY, aZ, bY, cY, cX, cZ, eY, fX, fZ, hX, hZ) yCursor += calcRiser stepMin += treadWinderMin stepMax += treadWinderMax } ve = stepsVertices.length te = treadVertices.length re = railingVertices.length if (angle) { var cosAngle = Math.cos(angle / 180 * Math.PI), sinAngle = Math.sin(angle / 180 * Math.PI) for (i=vs;i<ve-2; i = i + 3){ xRotate=stepsVertices[i]-offsetX stepsVertices[i+2]=stepsVertices[i+2]-offsetZ stepsVertices[i]=xRotate*cosAngle-stepsVertices[i+2]*sinAngle+offsetX stepsVertices[i+2]=stepsVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } for (i=ts;i<te-2; i = i + 3){ xRotate=treadVertices[i]-offsetX treadVertices[i+2]=treadVertices[i+2]-offsetZ treadVertices[i]=xRotate*cosAngle-treadVertices[i+2]*sinAngle+offsetX treadVertices[i+2]=treadVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } for (i=rs;i<re-2; i = i + 3){ xRotate=railingVertices[i]-offsetX railingVertices[i+2]=railingVertices[i+2]-offsetZ railingVertices[i]=xRotate*cosAngle-railingVertices[i+2]*sinAngle+offsetX railingVertices[i+2]=railingVertices[i+2]*cosAngle+xRotate*sinAngle+offsetZ } } } function _spiralRun(xCursor, yCursor, zCursor, stepNumber, flip) { var innerRadius = stairWidth-stepWidth var stepAngle = tread / (innerRadius+stepWidth/2) var rotAngle = 0 var outerStepDist = Math.sqrt(Math.pow((Math.sin(rotAngle)*(innerRadius+stepWidth)-Math.sin(rotAngle+stepAngle)*(innerRadius+stepWidth)), 2)+Math.pow((Math.cos(rotAngle)*(innerRadius+stepWidth)-Math.cos(rotAngle+stepAngle)*(innerRadius+stepWidth)), 2)) var innerStepDist = Math.sqrt(Math.pow((Math.sin(rotAngle)*(innerRadius)-Math.sin(rotAngle+stepAngle)*(innerRadius)), 2)+Math.pow((Math.cos(rotAngle)*(innerRadius)-Math.cos(rotAngle+stepAngle)*(innerRadius)), 2)) if (!flip) { rotAngle = Math.PI stepAngle = -stepAngle zCursor = zCursor + stairWidth } for (var c=0; c<stepNumber; c++){ // F----I // |\ |\ // G \ H \ // |\ A----D // J \| | // B C // | / // E if (flip) { aX = xCursor + Math.sin(rotAngle) * (innerRadius + stepWidth) aY = yCursor + calcRiser - a.treadHeight aZ = zCursor + Math.cos(rotAngle) * (innerRadius + stepWidth) bY = yCursor cY = yCursor + calcRiser - riserExt cX = xCursor + Math.sin(rotAngle + stepAngle) * (innerRadius + stepWidth) cZ = zCursor + Math.cos(rotAngle + stepAngle) * (innerRadius + stepWidth) eY = yCursor - riserExt fX = xCursor + Math.sin(rotAngle) * (innerRadius) fZ = zCursor + Math.cos(rotAngle) * (innerRadius) hX = xCursor + Math.sin(rotAngle + stepAngle) * (innerRadius) hZ = zCursor + Math.cos(rotAngle + stepAngle) * (innerRadius) } else { aX = xCursor + Math.sin(rotAngle) * (innerRadius) aY = yCursor + calcRiser - a.treadHeight aZ = zCursor + Math.cos(rotAngle) * (innerRadius) bY = yCursor cY = yCursor + calcRiser - riserExt cX = xCursor + Math.sin(rotAngle + stepAngle) * (innerRadius) cZ = zCursor + Math.cos(rotAngle + stepAngle) * (innerRadius) eY = yCursor - riserExt fX = xCursor + Math.sin(rotAngle) * (innerRadius + stepWidth) fZ = zCursor + Math.cos(rotAngle) * (innerRadius + stepWidth) hX = xCursor + Math.sin(rotAngle + stepAngle) * (innerRadius + stepWidth) hZ = zCursor + Math.cos(rotAngle + stepAngle) * (innerRadius + stepWidth) } //var outerStepDist = Math.sqrt((aX-cX)*(aX-cX)+(aZ-cZ)*(aZ-cZ)) _step(aX, aY, aZ, bY, cY, cX, cZ, eY, fX, fZ, hX, hZ) var openEnd = c<stepNumber-1 var railingAngle = flip ? (rotAngle+stepAngle/2)/Math.PI*(-180) : (rotAngle+stepAngle/2)/Math.PI*(-180)+180 if (flip) { if (stepWidth < stairWidth) { if (a.railing === 'left' || a.railing === 'both') _railing(fX, yCursor + calcRiser, fZ, fX + innerStepDist, yCursor + calcRiser * 2, fZ, railingAngle, openEnd) } if (a.railing === 'right'||a.railing === 'both') _railing(aX, yCursor+calcRiser, aZ, aX+outerStepDist, y