1 /* 2 * Wall3D.js 3 * 4 * Sweet Home 3D, Copyright (c) 2024 Space Mushrooms <info@sweethome3d.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 // Requires scene3d.js 22 // Object3DBranch.js 23 // ModelManager.js 24 // TextureManager.js 25 26 27 /** 28 * Creates the 3D wall matching the given home <code>wall</code>. 29 * @param {Wall} wall 30 * @param {Home} home 31 * @param {UserPreferences} [preferences] 32 * @param {boolean} waitModelAndTextureLoadingEnd 33 * @constructor 34 * @extends Object3DBranch 35 * @author Emmanuel Puybaret 36 */ 37 function Wall3D(wall, home, preferences, waitModelAndTextureLoadingEnd) { 38 if (waitModelAndTextureLoadingEnd === undefined) { 39 // 3 parameters 40 waitModelAndTextureLoadingEnd = preferences; 41 preferences = null; 42 } 43 Object3DBranch.call(this, wall, home, preferences); 44 45 for (var i = 0; i < 8; i++) { 46 var wallSideGroup = new Group3D(); 47 wallSideGroup.addChild(this.createWallPartShape()); 48 this.addChild(wallSideGroup); 49 } 50 51 // Add selection node 52 var wallSelectionShape = new Shape3D(); 53 wallSelectionShape.setAppearance(this.getSelectionAppearance()); 54 wallSelectionShape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE); 55 wallSelectionShape.setPickable(false); 56 this.addChild(wallSelectionShape); 57 58 this.updateWallGeometry(waitModelAndTextureLoadingEnd); 59 this.updateWallAppearance(waitModelAndTextureLoadingEnd); 60 } 61 Wall3D.prototype = Object.create(Object3DBranch.prototype); 62 Wall3D.prototype.constructor = Wall3D; 63 64 Wall3D.LEVEL_ELEVATION_SHIFT = 0.1; 65 Wall3D.FULL_FACE_CUT_OUT_AREA = new java.awt.geom.Area(new java.awt.geom.Rectangle2D.Float(-0.5, 0.5, 1, 1)); 66 Wall3D.WALL_LEFT_SIDE = 0; 67 Wall3D.WALL_RIGHT_SIDE = 1; 68 69 Wall3D.rotatedModelsFrontAreas = []; 70 71 /** 72 * Returns a new wall part shape with no geometry and a default appearance with 73 * a white material. 74 * @return {Node3D} 75 * @private 76 */ 77 Wall3D.prototype.createWallPartShape = function() { 78 var wallShape = new Shape3D(); 79 wallShape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE); 80 var wallAppearance = new Appearance3D(); 81 wallShape.setAppearance(wallAppearance); 82 this.updateAppearanceMaterial(wallAppearance, Object3DBranch.DEFAULT_COLOR, Object3DBranch.DEFAULT_AMBIENT_COLOR, 0); 83 return wallShape; 84 } 85 86 Wall3D.prototype.update = function() { 87 this.updateWallGeometry(false); 88 this.updateWallAppearance(false); 89 } 90 91 /** 92 * Sets the 3D geometry of this wall shapes that matches its 2D geometry. 93 * @param {boolean} waitDoorOrWindowModelsLoadingEnd 94 * @private 95 */ 96 Wall3D.prototype.updateWallGeometry = function(waitDoorOrWindowModelsLoadingEnd) { 97 this.updateWallSideGeometry(Wall3D.WALL_LEFT_SIDE, waitDoorOrWindowModelsLoadingEnd); 98 this.updateWallSideGeometry(Wall3D.WALL_RIGHT_SIDE, waitDoorOrWindowModelsLoadingEnd); 99 this.setPickable(this.getHome().getEnvironment().getWallsAlpha() == 0); 100 101 var wallSelectionShape = this.getChild(8); 102 wallSelectionShape.addGeometry(this.createWallSelectionGeometry()); 103 if (wallSelectionShape.getGeometries().length > 1) { 104 wallSelectionShape.removeGeometry(0); 105 } 106 } 107 108 Wall3D.prototype.updateWallSideGeometry = function(wallSide, waitDoorOrWindowModelsLoadingEnd) { 109 var wall = this.getUserData(); 110 var wallTexture; 111 var baseboard; 112 if (wallSide === Wall3D.WALL_LEFT_SIDE) { 113 wallTexture = wall.getLeftSideTexture(); 114 baseboard = wall.getLeftSideBaseboard(); 115 } else { 116 wallTexture = wall.getRightSideTexture(); 117 baseboard = wall.getRightSideBaseboard(); 118 } 119 var wallSideGroups = [this.getChild(wallSide), 120 this.getChild(wallSide + 2), 121 this.getChild(wallSide + 4), 122 this.getChild(wallSide + 6)]; 123 var wallFilledShapes = new Array(wallSideGroups.length); 124 var currentGeometriesCounts = new Array(wallSideGroups.length); 125 for (var i = 0; i < wallSideGroups.length; i++) { 126 wallFilledShapes[i] = wallSideGroups[i].getChild(0); 127 currentGeometriesCounts[i] = wallFilledShapes[i].getGeometries().length; 128 } 129 if (wall.getLevel() == null || wall.getLevel().isViewableAndVisible()) { 130 var wallGeometries = [[], [], [], []]; 131 this.createWallGeometries(wallGeometries[0], wallGeometries[2], wallGeometries[3], wallSide, 132 null, wallTexture, waitDoorOrWindowModelsLoadingEnd); 133 if (baseboard != null) { 134 var baseboardTexture = baseboard.getTexture(); 135 if (baseboardTexture === null && baseboard.getColor() === null) { 136 baseboardTexture = wallTexture; 137 } 138 this.createWallGeometries(wallGeometries[1], wallGeometries[1], wallGeometries[1], wallSide, 139 baseboard, baseboardTexture, waitDoorOrWindowModelsLoadingEnd); 140 } 141 for (var i = 0; i < wallSideGroups.length; i++) { 142 for (var j = 0; j < wallGeometries[i].length; j++) { 143 var wallGeometry = wallGeometries[i][j]; 144 if (wallGeometry !== null) { 145 wallFilledShapes[i].addGeometry(wallGeometry); 146 } 147 } 148 } 149 } 150 for (var i = 0; i < wallSideGroups.length; i++) { 151 for (var j = currentGeometriesCounts[i] - 1; j >= 0; j--) { 152 wallFilledShapes[i].removeGeometry(j); 153 } 154 } 155 } 156 157 /** 158 * Creates <code>wall</code> or baseboard geometries computed with windows or doors 159 * that intersect wall. 160 * @param {Array} bottomGeometries 161 * @param {Array} sideGeometries 162 * @param {Array} topGeometries 163 * @param {number} wallSide 164 * @param {Baseboard} baseboard 165 * @param {HomeTexture} texture 166 * @param {boolean} waitDoorOrWindowModelsLoadingEnd 167 * @private 168 */ 169 Wall3D.prototype.createWallGeometries = function(bottomGeometries, sideGeometries, topGeometries, wallSide, 170 baseboard, texture, waitDoorOrWindowModelsLoadingEnd) { 171 var wall = this.getUserData(); 172 var wallShape = this.getShape(wall.getPoints()); 173 var wallSidePoints = this.getWallSidePoints(wallSide); 174 var wallSideShape = this.getShape(wallSidePoints); 175 var wallSideOrBaseboardPoints = baseboard == null 176 ? wallSidePoints 177 : this.getWallBaseboardPoints(wallSide); 178 var wallSideOrBaseboardShape = this.getShape(wallSideOrBaseboardPoints); 179 var wallSideOrBaseboardArea = new java.awt.geom.Area(wallSideOrBaseboardShape); 180 var textureReferencePoint = wallSide === Wall3D.WALL_LEFT_SIDE 181 ? wallSideOrBaseboardPoints[0].slice(0) 182 : wallSideOrBaseboardPoints[wallSideOrBaseboardPoints.length - 1].slice(0); 183 var wallElevation = this.getWallElevation(baseboard !== null); 184 var topElevationAtStart; 185 var topElevationAtEnd; 186 if (baseboard === null) { 187 topElevationAtStart = this.getWallTopElevationAtStart(); 188 topElevationAtEnd = this.getWallTopElevationAtEnd(); 189 } else { 190 topElevationAtStart = 191 topElevationAtEnd = this.getBaseboardTopElevation(baseboard); 192 } 193 var maxTopElevation = Math.max(topElevationAtStart, topElevationAtEnd); 194 195 var wallYawAngle = Math.atan2(wall.getYEnd() - wall.getYStart(), wall.getXEnd() - wall.getXStart()); 196 var cosWallYawAngle = Math.cos(wallYawAngle); 197 var sinWallYawAngle = Math.sin(wallYawAngle); 198 var wallXStartWithZeroYaw = cosWallYawAngle * wall.getXStart() + sinWallYawAngle * wall.getYStart(); 199 var wallXEndWithZeroYaw = cosWallYawAngle * wall.getXEnd() + sinWallYawAngle * wall.getYEnd(); 200 var arcExtent = wall.getArcExtent(); 201 var roundWall = arcExtent !== null && arcExtent !== 0; 202 var topLineAlpha; 203 var topLineBeta; 204 if (topElevationAtStart === topElevationAtEnd) { 205 topLineAlpha = 0; 206 topLineBeta = topElevationAtStart; 207 } else { 208 topLineAlpha = (topElevationAtEnd - topElevationAtStart) / (wallXEndWithZeroYaw - wallXStartWithZeroYaw); 209 topLineBeta = topElevationAtStart - topLineAlpha * wallXStartWithZeroYaw; 210 } 211 var windowIntersections = []; 212 var intersectingDoorOrWindows = []; 213 var visibleDoorsAndWindows = this.getVisibleDoorsAndWindows(this.getHome().getFurniture()); 214 for (var i = 0; i < visibleDoorsAndWindows.length; i++) { 215 var piece = visibleDoorsAndWindows[i]; 216 var pieceElevation = piece.getGroundElevation(); 217 if (pieceElevation + piece.getHeight() > wallElevation 218 && pieceElevation < maxTopElevation) { 219 var pieceArea = new java.awt.geom.Area(this.getShape(piece.getPoints())); 220 var intersectionArea = new java.awt.geom.Area(wallShape); 221 intersectionArea.intersect(pieceArea); 222 if (!intersectionArea.isEmpty()) { 223 var deeperPiece = null; 224 if (piece.isParallelToWall(wall)) { 225 if (baseboard !== null) { 226 // Increase piece depth to ensure baseboard will be cut even if the window is as thick as the wall 227 deeperPiece = piece.clone(); 228 deeperPiece.setDepthInPlan(deeperPiece.getDepth() + 2 * baseboard.getThickness()); 229 } 230 if (typeof HomeDoorOrWindow !== "undefined" 231 && piece instanceof HomeDoorOrWindow) { 232 if (piece.isWallCutOutOnBothSides()) { 233 if (deeperPiece === null) { 234 deeperPiece = piece.clone(); 235 } 236 // Increase piece depth to ensure the wall will be cut on both sides 237 deeperPiece.setDepthInPlan(deeperPiece.getDepth() + 4 * wall.getThickness()); 238 } 239 } 240 } 241 // Recompute intersection on wall side shape only 242 if (deeperPiece !== null) { 243 pieceArea = new java.awt.geom.Area(this.getShape(deeperPiece.getPoints())); 244 intersectionArea = new java.awt.geom.Area(wallSideOrBaseboardShape); 245 intersectionArea.intersect(pieceArea); 246 } else { 247 intersectionArea = new java.awt.geom.Area(wallSideShape); 248 intersectionArea.intersect(pieceArea); 249 } 250 if (!intersectionArea.isEmpty() 251 && (!wall.isTrapezoidal() 252 || pieceElevation < this.getMaxElevationAtWallIntersection(intersectionArea, cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta))) { 253 windowIntersections.push(new Wall3D.DoorOrWindowArea(intersectionArea, [piece])); 254 intersectingDoorOrWindows.push(piece); 255 wallSideOrBaseboardArea.subtract(pieceArea); 256 } 257 } 258 } 259 } 260 if (windowIntersections.length > 1) { 261 for (var windowIndex = 0; windowIndex < windowIntersections.length; windowIndex++) { 262 var windowIntersection = windowIntersections[windowIndex]; 263 var otherWindowIntersections = []; 264 var otherWindowIndex = 0; 265 for (var i = 0; i < windowIntersections.length; i++) { 266 var otherWindowIntersection = windowIntersections[i]; 267 if (windowIntersection.getArea().isEmpty()) { 268 break; 269 } else if (otherWindowIndex > windowIndex) { 270 var windowsIntersectionArea = new java.awt.geom.Area(otherWindowIntersection.getArea()); 271 windowsIntersectionArea.intersect(windowIntersection.getArea()); 272 if (!windowsIntersectionArea.isEmpty()) { 273 otherWindowIntersection.getArea().subtract(windowsIntersectionArea); 274 windowIntersection.getArea().subtract(windowsIntersectionArea); 275 var doorsOrWindows = (windowIntersection.getDoorsOrWindows().slice(0)); 276 doorsOrWindows.push.apply(doorsOrWindows, otherWindowIntersection.getDoorsOrWindows()); 277 otherWindowIntersections.push(new Wall3D.DoorOrWindowArea(windowsIntersectionArea, doorsOrWindows)); 278 } 279 } 280 otherWindowIndex++; 281 } 282 windowIntersections.push.apply(windowIntersections, otherWindowIntersections); 283 } 284 } 285 var points = []; 286 var previousPoint = null; 287 for (var it = wallSideOrBaseboardArea.getPathIterator(null); !it.isDone(); it.next()) { 288 var wallPoint = [0, 0]; 289 if (it.currentSegment(wallPoint) === java.awt.geom.PathIterator.SEG_CLOSE) { 290 if (points.length > 2) { 291 if (points[0][0] === points[points.length - 1][0] 292 && points[0][1] === points[points.length - 1][1]) { 293 points.splice(points.length - 1, 1); 294 } 295 if (points.length > 2) { 296 var wallPartPoints = points.slice(0); 297 sideGeometries.push(this.createVerticalPartGeometry(wall, wallPartPoints, wallElevation, 298 cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, baseboard, texture, 299 textureReferencePoint, wallSide)); 300 bottomGeometries.push(this.createHorizontalPartGeometry(wallPartPoints, wallElevation, true, roundWall)); 301 topGeometries.push(this.createTopPartGeometry(wallPartPoints, 302 cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, roundWall)); 303 } 304 } 305 points.length = 0; 306 previousPoint = null; 307 } else if (previousPoint === null 308 || wallPoint[0] !== previousPoint[0] 309 || wallPoint[1] !== previousPoint[1]) { 310 points.push(wallPoint); 311 previousPoint = wallPoint; 312 } 313 } 314 315 var level = wall.getLevel(); 316 previousPoint = null; 317 for (var index = 0; index < windowIntersections.length; index++) { 318 var windowIntersection = windowIntersections[index]; 319 if (!windowIntersection.getArea().isEmpty()) { 320 for (var it = windowIntersection.getArea().getPathIterator(null); !it.isDone(); it.next()) { 321 var wallPoint = [0, 0]; 322 if (it.currentSegment(wallPoint) === java.awt.geom.PathIterator.SEG_CLOSE) { 323 if (points[0][0] === points[points.length - 1][0] 324 && points[0][1] === points[points.length - 1][1]) { 325 points.splice(points.length - 1, 1); 326 } 327 328 if (points.length > 2) { 329 var wallPartPoints = points.slice(0); 330 var doorsOrWindows = windowIntersection.getDoorsOrWindows(); 331 if (doorsOrWindows.length > 1) { 332 doorsOrWindows.sort(function(piece1, piece2) { 333 var piece1Elevation = piece1.getGroundElevation(); 334 var piece2Elevation = piece2.getGroundElevation(); 335 if (piece1Elevation < piece2Elevation) { 336 return -1; 337 } else if (piece1Elevation > piece2Elevation) { 338 return 1; 339 } else { 340 return 0; 341 } 342 }); 343 } 344 var lowestDoorOrWindow = doorsOrWindows[0]; 345 var lowestDoorOrWindowElevation = lowestDoorOrWindow.getGroundElevation(); 346 if (lowestDoorOrWindowElevation > wallElevation) { 347 if (level != null 348 && level.getElevation() !== wallElevation 349 && lowestDoorOrWindow.getElevation() < Wall3D.LEVEL_ELEVATION_SHIFT) { 350 lowestDoorOrWindowElevation -= Wall3D.LEVEL_ELEVATION_SHIFT; 351 } 352 sideGeometries.push(this.createVerticalPartGeometry(wall, wallPartPoints, wallElevation, 353 cosWallYawAngle, sinWallYawAngle, 0, lowestDoorOrWindowElevation, baseboard, texture, 354 textureReferencePoint, wallSide)); 355 bottomGeometries.push(this.createHorizontalPartGeometry(wallPartPoints, wallElevation, true, roundWall)); 356 sideGeometries.push(this.createHorizontalPartGeometry(wallPartPoints, 357 lowestDoorOrWindowElevation, false, roundWall)); 358 } 359 for (var i = 0; i < doorsOrWindows.length - 1;) { 360 var lowerDoorOrWindow = doorsOrWindows[i]; 361 var lowerDoorOrWindowElevation = lowerDoorOrWindow.getGroundElevation(); 362 var higherDoorOrWindow = doorsOrWindows[++i]; 363 var higherDoorOrWindowElevation = higherDoorOrWindow.getGroundElevation(); 364 while ((lowerDoorOrWindowElevation + lowerDoorOrWindow.getHeight() >= higherDoorOrWindowElevation + higherDoorOrWindow.getHeight() 365 && ++i < doorsOrWindows.length)) { 366 higherDoorOrWindow = doorsOrWindows[i]; 367 } 368 if (i < doorsOrWindows.length 369 && lowerDoorOrWindowElevation + lowerDoorOrWindow.getHeight() < higherDoorOrWindowElevation) { 370 sideGeometries.push(this.createVerticalPartGeometry(wall, wallPartPoints, lowerDoorOrWindowElevation + lowerDoorOrWindow.getHeight(), 371 cosWallYawAngle, sinWallYawAngle, 0, higherDoorOrWindowElevation, baseboard, texture, textureReferencePoint, wallSide)); 372 sideGeometries.push(this.createHorizontalPartGeometry(wallPartPoints, 373 lowerDoorOrWindowElevation + lowerDoorOrWindow.getHeight(), true, roundWall)); 374 sideGeometries.push(this.createHorizontalPartGeometry(wallPartPoints, higherDoorOrWindowElevation, false, roundWall)); 375 } 376 } 377 var highestDoorOrWindow = doorsOrWindows[doorsOrWindows.length - 1]; 378 var highestDoorOrWindowElevation = highestDoorOrWindow.getGroundElevation(); 379 for (var i = doorsOrWindows.length - 2; i >= 0; i--) { 380 var doorOrWindow = doorsOrWindows[i]; 381 if (doorOrWindow.getGroundElevation() + doorOrWindow.getHeight() > highestDoorOrWindowElevation + highestDoorOrWindow.getHeight()) { 382 highestDoorOrWindow = doorOrWindow; 383 } 384 } 385 var doorOrWindowTop = highestDoorOrWindowElevation + highestDoorOrWindow.getHeight(); 386 var generateGeometry = true; 387 for (var i = 0; i < wallPartPoints.length; i++) { 388 var xTopPointWithZeroYaw = cosWallYawAngle * wallPartPoints[i][0] + sinWallYawAngle * wallPartPoints[i][1]; 389 var topPointWithZeroYawElevation = topLineAlpha * xTopPointWithZeroYaw + topLineBeta; 390 if (doorOrWindowTop > topPointWithZeroYawElevation) { 391 if (topLineAlpha === 0 || roundWall) { 392 generateGeometry = false; 393 break; 394 } 395 var translation = (doorOrWindowTop - topPointWithZeroYawElevation) / topLineAlpha; 396 wallPartPoints[i][0] += (translation * cosWallYawAngle); 397 wallPartPoints[i][1] += (translation * sinWallYawAngle); 398 } 399 } 400 if (generateGeometry) { 401 sideGeometries.push(this.createVerticalPartGeometry(wall, wallPartPoints, doorOrWindowTop, 402 cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, baseboard, texture, textureReferencePoint, wallSide)); 403 sideGeometries.push(this.createHorizontalPartGeometry(wallPartPoints, doorOrWindowTop, true, roundWall)); 404 topGeometries.push(this.createTopPartGeometry(wallPartPoints, 405 cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, roundWall)); 406 } 407 } 408 points.length = 0; 409 previousPoint = null; 410 } else if (previousPoint == null 411 || wallPoint[0] !== previousPoint[0] 412 || wallPoint[1] !== previousPoint[1]) { 413 points.push(wallPoint); 414 previousPoint = wallPoint; 415 } 416 } 417 } 418 } 419 420 if (!roundWall && intersectingDoorOrWindows.length > 0) { 421 var epsilon = Math.PI / 720; 422 var missingModels = []; 423 for (var i = 0; i < intersectingDoorOrWindows.length; i++) { 424 var piece = intersectingDoorOrWindows[i]; 425 if (typeof HomeDoorOrWindow !== "undefined" 426 && piece instanceof HomeDoorOrWindow 427 && (PieceOfFurniture.DEFAULT_CUT_OUT_SHAPE != piece.getCutOutShape() 428 || piece.getWallWidth() !== 1 429 || piece.getWallLeft() !== 0 430 || piece.getWallHeight() !== 1 431 || piece.getWallTop() !== 0)) { 432 var angleDifference = Math.abs(wallYawAngle - piece.getAngle()) % (2 * Math.PI); 433 if (angleDifference < epsilon 434 || angleDifference > 2 * Math.PI - epsilon 435 || Math.abs(angleDifference - Math.PI) < epsilon) { 436 var frontOrBackSide = Math.abs(angleDifference - Math.PI) < epsilon ? 1 : -1; 437 var rotatedModelFrontArea = Wall3D.getRotatedModelFrontArea(piece); 438 if (rotatedModelFrontArea !== null 439 && (missingModels.length === 0 || !waitDoorOrWindowModelsLoadingEnd)) { 440 this.createGeometriesSurroundingDoorOrWindow(piece, rotatedModelFrontArea, frontOrBackSide, 441 wall, sideGeometries, topGeometries, 442 wallSideOrBaseboardPoints, wallElevation, cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, 443 texture, textureReferencePoint, wallSide); 444 } else { 445 missingModels.push(piece); 446 } 447 } 448 } 449 } 450 if (missingModels.length > 0) { 451 var modelManager = ModelManager.getInstance(); 452 missingModels = missingModels.slice(0); 453 var wall3d = this; 454 for (var i = 0; i < missingModels.length; i++) { 455 var modelObserver = { 456 doorOrWindow : missingModels[i], 457 modelUpdated : function(modelRoot) { 458 var rotatedModelFrontArea = Wall3D.getRotatedModelFrontArea(this.doorOrWindow); 459 var frontArea; 460 if (rotatedModelFrontArea === null) { 461 var rotation = new TransformGroup3D(modelManager.getRotationTransformation(this.doorOrWindow.getModelRotation())); 462 rotation.addChild(modelRoot); 463 frontArea = modelManager.getFrontArea(this.doorOrWindow.getCutOutShape(), rotation); 464 Wall3D.rotatedModelsFrontAreas.push({ 465 model : this.doorOrWindow.getModel(), 466 modelRotation : this.doorOrWindow.getModelRotation(), 467 cutOutShape : this.doorOrWindow.getCutOutShape(), 468 frontArea : frontArea}); 469 } 470 471 var angleDifference = Math.abs(wallYawAngle - this.doorOrWindow.getAngle()) % (2 * Math.PI); 472 var frontOrBackSide = Math.abs(angleDifference - Math.PI) < epsilon ? 1 : -1; 473 if (waitDoorOrWindowModelsLoadingEnd) { 474 wall3d.createGeometriesSurroundingDoorOrWindow(this.doorOrWindow, frontArea, frontOrBackSide, 475 wall, sideGeometries, topGeometries, wallSideOrBaseboardPoints, wallElevation, cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, 476 texture, textureReferencePoint, wallSide); 477 } else { 478 missingModels.splice(missingModels.indexOf(this.doorOrWindow), 1); 479 if (missingModels.length === 0 480 && this.baseboard == null) { 481 setTimeout(function() { 482 wall3d.updateWallSideGeometry(wallSide, waitDoorOrWindowModelsLoadingEnd); 483 }, 0); 484 } 485 } 486 }, 487 modelError : function(ex) { 488 if (Wall3D.getRotatedModelFrontArea(this.doorOrWindow) === null) { 489 Wall3D.rotatedModelsFrontAreas.push({ 490 model : this.doorOrWindow.getModel(), 491 modelRotation : this.doorOrWindow.getModelRotation(), 492 cutOutShape : this.doorOrWindow.getCutOutShape(), 493 frontArea : Wall3D.FULL_FACE_CUT_OUT_AREA}); 494 } 495 if (!waitDoorOrWindowModelsLoadingEnd) { 496 missingModels.splice(missingModels.indexOf(this.doorOrWindow), 1); 497 } 498 } 499 }; 500 modelManager.loadModel(missingModels[i].getModel(), waitDoorOrWindowModelsLoadingEnd, modelObserver); 501 } 502 } 503 } 504 } 505 506 /** 507 * Returns the front area of the given piece if already computed. 508 * @private 509 */ 510 Wall3D.getRotatedModelFrontArea = function(piece) { 511 var rotatedModelFrontArea = null; 512 for (var j = 0; j < Wall3D.rotatedModelsFrontAreas.length; j++) { 513 if (Wall3D.rotatedModelsFrontAreas [j].model.equals(piece.getModel()) 514 && Object3DBranch.areModelRotationsEqual(Wall3D.rotatedModelsFrontAreas [j].modelRotation, piece.getModelRotation()) 515 && Wall3D.rotatedModelsFrontAreas [j].cutOutShape == piece.getCutOutShape()) { 516 return Wall3D.rotatedModelsFrontAreas [j].frontArea; 517 } 518 } 519 return null; 520 } 521 522 /** 523 * Returns all the visible doors and windows in the given <code>furniture</code>. 524 * @param {Array} furniture 525 * @return {Array} 526 * @private 527 */ 528 Wall3D.prototype.getVisibleDoorsAndWindows = function(furniture) { 529 var visibleDoorsAndWindows = []; 530 for (var i = 0; i < furniture.length; i++) { 531 var piece = furniture[i]; 532 if (piece.isVisible() 533 && (piece.getLevel() == null 534 || piece.getLevel().isViewableAndVisible())) { 535 if (piece instanceof HomeFurnitureGroup) { 536 visibleDoorsAndWindows.push.apply(visibleDoorsAndWindows, this.getVisibleDoorsAndWindows(piece.getFurniture())); 537 } else if (piece.isDoorOrWindow()) { 538 visibleDoorsAndWindows.push(piece); 539 } 540 } 541 } 542 return visibleDoorsAndWindows; 543 } 544 545 /** 546 * Returns the points of one of the side of this wall. 547 * @param {number} wallSide 548 * @return {Array} 549 * @private 550 */ 551 Wall3D.prototype.getWallSidePoints = function(wallSide) { 552 var wall = this.getUserData(); 553 var wallPoints = wall.getPoints(); 554 555 if (wallSide === Wall3D.WALL_LEFT_SIDE) { 556 for (var i = (wallPoints.length / 2 | 0); i < wallPoints.length; i++) { 557 wallPoints[i][0] = (wallPoints[i][0] + wallPoints[wallPoints.length - i - 1][0]) / 2; 558 wallPoints[i][1] = (wallPoints[i][1] + wallPoints[wallPoints.length - i - 1][1]) / 2; 559 } 560 } else { 561 for (var i = 0, n = (wallPoints.length / 2 | 0); i < n; i++) { 562 wallPoints[i][0] = (wallPoints[i][0] + wallPoints[wallPoints.length - i - 1][0]) / 2; 563 wallPoints[i][1] = (wallPoints[i][1] + wallPoints[wallPoints.length - i - 1][1]) / 2; 564 } 565 } 566 return wallPoints; 567 } 568 569 /** 570 * Returns the points of one of the baseboard of this wall. 571 * @param {number} wallSide 572 * @return {Array} 573 * @private 574 */ 575 Wall3D.prototype.getWallBaseboardPoints = function(wallSide) { 576 var wall = this.getUserData(); 577 var wallPointsIncludingBaseboards = wall.getPoints$boolean(true); 578 var wallPoints = wall.getPoints(); 579 580 if (wallSide === Wall3D.WALL_LEFT_SIDE) { 581 for (var i = Math.floor(wallPointsIncludingBaseboards.length / 2); i < wallPointsIncludingBaseboards.length; i++) { 582 wallPointsIncludingBaseboards[i] = wallPoints[wallPoints.length - i - 1]; 583 } 584 } else { 585 for (var i = 0, n = Math.floor(wallPoints.length / 2); i < n; i++) { 586 wallPointsIncludingBaseboards[i] = wallPoints[wallPoints.length - i - 1]; 587 } 588 } 589 return wallPointsIncludingBaseboards; 590 } 591 592 /** 593 * Returns the vertical rectangles that join each point of <code>points</code> 594 * and spread from <code>minElevation</code> to a top line (y = ax + b) described by <code>topLineAlpha</code> 595 * and <code>topLineBeta</code> factors in a vertical plan that is rotated around 596 * vertical axis matching <code>cosWallYawAngle</code> and <code>sinWallYawAngle</code>. 597 * @param {Wall} wall 598 * @param {Array} points 599 * @param {number} minElevation 600 * @param {number} cosWallYawAngle 601 * @param {number} sinWallYawAngle 602 * @param {number} topLineAlpha 603 * @param {number} topLineBeta 604 * @param {Baseboard} baseboard 605 * @param {HomeTexture} texture 606 * @param {Array} textureReferencePoint 607 * @param {number} wallSide 608 * @return {IndexedGeometryArray3D} 609 * @private 610 */ 611 Wall3D.prototype.createVerticalPartGeometry = function(wall, points, minElevation, 612 cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, 613 baseboard, texture, textureReferencePoint, wallSide) { 614 var subpartSize = this.getHome().getEnvironment().getSubpartSizeUnderLight(); 615 var arcExtent = wall.getArcExtent(); 616 if ((arcExtent === null || arcExtent === 0) && subpartSize > 0) { 617 var pointsList = []; 618 pointsList.push(points[0]); 619 for (var i = 1; i < points.length; i++) { 620 var distance = java.awt.geom.Point2D.distance(points[i - 1][0], points[i - 1][1], points[i][0], points[i][1]) - subpartSize / 2; 621 var angle = Math.atan2(points[i][1] - points[i - 1][1], points[i][0] - points[i - 1][0]); 622 var cosAngle = Math.cos(angle); 623 var sinAngle = Math.sin(angle); 624 for (var d = 0; d < distance; d += subpartSize) { 625 pointsList.push([(points[i - 1][0] + d * cosAngle), (points[i - 1][1] + d * sinAngle)]); 626 } 627 pointsList.push(points[i]); 628 } 629 points = pointsList.slice(0); 630 } 631 632 var bottom = new Array(points.length); 633 var top = new Array(points.length); 634 var pointUCoordinates = new Array(points.length); 635 var xStart = wall.getXStart(); 636 var yStart = wall.getYStart(); 637 var xEnd = wall.getXEnd(); 638 var yEnd = wall.getYEnd(); 639 var arcCircleCenter = null; 640 var arcCircleRadius = 0; 641 var referencePointAngle = 0; 642 if (arcExtent !== null && arcExtent !== 0) { 643 arcCircleCenter = [wall.getXArcCircleCenter(), wall.getYArcCircleCenter()]; 644 arcCircleRadius = java.awt.geom.Point2D.distance(arcCircleCenter[0], arcCircleCenter[1], xStart, yStart); 645 referencePointAngle = Math.fround(Math.atan2(textureReferencePoint[1] - arcCircleCenter[1], textureReferencePoint[0] - arcCircleCenter[0])); 646 } 647 for (var i = 0; i < points.length; i++) { 648 bottom[i] = vec3.fromValues(points[i][0], minElevation, points[i][1]); 649 var topY = this.getWallPointElevation(points[i][0], points[i][1], cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta); 650 top[i] = vec3.fromValues(points[i][0], topY, points[i][1]); 651 } 652 var distanceSqToWallMiddle = new Array(points.length); 653 for (var i = 0; i < points.length; i++) { 654 if (arcCircleCenter === null) { 655 distanceSqToWallMiddle[i] = java.awt.geom.Line2D.ptLineDistSq(xStart, yStart, xEnd, yEnd, bottom[i][0], bottom[i][2]); 656 } else { 657 distanceSqToWallMiddle[i] = arcCircleRadius - java.awt.geom.Point2D.distance(arcCircleCenter[0], arcCircleCenter[1], bottom[i][0], bottom[i][2]); 658 distanceSqToWallMiddle[i] *= distanceSqToWallMiddle[i]; 659 } 660 } 661 var rectanglesCount = points.length; 662 var usedRectangle = new Array(points.length); 663 if (baseboard === null) { 664 for (var i = 0; i < points.length - 1; i++) { 665 usedRectangle[i] = distanceSqToWallMiddle[i] > 0.001 666 || distanceSqToWallMiddle[i + 1] > 0.001; 667 if (!usedRectangle[i]) { 668 rectanglesCount--; 669 } 670 } 671 usedRectangle[usedRectangle.length - 1] = distanceSqToWallMiddle[0] > 0.001 672 || distanceSqToWallMiddle[points.length - 1] > 0.001; 673 if (!usedRectangle[usedRectangle.length - 1]) { 674 rectanglesCount--; 675 } 676 if (rectanglesCount === 0) { 677 return null; 678 } 679 } else { 680 for (var i = 0; i < usedRectangle.length; i++) { 681 usedRectangle [i] = true; 682 } 683 } 684 685 var coords = []; 686 for (var index = 0; index < points.length; index++) { 687 if (usedRectangle[index]) { 688 var y = minElevation; 689 var point1 = bottom[index]; 690 var nextIndex = (index + 1) % points.length; 691 var point2 = bottom[nextIndex]; 692 if (subpartSize > 0) { 693 for (var yMax = Math.min(top[index][1], top[nextIndex][1]) - subpartSize / 2; y < yMax; y += subpartSize) { 694 coords.push(point1); 695 coords.push(point2); 696 point1 = vec3.fromValues(bottom[index][0], y, bottom[index][2]); 697 point2 = vec3.fromValues(bottom[nextIndex][0], y, bottom[nextIndex][2]); 698 coords.push(point2); 699 coords.push(point1); 700 } 701 } 702 coords.push(point1); 703 coords.push(point2); 704 coords.push(top[nextIndex]); 705 coords.push(top[index]); 706 } 707 } 708 709 var geometryInfo = new GeometryInfo3D(GeometryInfo3D.QUAD_ARRAY); 710 geometryInfo.setCoordinates(coords.slice(0)); 711 712 if (texture !== null) { 713 var halfThicknessSq; 714 if (baseboard !== null) { 715 halfThicknessSq = wall.getThickness() / 2 + baseboard.getThickness(); 716 halfThicknessSq *= halfThicknessSq; 717 } else { 718 halfThicknessSq = (wall.getThickness() * wall.getThickness()) / 4; 719 } 720 var textureCoords = new Array(coords.length); 721 var firstTextureCoords = vec2.fromValues(0, minElevation); 722 var j = 0; 723 var epsilon = arcCircleCenter === null 724 ? wall.getThickness() / 10000.0 725 : halfThicknessSq / 4; 726 for (var index = 0; index < points.length; index++) { 727 if (usedRectangle[index]) { 728 var nextIndex = (index + 1) % points.length; 729 var textureCoords1; 730 var textureCoords2; 731 if (Math.abs(distanceSqToWallMiddle[index] - halfThicknessSq) < epsilon 732 && Math.abs(distanceSqToWallMiddle[nextIndex] - halfThicknessSq) < epsilon) { 733 var firstHorizontalTextureCoords; 734 var secondHorizontalTextureCoords; 735 if (arcCircleCenter === null) { 736 firstHorizontalTextureCoords = java.awt.geom.Point2D.distance(textureReferencePoint[0], textureReferencePoint[1], 737 points[index][0], points[index][1]); 738 secondHorizontalTextureCoords = java.awt.geom.Point2D.distance(textureReferencePoint[0], textureReferencePoint[1], 739 points[nextIndex][0], points[nextIndex][1]); 740 } else { 741 if (pointUCoordinates[index] === undefined) { 742 var pointAngle = Math.fround(Math.atan2(points[index][1] - arcCircleCenter[1], points[index][0] - arcCircleCenter[0])); 743 pointAngle = this.adjustAngleOnReferencePointAngle(pointAngle, referencePointAngle, arcExtent); 744 pointUCoordinates[index] = (pointAngle - referencePointAngle) * arcCircleRadius; 745 } 746 if (pointUCoordinates[nextIndex] === undefined) { 747 var pointAngle = Math.fround(Math.atan2(points[nextIndex][1] - arcCircleCenter[1], points[nextIndex][0] - arcCircleCenter[0])); 748 pointAngle = this.adjustAngleOnReferencePointAngle(pointAngle, referencePointAngle, arcExtent); 749 pointUCoordinates[nextIndex] = (pointAngle - referencePointAngle) * arcCircleRadius; 750 } 751 firstHorizontalTextureCoords = pointUCoordinates[index]; 752 secondHorizontalTextureCoords = pointUCoordinates[nextIndex]; 753 } 754 if (wallSide === Wall3D.WALL_LEFT_SIDE && texture.isLeftToRightOriented()) { 755 firstHorizontalTextureCoords = -firstHorizontalTextureCoords; 756 secondHorizontalTextureCoords = -secondHorizontalTextureCoords; 757 } 758 759 textureCoords1 = vec2.fromValues(firstHorizontalTextureCoords, minElevation); 760 textureCoords2 = vec2.fromValues(secondHorizontalTextureCoords, minElevation); 761 } else { 762 textureCoords1 = firstTextureCoords; 763 var horizontalTextureCoords = java.awt.geom.Point2D.distance(points[index][0], points[index][1], points[nextIndex][0], 764 points[nextIndex][1]); 765 textureCoords2 = vec2.fromValues(horizontalTextureCoords, minElevation); 766 } 767 768 if (subpartSize > 0) { 769 var y = minElevation; 770 for (var yMax = Math.min(top[index][1], top[nextIndex][1]) - subpartSize / 2; y < yMax; y += subpartSize) { 771 textureCoords[j++] = textureCoords1; 772 textureCoords[j++] = textureCoords2; 773 textureCoords1 = vec2.fromValues(textureCoords1[0], y); 774 textureCoords2 = vec2.fromValues(textureCoords2[0], y); 775 textureCoords[j++] = textureCoords2; 776 textureCoords[j++] = textureCoords1; 777 } 778 } 779 textureCoords[j++] = textureCoords1; 780 textureCoords[j++] = textureCoords2; 781 textureCoords[j++] = vec2.fromValues(textureCoords2[0], top[nextIndex][1]); 782 textureCoords[j++] = vec2.fromValues(textureCoords1[0], top[index][1]); 783 } 784 } 785 geometryInfo.setTextureCoordinates(textureCoords); 786 } 787 if (arcCircleCenter === null) { 788 geometryInfo.setCreaseAngle(0); 789 } 790 geometryInfo.setGeneratedNormals(true); 791 return geometryInfo.getIndexedGeometryArray(); 792 } 793 794 /** 795 * Returns the maximum wall elevation of each point of the given intersection. 796 * @param {Area} pieceWallIntersection 797 * @param {number} cosWallYawAngle 798 * @param {number} sinWallYawAngle 799 * @param {number} topLineAlpha 800 * @param {number} topLineBeta 801 * @return {number} 802 * @private 803 */ 804 Wall3D.prototype.getMaxElevationAtWallIntersection = function(pieceWallIntersection, cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta) { 805 var maxElevation = -Infinity; 806 for (var it = pieceWallIntersection.getPathIterator(null); !it.isDone(); it.next()) { 807 var wallPoint = [0, 0]; 808 if (it.currentSegment(wallPoint) !== java.awt.geom.PathIterator.SEG_CLOSE) { 809 maxElevation = Math.max(maxElevation, this.getWallPointElevation(wallPoint [0], wallPoint [1], 810 cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta)); 811 } 812 } 813 return maxElevation; 814 } 815 816 /** 817 * Returns the elevation of the wall at the given point. 818 * @param {number} xWallPoint 819 * @param {number} yWallPoint 820 * @param {number} cosWallYawAngle 821 * @param {number} sinWallYawAngle 822 * @param {number} topLineAlpha 823 * @param {number} topLineBeta 824 * @return {number} 825 * @private 826 */ 827 Wall3D.prototype.getWallPointElevation = function(xWallPoint, yWallPoint, cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta) { 828 var xTopPointWithZeroYaw = cosWallYawAngle * xWallPoint + sinWallYawAngle * yWallPoint; 829 return (topLineAlpha * xTopPointWithZeroYaw + topLineBeta); 830 } 831 832 /** 833 * Returns <code>pointAngle</code> plus or minus 2 PI to ensure <code>pointAngle</code> value 834 * will be greater or lower than <code>referencePointAngle</code> depending on <code>arcExtent</code> direction. 835 * @param {number} pointAngle 836 * @param {number} referencePointAngle 837 * @param {number} arcExtent 838 * @return {number} 839 * @private 840 */ 841 Wall3D.prototype.adjustAngleOnReferencePointAngle = function(pointAngle, referencePointAngle, arcExtent) { 842 if (arcExtent > 0) { 843 if ((referencePointAngle > 0 844 && (pointAngle < 0 845 || pointAngle < referencePointAngle)) 846 || (referencePointAngle < 0 847 && pointAngle < referencePointAngle)) { 848 pointAngle += 2 * Math.PI; 849 } 850 } else { 851 if ((referencePointAngle < 0 852 && (pointAngle > 0 853 || referencePointAngle < pointAngle)) 854 || (referencePointAngle > 0 855 && referencePointAngle < pointAngle)) { 856 pointAngle -= 2 * Math.PI; 857 } 858 } 859 return pointAngle; 860 } 861 862 /** 863 * Returns the geometry of an horizontal part of a wall or a baseboard at <code>y</code>. 864 * @param {Array} points 865 * @param {number} y 866 * @param {boolean} reverseOrder 867 * @param {boolean} roundWall 868 * @return {IndexedGeometryArray3D} 869 * @private 870 */ 871 Wall3D.prototype.createHorizontalPartGeometry = function(points, y, reverseOrder, roundWall) { 872 var coords = new Array(points.length); 873 for (var i = 0; i < points.length; i++) { 874 coords[i] = vec3.fromValues(points[i][0], y, points[i][1]); 875 } 876 var geometryInfo = new GeometryInfo3D(GeometryInfo3D.POLYGON_ARRAY); 877 geometryInfo.setCoordinates(reverseOrder ? coords.reverse() : coords); 878 geometryInfo.setStripCounts([coords.length]); 879 if (roundWall) { 880 geometryInfo.setCreaseAngle(0); 881 } 882 geometryInfo.setGeneratedNormals(true); 883 return geometryInfo.getIndexedGeometryArray(); 884 } 885 886 /** 887 * Returns the geometry of the top part of a wall or a baseboard. 888 * @param {Array} points 889 * @param {number} cosWallYawAngle 890 * @param {number} sinWallYawAngle 891 * @param {number} topLineAlpha 892 * @param {number} topLineBeta 893 * @param {boolean} roundWall 894 * @return {IndexedGeometryArray3D} 895 * @private 896 */ 897 Wall3D.prototype.createTopPartGeometry = function(points, cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, roundWall) { 898 var coords = new Array(points.length); 899 for (var i = 0; i < points.length; i++) { 900 var xTopPointWithZeroYaw = cosWallYawAngle * points[i][0] + sinWallYawAngle * points[i][1]; 901 var topY = (topLineAlpha * xTopPointWithZeroYaw + topLineBeta); 902 coords[i] = vec3.fromValues(points[i][0], topY, points[i][1]); 903 } 904 var geometryInfo = new GeometryInfo3D(GeometryInfo3D.POLYGON_ARRAY); 905 geometryInfo.setCoordinates(coords); 906 geometryInfo.setStripCounts([coords.length]); 907 if (roundWall) { 908 geometryInfo.setCreaseAngle(0); 909 } 910 geometryInfo.setGeneratedNormals(true); 911 return geometryInfo.getIndexedGeometryArray(); 912 } 913 914 /** 915 * Creates the geometry surrounding the given non rectangular door or window. 916 * @param {HomeDoorOrWindow} doorOrWindow 917 * @param {Area} doorOrWindowFrontArea 918 * @param {number} frontOrBackSide 919 * @param {Wall} wall 920 * @param {Array} wallGeometries 921 * @param {Array} wallTopGeometries 922 * @param {Array} wallSidePoints 923 * @param {number} wallElevation 924 * @param {number} cosWallYawAngle 925 * @param {number} sinWallYawAngle 926 * @param {number} topLineAlpha 927 * @param {number} topLineBeta 928 * @param {HomeTexture} texture 929 * @param {Array} textureReferencePoint 930 * @param {number} wallSide 931 * @private 932 */ 933 Wall3D.prototype.createGeometriesSurroundingDoorOrWindow = function(doorOrWindow, doorOrWindowFrontArea, frontOrBackSide, wall, wallGeometries, wallTopGeometries, 934 wallSidePoints, wallElevation, cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta, 935 texture, textureReferencePoint, wallSide) { 936 if (doorOrWindow.getModelTransformations() !== null) { 937 doorOrWindowFrontArea = new java.awt.geom.Area(doorOrWindowFrontArea); 938 doorOrWindowFrontArea.transform(java.awt.geom.AffineTransform.getTranslateInstance(0.5, 0.5)); 939 doorOrWindowFrontArea.transform(java.awt.geom.AffineTransform.getScaleInstance( 940 doorOrWindow.getWidth() * doorOrWindow.getWallWidth(), 941 doorOrWindow.getHeight() * doorOrWindow.getWallHeight())); 942 doorOrWindowFrontArea.transform(java.awt.geom.AffineTransform.getTranslateInstance( 943 doorOrWindow.getWallLeft() * doorOrWindow.getWidth(), 944 (1 - doorOrWindow.getWallHeight() - doorOrWindow.getWallTop()) * doorOrWindow.getHeight())); 945 doorOrWindowFrontArea.transform(java.awt.geom.AffineTransform.getScaleInstance( 946 1 / doorOrWindow.getWidth(), 947 1 / doorOrWindow.getHeight())); 948 doorOrWindowFrontArea.transform(java.awt.geom.AffineTransform.getTranslateInstance(-0.5, -0.5)); 949 } 950 951 var fullFaceArea = new java.awt.geom.Area(Wall3D.FULL_FACE_CUT_OUT_AREA); 952 fullFaceArea.subtract(doorOrWindowFrontArea); 953 if (!fullFaceArea.isEmpty()) { 954 var doorOrWindowDepth = doorOrWindow.getDepth(); 955 var xPieceSide = (doorOrWindow.getX() - frontOrBackSide * doorOrWindowDepth / 2 * Math.sin(doorOrWindow.getAngle())); 956 var yPieceSide = (doorOrWindow.getY() + frontOrBackSide * doorOrWindowDepth / 2 * Math.cos(doorOrWindow.getAngle())); 957 var wallFirstPoint = wallSide === Wall3D.WALL_LEFT_SIDE 958 ? wallSidePoints[0] 959 : wallSidePoints[wallSidePoints.length - 1]; 960 var wallSecondPoint = wallSide === Wall3D.WALL_LEFT_SIDE 961 ? wallSidePoints[(wallSidePoints.length / 2 | 0) - 1] 962 : wallSidePoints[(wallSidePoints.length / 2 | 0)]; 963 var frontSideToWallDistance = java.awt.geom.Line2D.ptLineDist(wallFirstPoint[0], wallFirstPoint[1], wallSecondPoint[0], 964 wallSecondPoint[1], xPieceSide, yPieceSide); 965 var position = java.awt.geom.Line2D.relativeCCW(wallFirstPoint[0], wallFirstPoint[1], 966 wallSecondPoint[0], wallSecondPoint[1], xPieceSide, yPieceSide); 967 var depthTranslation = frontOrBackSide * (0.5 - position * frontSideToWallDistance / doorOrWindowDepth); 968 969 var frontAreaTransform = ModelManager.getInstance().getPieceOfFurnitureNormalizedModelTransformation(doorOrWindow, null); 970 var frontAreaTranslation = mat4.create(); 971 mat4.fromTranslation(frontAreaTranslation, vec3.fromValues(0, 0, depthTranslation)); 972 mat4.mul(frontAreaTransform, frontAreaTransform, frontAreaTranslation); 973 974 var invertedFrontAreaTransform = mat4.create(); 975 mat4.invert(invertedFrontAreaTransform, frontAreaTransform); 976 var wallPath = new java.awt.geom.GeneralPath(); 977 var wallPoint = vec3.fromValues(wallFirstPoint[0], wallElevation, wallFirstPoint[1]); 978 vec3.transformMat4(wallPoint, wallPoint, invertedFrontAreaTransform); 979 wallPath.moveTo(wallPoint[0], wallPoint[1]); 980 wallPoint = vec3.fromValues(wallSecondPoint[0], wallElevation, wallSecondPoint[1]); 981 vec3.transformMat4(wallPoint, wallPoint, invertedFrontAreaTransform); 982 wallPath.lineTo(wallPoint[0], wallPoint[1]); 983 var topWallPoint1 = vec3.fromValues(wallSecondPoint[0], this.getWallPointElevation(wallSecondPoint[0], wallSecondPoint[1], cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta), wallSecondPoint[1]); 984 vec3.transformMat4(topWallPoint1, topWallPoint1, invertedFrontAreaTransform); 985 wallPath.lineTo(topWallPoint1[0], topWallPoint1[1]); 986 var topWallPoint2 = vec3.fromValues(wallFirstPoint[0], this.getWallPointElevation(wallFirstPoint[0], wallFirstPoint[1], cosWallYawAngle, sinWallYawAngle, topLineAlpha, topLineBeta), wallFirstPoint[1]); 987 vec3.transformMat4(topWallPoint2, topWallPoint2, invertedFrontAreaTransform); 988 wallPath.lineTo(topWallPoint2[0], topWallPoint2[1]); 989 wallPath.closePath(); 990 991 var doorOrWindowSurroundingPath = new java.awt.geom.GeneralPath(); 992 doorOrWindowSurroundingPath.moveTo(-0.5, -0.5); 993 doorOrWindowSurroundingPath.lineTo(-0.5, 0.5); 994 doorOrWindowSurroundingPath.lineTo(0.5, 0.5); 995 doorOrWindowSurroundingPath.lineTo(0.5, -0.5); 996 doorOrWindowSurroundingPath.closePath(); 997 998 var doorOrWindowSurroundingArea = new java.awt.geom.Area(doorOrWindowSurroundingPath); 999 doorOrWindowSurroundingArea.intersect(new java.awt.geom.Area(wallPath)); 1000 doorOrWindowSurroundingArea.subtract(doorOrWindowFrontArea); 1001 var flatness = 0.5 / (Math.max(doorOrWindow.getWidth(), doorOrWindow.getHeight())); 1002 if (!doorOrWindowSurroundingArea.isEmpty()) { 1003 var reversed = frontOrBackSide > 0 !== (wallSide === Wall3D.WALL_RIGHT_SIDE) !== doorOrWindow.isModelMirrored(); 1004 var doorOrWindowSurroundingAreasPoints = this.getAreaPoints(doorOrWindowSurroundingArea, flatness, reversed); 1005 if (!(doorOrWindowSurroundingAreasPoints.length === 0)) { 1006 var stripCounts = new Array(doorOrWindowSurroundingAreasPoints.length); 1007 var vertexCount = 0; 1008 for (var i = 0; i < doorOrWindowSurroundingAreasPoints.length; i++) { 1009 var areaPoints = doorOrWindowSurroundingAreasPoints[i]; 1010 stripCounts[i] = areaPoints.length + 1; 1011 vertexCount += stripCounts[i]; 1012 } 1013 var halfWallThickness = wall.getThickness() / 2; 1014 var deltaXToWallMiddle = halfWallThickness * sinWallYawAngle; 1015 var deltaZToWallMiddle = -halfWallThickness * cosWallYawAngle; 1016 if (wallSide === Wall3D.WALL_LEFT_SIDE) { 1017 deltaXToWallMiddle *= -1; 1018 deltaZToWallMiddle *= -1; 1019 } 1020 var coords = new Array(vertexCount); 1021 var borderCoords = ([]); 1022 var slopingTopCoords = ([]); 1023 var textureCoords; 1024 var borderTextureCoords; 1025 if (texture != null) { 1026 textureCoords = new Array(coords.length); 1027 borderTextureCoords = []; 1028 } else { 1029 textureCoords = null; 1030 borderTextureCoords = null; 1031 } 1032 var i = 0; 1033 for (var index = 0; index < doorOrWindowSurroundingAreasPoints.length; index++) { 1034 var areaPoints = doorOrWindowSurroundingAreasPoints[index]; 1035 var point = vec3.fromValues(areaPoints[0][0], areaPoints[0][1], 0); 1036 vec3.transformMat4(point, point, frontAreaTransform); 1037 var textureCoord = null; 1038 if (texture != null) { 1039 var horizontalTextureCoords = java.awt.geom.Point2D.distance(textureReferencePoint[0], textureReferencePoint[1], point[0], point[2]); 1040 if (wallSide === Wall3D.WALL_LEFT_SIDE && texture.isLeftToRightOriented()) { 1041 horizontalTextureCoords = -horizontalTextureCoords; 1042 } 1043 textureCoord = vec2.fromValues(horizontalTextureCoords, point[1]); 1044 } 1045 var distanceToTop = java.awt.geom.Line2D.ptLineDistSq(topWallPoint1[0], topWallPoint1[1], topWallPoint2[0], topWallPoint2[1], 1046 areaPoints[0][0], areaPoints[0][1]); 1047 1048 for (var j = 0; j < areaPoints.length; j++, i++) { 1049 coords[i] = point; 1050 if (texture != null) { 1051 textureCoords[i] = textureCoord; 1052 } 1053 1054 var nextPointIndex = j < areaPoints.length - 1 1055 ? j + 1 1056 : 0; 1057 var coordsList; 1058 var nextDistanceToTop = java.awt.geom.Line2D.ptLineDistSq(topWallPoint1[0], topWallPoint1[1], topWallPoint2[0], topWallPoint2[1], 1059 areaPoints[nextPointIndex][0], areaPoints[nextPointIndex][1]); 1060 if (distanceToTop < 1.0E-10 && nextDistanceToTop < 1.0E-10) { 1061 coordsList = slopingTopCoords; 1062 } else { 1063 coordsList = borderCoords; 1064 } 1065 1066 var nextPoint = vec3.fromValues(areaPoints[nextPointIndex][0], areaPoints[nextPointIndex][1], 0); 1067 vec3.transformMat4(nextPoint, nextPoint, frontAreaTransform); 1068 coordsList.push(point); 1069 coordsList.push(vec3.fromValues(point[0] + deltaXToWallMiddle, point[1], point[2] + deltaZToWallMiddle)); 1070 coordsList.push(vec3.fromValues(nextPoint[0] + deltaXToWallMiddle, nextPoint[1], nextPoint[2] + deltaZToWallMiddle)); 1071 coordsList.push(nextPoint); 1072 1073 var nextTextureCoord = null; 1074 if (texture != null) { 1075 var horizontalTextureCoords = java.awt.geom.Point2D.distance(textureReferencePoint[0], textureReferencePoint[1], 1076 nextPoint[0], nextPoint[2]); 1077 if (wallSide === Wall3D.WALL_LEFT_SIDE && texture.isLeftToRightOriented()) { 1078 horizontalTextureCoords = -horizontalTextureCoords; 1079 } 1080 nextTextureCoord = vec2.fromValues(horizontalTextureCoords, nextPoint[1]); 1081 if (coordsList === borderCoords) { 1082 borderTextureCoords.push(textureCoord); 1083 borderTextureCoords.push(textureCoord); 1084 borderTextureCoords.push(nextTextureCoord); 1085 borderTextureCoords.push(nextTextureCoord); 1086 } 1087 } 1088 1089 distanceToTop = nextDistanceToTop; 1090 point = nextPoint; 1091 textureCoord = nextTextureCoord; 1092 } 1093 1094 coords[i] = point; 1095 if (texture != null) { 1096 textureCoords[i] = textureCoord; 1097 } 1098 i++; 1099 } 1100 1101 var geometryInfo = new GeometryInfo3D(GeometryInfo3D.POLYGON_ARRAY); 1102 geometryInfo.setStripCounts(stripCounts); 1103 geometryInfo.setCoordinates(coords); 1104 if (texture !== null) { 1105 geometryInfo.setTextureCoordinates(textureCoords); 1106 } 1107 geometryInfo.setGeneratedNormals(true); 1108 wallGeometries.push(geometryInfo.getIndexedGeometryArray()); 1109 1110 if (borderCoords.length > 0) { 1111 geometryInfo = new GeometryInfo3D(GeometryInfo3D.QUAD_ARRAY); 1112 geometryInfo.setCoordinates(borderCoords.slice(0)); 1113 if (texture !== null) { 1114 geometryInfo.setTextureCoordinates(borderTextureCoords.slice(0)); 1115 } 1116 geometryInfo.setCreaseAngle(Math.PI / 2); 1117 geometryInfo.setGeneratedNormals(true); 1118 wallGeometries.push(geometryInfo.getIndexedGeometryArray()); 1119 } 1120 1121 if (slopingTopCoords.length > 0) { 1122 geometryInfo = new GeometryInfo3D(GeometryInfo3D.QUAD_ARRAY); 1123 geometryInfo.setCoordinates(slopingTopCoords.slice(0)); 1124 geometryInfo.setGeneratedNormals(true); 1125 wallTopGeometries.push(geometryInfo.getIndexedGeometryArray()); 1126 } 1127 } 1128 } 1129 } 1130 } 1131 1132 /** 1133 * Returns the elevation of the wall managed by this 3D object. 1134 * @param {boolean} ignoreFloorThickness 1135 * @return {number} 1136 * @private 1137 */ 1138 Wall3D.prototype.getWallElevation = function(ignoreFloorThickness) { 1139 var wall = this.getUserData(); 1140 var level = wall.getLevel(); 1141 if (level === null) { 1142 return 0; 1143 } else if (ignoreFloorThickness) { 1144 return level.getElevation(); 1145 } else { 1146 var floorThicknessBottomWall = this.getFloorThicknessBottomWall(); 1147 if (floorThicknessBottomWall > 0) { 1148 floorThicknessBottomWall -= Wall3D.LEVEL_ELEVATION_SHIFT; 1149 } 1150 return level.getElevation() - floorThicknessBottomWall; 1151 } 1152 } 1153 1154 /** 1155 * Returns the floor thickness at the bottom of the wall managed by this 3D object. 1156 * @return {number} 1157 * @private 1158 */ 1159 Wall3D.prototype.getFloorThicknessBottomWall = function() { 1160 var wall = this.getUserData(); 1161 var level = wall.getLevel(); 1162 if (level == null) { 1163 return 0; 1164 } else { 1165 var levels = this.getHome().getLevels(); 1166 if (!(levels.length === 0) && levels[0].getElevation() === level.getElevation()) { 1167 return 0; 1168 } else { 1169 return level.getFloorThickness(); 1170 } 1171 } 1172 } 1173 1174 /** 1175 * Returns the elevation of the wall top at its start. 1176 * @return {number} 1177 * @private 1178 */ 1179 Wall3D.prototype.getWallTopElevationAtStart = function() { 1180 var wallHeight = this.getUserData().getHeight(); 1181 var wallHeightAtStart; 1182 if (wallHeight !== null) { 1183 wallHeightAtStart = wallHeight + this.getWallElevation(false) + this.getFloorThicknessBottomWall(); 1184 } else { 1185 wallHeightAtStart = this.getHome().getWallHeight() + this.getWallElevation(false) + this.getFloorThicknessBottomWall(); 1186 } 1187 return wallHeightAtStart + this.getTopElevationShift(); 1188 } 1189 1190 /** 1191 * @private 1192 */ 1193 Wall3D.prototype.getTopElevationShift = function() { 1194 var level = this.getUserData().getLevel(); 1195 if (level !== null) { 1196 var levels = this.getHome().getLevels(); 1197 if (levels[levels.length - 1] !== level) { 1198 return Wall3D.LEVEL_ELEVATION_SHIFT; 1199 } 1200 } 1201 return 0; 1202 } 1203 1204 /** 1205 * Returns the elevation of the wall top at its end. 1206 * @return {number} 1207 * @private 1208 */ 1209 Wall3D.prototype.getWallTopElevationAtEnd = function() { 1210 var wall = this.getUserData(); 1211 if (wall.isTrapezoidal()) { 1212 return wall.getHeightAtEnd() + this.getWallElevation(false) + this.getFloorThicknessBottomWall() + this.getTopElevationShift(); 1213 } else { 1214 return this.getWallTopElevationAtStart(); 1215 } 1216 } 1217 1218 /** 1219 * Returns the elevation of the given baseboard top. 1220 * @param {Baseboard} baseboard 1221 * @return {number} 1222 * @private 1223 */ 1224 Wall3D.prototype.getBaseboardTopElevation = function(baseboard) { 1225 return baseboard.getHeight() + this.getWallElevation(true); 1226 } 1227 1228 /** 1229 * Returns the selection geometry of this wall. 1230 * @return {IndexedGeometryArray3D} 1231 * @private 1232 */ 1233 Wall3D.prototype.createWallSelectionGeometry = function() { 1234 var wall = this.getUserData(); 1235 var wallElevation = this.getWallElevation(true); 1236 var leftSideBaseboard = wall.getLeftSideBaseboard(); 1237 var rightSideBaseboard = wall.getRightSideBaseboard(); 1238 var wallPoints = wall.getPoints(); 1239 var wallPointsIncludingBaseboards = wall.getPoints(true); 1240 var selectionCoordinates = new Array(wallPoints.length * 2 1241 + (leftSideBaseboard != null ? 4 : 0) 1242 + (rightSideBaseboard != null ? 4 : 0)); 1243 var indices = new Array(wallPoints.length * 4 1244 + (leftSideBaseboard != null ? 12 : 4) 1245 + (rightSideBaseboard != null ? 12 : 4)); 1246 // Contour at bottom 1247 var j = 0, k = 0; 1248 for (var i = 0; i < wallPoints.length; i++, j++) { 1249 selectionCoordinates [j] = vec3.fromValues(wallPointsIncludingBaseboards [i][0], wallElevation, wallPointsIncludingBaseboards [i][1]); 1250 indices [k++] = j; 1251 if (i > 0) { 1252 indices [k++] = j; 1253 } 1254 } 1255 indices [k++] = 0; 1256 1257 // Compute wall angles and top line factors to generate top contour 1258 var topElevationAtStart = this.getWallTopElevationAtStart(); 1259 var topElevationAtEnd = this.getWallTopElevationAtEnd(); 1260 var wallYawAngle = Math.atan2(wall.getYEnd() - wall.getYStart(), wall.getXEnd() - wall.getXStart()); 1261 var cosWallYawAngle = Math.cos(wallYawAngle); 1262 var sinWallYawAngle = Math.sin(wallYawAngle); 1263 var wallXStartWithZeroYaw = cosWallYawAngle * wall.getXStart() + sinWallYawAngle * wall.getYStart(); 1264 var wallXEndWithZeroYaw = cosWallYawAngle * wall.getXEnd() + sinWallYawAngle * wall.getYEnd(); 1265 var topLineAlpha; 1266 var topLineBeta; 1267 if (topElevationAtStart == topElevationAtEnd) { 1268 topLineAlpha = 0; 1269 topLineBeta = topElevationAtStart; 1270 } else { 1271 topLineAlpha = (topElevationAtEnd - topElevationAtStart) / (wallXEndWithZeroYaw - wallXStartWithZeroYaw); 1272 topLineBeta = topElevationAtStart - topLineAlpha * wallXStartWithZeroYaw; 1273 } 1274 1275 // Contour at top 1276 for (var i = 0; i < wallPoints.length; i++, j++) { 1277 var xTopPointWithZeroYaw = cosWallYawAngle * wallPoints [i][0] + sinWallYawAngle * wallPoints [i][1]; 1278 var topY = topLineAlpha * xTopPointWithZeroYaw + topLineBeta; 1279 selectionCoordinates [j] = vec3.fromValues(wallPoints [i][0], topY, wallPoints [i][1]); 1280 indices [k++] = j; 1281 if (i > 0) { 1282 indices [k++] = j; 1283 } 1284 } 1285 indices [k++] = wallPoints.length; 1286 1287 // Vertical lines at corners 1288 indices [k++] = 0; 1289 if (leftSideBaseboard != null) { 1290 var leftBaseboardHeight = this.getBaseboardTopElevation(leftSideBaseboard); 1291 selectionCoordinates [j] = vec3.fromValues(wallPointsIncludingBaseboards [0][0], Math.min(leftBaseboardHeight, topElevationAtStart), wallPointsIncludingBaseboards [0][1]); 1292 indices [k++] = j; 1293 indices [k++] = j++; 1294 selectionCoordinates [j] = vec3.fromValues(wallPoints [0][0], Math.min(leftBaseboardHeight, topElevationAtStart), wallPoints [0][1]); 1295 indices [k++] = j; 1296 indices [k++] = j++; 1297 } 1298 indices [k++] = wallPoints.length; 1299 indices [k++] = wallPoints.length / 2 - 1; 1300 if (leftSideBaseboard != null) { 1301 var leftBaseboardHeight = this.getBaseboardTopElevation(leftSideBaseboard); 1302 selectionCoordinates [j] = vec3.fromValues(wallPointsIncludingBaseboards [wallPoints.length / 2 - 1][0], Math.min(leftBaseboardHeight, topElevationAtEnd), wallPointsIncludingBaseboards [wallPoints.length / 2 - 1][1]); 1303 indices [k++] = j; 1304 indices [k++] = j++; 1305 selectionCoordinates [j] = vec3.fromValues(wallPoints [wallPoints.length / 2 - 1][0], Math.min(leftBaseboardHeight, topElevationAtEnd), wallPoints [wallPoints.length / 2 - 1][1]); 1306 indices [k++] = j; 1307 indices [k++] = j++; 1308 } 1309 indices [k++] = wallPoints.length + wallPoints.length / 2 - 1; 1310 indices [k++] = wallPoints.length - 1; 1311 if (rightSideBaseboard != null) { 1312 var rightBaseboardHeight = this.getBaseboardTopElevation(rightSideBaseboard); 1313 selectionCoordinates [j] = vec3.fromValues(wallPointsIncludingBaseboards [wallPoints.length - 1][0], Math.min(rightBaseboardHeight, topElevationAtStart), wallPointsIncludingBaseboards [wallPoints.length - 1][1]); 1314 indices [k++] = j; 1315 indices [k++] = j++; 1316 selectionCoordinates [j] = vec3.fromValues(wallPoints [wallPoints.length - 1][0], Math.min(rightBaseboardHeight, topElevationAtStart), wallPoints [wallPoints.length - 1][1]); 1317 indices [k++] = j; 1318 indices [k++] = j++; 1319 } 1320 indices [k++] = 2 * wallPoints.length - 1; 1321 indices [k++] = wallPoints.length / 2; 1322 if (rightSideBaseboard != null) { 1323 var rightBaseboardHeight = this.getBaseboardTopElevation(rightSideBaseboard); 1324 selectionCoordinates [j] = vec3.fromValues(wallPointsIncludingBaseboards [wallPoints.length / 2][0], Math.min(rightBaseboardHeight, topElevationAtEnd), wallPointsIncludingBaseboards [wallPoints.length / 2][1]); 1325 indices [k++] = j; 1326 indices [k++] = j++; 1327 selectionCoordinates [j] = vec3.fromValues(wallPoints [wallPoints.length / 2][0], Math.min(rightBaseboardHeight, topElevationAtEnd), wallPoints [wallPoints.length / 2][1]); 1328 indices [k++] = j; 1329 indices [k++] = j++; 1330 } 1331 indices [k++] = wallPoints.length + wallPoints.length / 2; 1332 1333 return new IndexedLineArray3D(selectionCoordinates, indices); 1334 } 1335 1336 /** 1337 * Sets wall appearance with its color, texture and transparency. 1338 * @param {boolean} waitTextureLoadingEnd 1339 * @private 1340 */ 1341 Wall3D.prototype.updateWallAppearance = function(waitTextureLoadingEnd) { 1342 var wall = this.getUserData(); 1343 var wallsTopColor = wall.getTopColor(); 1344 var wallLeftSideGroups = [this.getChild(0), this.getChild(2), this.getChild(4), this.getChild(6)]; 1345 var wallRightSideGroups = [this.getChild(1), this.getChild(3), this.getChild(5), this.getChild(7)]; 1346 for (var i = 0; i < wallLeftSideGroups.length; i++) { 1347 if (i === 1) { 1348 var leftSideBaseboard = wall.getLeftSideBaseboard(); 1349 if (leftSideBaseboard != null) { 1350 var texture = leftSideBaseboard.getTexture(); 1351 var color = leftSideBaseboard.getColor(); 1352 if (color === null && texture === null) { 1353 texture = wall.getLeftSideTexture(); 1354 color = wall.getLeftSideColor(); 1355 } 1356 this.updateFilledWallSideAppearance(wallLeftSideGroups[i].getChild(0).getAppearance(), 1357 texture, waitTextureLoadingEnd, color, wall.getLeftSideShininess()); 1358 } 1359 var rightSideBaseboard = wall.getRightSideBaseboard(); 1360 if (rightSideBaseboard != null) { 1361 var texture = rightSideBaseboard.getTexture(); 1362 var color = rightSideBaseboard.getColor(); 1363 if (color == null && texture == null) { 1364 texture = wall.getRightSideTexture(); 1365 color = wall.getRightSideColor(); 1366 } 1367 this.updateFilledWallSideAppearance(wallRightSideGroups[i].getChild(0).getAppearance(), 1368 texture, waitTextureLoadingEnd, color, wall.getRightSideShininess()); 1369 } 1370 } else if (i !== 3 || wallsTopColor == null) { 1371 this.updateFilledWallSideAppearance(wallLeftSideGroups[i].getChild(0).getAppearance(), 1372 wall.getLeftSideTexture(), waitTextureLoadingEnd, wall.getLeftSideColor(), wall.getLeftSideShininess()); 1373 this.updateFilledWallSideAppearance(wallRightSideGroups[i].getChild(0).getAppearance(), 1374 wall.getRightSideTexture(), waitTextureLoadingEnd, wall.getRightSideColor(), wall.getRightSideShininess()); 1375 } else { 1376 this.updateFilledWallSideAppearance(wallLeftSideGroups[i].getChild(0).getAppearance(), 1377 null, waitTextureLoadingEnd, wallsTopColor, 0); 1378 this.updateFilledWallSideAppearance(wallRightSideGroups[i].getChild(0).getAppearance(), 1379 null, waitTextureLoadingEnd, wallsTopColor, 0); 1380 } 1381 } 1382 1383 var selectionShapeAppearance = this.getChild(8).getAppearance(); 1384 selectionShapeAppearance.setVisible(this.getUserPreferences() != null 1385 && this.getUserPreferences().isEditingIn3DViewEnabled() 1386 && this.getHome().isItemSelected(wall)); 1387 } 1388 1389 /** 1390 * Sets filled wall side appearance with its color, texture, transparency and visibility. 1391 * @param {Appearance3D} wallSideAppearance 1392 * @param {HomeTexture} wallSideTexture 1393 * @param {boolean} waitTextureLoadingEnd 1394 * @param {number} wallSideColor 1395 * @param {number} shininess 1396 * @private 1397 */ 1398 Wall3D.prototype.updateFilledWallSideAppearance = function(wallSideAppearance, wallSideTexture, waitTextureLoadingEnd, 1399 wallSideColor, shininess) { 1400 if (wallSideTexture == null) { 1401 this.updateAppearanceMaterial(wallSideAppearance, wallSideColor, wallSideColor, shininess); 1402 wallSideAppearance.setTextureImage(null); 1403 } else { 1404 this.updateAppearanceMaterial(wallSideAppearance, Object3DBranch.DEFAULT_COLOR, Object3DBranch.DEFAULT_AMBIENT_COLOR, shininess); 1405 this.updateTextureTransform(wallSideAppearance, wallSideTexture, true); 1406 TextureManager.getInstance().loadTexture(wallSideTexture.getImage(), waitTextureLoadingEnd, { 1407 textureUpdated : function(texture) { 1408 wallSideAppearance.setTextureImage(texture); 1409 }, 1410 textureError : function(error) { 1411 return this.textureUpdated(TextureManager.getInstance().getErrorImage()); 1412 } 1413 }); 1414 } 1415 var wallsAlpha = this.getHome().getEnvironment().getWallsAlpha(); 1416 wallSideAppearance.setTransparency(wallsAlpha); 1417 } 1418 1419 /** 1420 * An area used to compute holes in walls. 1421 * @constructor 1422 * @private 1423 */ 1424 Wall3D.DoorOrWindowArea = function(area, doorsOrWindows) { 1425 this.area = area; 1426 this.doorsOrWindows = doorsOrWindows; 1427 } 1428 1429 Wall3D.DoorOrWindowArea.prototype.getArea = function() { 1430 return this.area; 1431 } 1432 1433 Wall3D.DoorOrWindowArea.prototype.getDoorsOrWindows = function() { 1434 return this.doorsOrWindows; 1435 } 1436