I have developed a code that simplifies the process of selecting a floorplan and adding doors and windows. Currently, I am seeking basic architectural textures and finishes for my project. While I could create these elements from scratch, I believe there may be valuable resources already available. Specifically, I am looking for the following architectural essentials:
Textures for wood, stone, brick, stucco, and concrete (I plan to incorporate a color picker but aim for ultra-realistic results)
Landscaping elements (trees, shrubs, grass)
Textures for tiles, carpet, and other flooring materials
Electrical outlets, fixtures, and switches
If anyone has reliable resources or recommendations for these, I would greatly appreciate your assistance in sharing links. Please pardon the simplicity of my GUI; I haven’t yet dedicated time to enhance it.
If you plan to switch to WebGPU renderer, you could try TSL textures for wood, concrete, marble, karst, rust, etc.
Here is a short clip of converting GLTF car models into wooden toys (the texture of the wood is a TSL texture):
2 Likes
I realized I already have several texture images on my PC from Autodesk Inventor and Fusion, so I decided to take a different approach.
I simply added an image upload feature that appends the file to a combobox, along with a scaling factor for adjustments.
It’s functional and effective.
I might use AI and create my own texture pack with DeepAI image editor, but I’d be interested to hear how you would approach using WebGPU and TSL, though. It seems like it could open up some more possibilities. I am using Manthrax CSG library, and don’t really want to alter that. Can I still use WebGPU while applying these same imports?
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.128/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.128/examples/jsm/"
}
}
</script>
<script type='module'>
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import CSG from "https://cdn.jsdelivr.net/gh/manthrax/THREE-CSGMesh/three-csg.js";
let scene, camera, renderer, controls, floorplanMesh = null;
<label for="textureSelect">Select Texture:</label>
<select id="textureSelect" onchange="updateTextureOnSelectionChange()">
<option value="" disabled selected>Select Texture</option>
</select>
<button id="addTextureButton">Add Texture</button>
<label for="textureScale">Texture Scale:</label>
<input type="number" id="textureScale" value="1" min="0.1" step="0.1" onchange="updateTextureScale()" />
const textureLoader = new THREE.TextureLoader();
const uploadedTextures = {};
const textureSelect = document.getElementById('textureSelect');
const textureScaleInput = document.getElementById('textureScale');
// Function to handle texture upload
function handleTextureUpload(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(e) {
const textureName = file.name;
const option = document.createElement('option');
option.value = textureName;
option.textContent = textureName;
textureSelect.appendChild(option);
uploadedTextures[textureName] = e.target.result;
};
reader.readAsDataURL(file);
}
// Function to get the selected texture and apply the scale
function getSelectedTexture() {
const selectedTextureName = textureSelect.value;
const textureURL = uploadedTextures[selectedTextureName];
if (textureURL) return textureLoader.load(textureURL);
return null;
}
// Function to apply texture with the selected scale
function applyTextureWithScale(texture) {
const scale = parseFloat(textureScaleInput.value) || 1;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(scale, scale);
// Apply texture to all meshes in floorplanMesh
floorplanMesh.traverse((child) => {
if (child.isMesh) {
child.material = new THREE.MeshStandardMaterial({ map: texture });
child.material.needsUpdate = true;
}
});
}
// Function to update texture on selection change
function updateTextureOnSelectionChange() {
const newTexture = getSelectedTexture();
if (newTexture) applyTextureWithScale(newTexture);
}
// Function to update texture scale based on input
function updateTextureScale() {
const selectedTexture = getSelectedTexture();
if (selectedTexture) applyTextureWithScale(selectedTexture);
}
// Event listener for "Add Texture" button
document.getElementById('addTextureButton').addEventListener('click', function() {
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = 'image/*';
fileInput.onchange = handleTextureUpload;
fileInput.click();
});
// Event listeners for texture selection and scale change
textureSelect.addEventListener('change', updateTextureOnSelectionChange);
textureScaleInput.addEventListener('change', updateTextureScale);
// Function to apply the selected texture to the mesh after CSG operation
function applyCSGSubtraction() {
updateFloorplanMesh();
if (!floorplanMesh) {
console.error('Floorplan mesh is not defined.');
return;
}
const resultMeshes = [];
const offsetY = document.getElementById('width').value - parseFloat(document.getElementById('positionZ').value);
function processMesh(mesh) {
if (mesh.isMesh) {
const childGeometry = mesh.geometry.clone();
const childMaterial = mesh.material.clone();
let childCSG = CSG.fromMesh(new THREE.Mesh(childGeometry, childMaterial));
mesh.updateMatrixWorld();
const worldPosition = new THREE.Vector3();
mesh.getWorldPosition(worldPosition);
const newZPosition = worldPosition.z;
mesh.position.z = newZPosition - offsetY;
openings.forEach(openingData => {
const openingMesh = openingData.box;
if (openingMesh) {
openingMesh.updateMatrixWorld();
const openingCSG = CSG.fromMesh(openingMesh);
if (checkIntersection(mesh, openingMesh)) {
childCSG = childCSG.subtract(openingCSG);
openingMesh.visible = false;
}
}
});
const resultMesh = CSG.toMesh(childCSG, new THREE.Matrix4(), childMaterial);
resultMesh.geometry.computeVertexNormals();
resultMesh.position.copy(worldPosition);
const worldQuaternion = new THREE.Quaternion();
const worldScale = new THREE.Vector3();
mesh.getWorldQuaternion(worldQuaternion);
mesh.getWorldScale(worldScale);
resultMesh.quaternion.copy(worldQuaternion);
resultMesh.scale.copy(worldScale);
resultMeshes.push(resultMesh);
}
}
function checkIntersection(mesh1, mesh2) {
const box1 = new THREE.Box3().setFromObject(mesh1);
const box2 = new THREE.Box3().setFromObject(mesh2);
return box1.intersectsBox(box2);
}
floorplanMesh.traverse(child => processMesh(child));
scene.remove(floorplanMesh);
const newFloorplanGroup = new THREE.Group();
resultMeshes.forEach(mesh => newFloorplanGroup.add(mesh));
newFloorplanGroup.rotation.x = -Math.PI / 2;
scene.add(newFloorplanGroup);
floorplanMesh = newFloorplanGroup;
// Apply the texture with scale adjustment
const selectedTexture = getSelectedTexture();
if (selectedTexture) {
applyTextureWithScale(selectedTexture);
}
}
axekan
November 1, 2024, 9:42am
4
I recommend checking out Sketchup texture club for textures. Some of theirs require membership but a lot are free.