Skip to content

Instantly share code, notes, and snippets.

@sfpgmr
Last active May 16, 2017 12:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfpgmr/e1917c9f13455b4af39226c8835094ca to your computer and use it in GitHub Desktop.
Save sfpgmr/e1917c9f13455b4af39226c8835094ca to your computer and use it in GitHub Desktop.
ExtrudeGeometry&TextureMapping
typings
node_modules
.vscode
temp

Extrude Geometry

E

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ExtrudeGeometryの検証</title>
<script type="text/javascript" src="./three.js"></script>
<script type="text/javascript" src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.8.0/d3.min.js"></script>
<script type="text/javascript" src="./main.js"></script>
<style>
body {margin:0;padding:0;overflow:hidden;}
#container {
position: relative;
}
#loading {
left:25vw;
top:50vh;
width:50vw;
position: absolute;
background: white;
color:black;
opacity: 0.5;
margin:auto;
text-align: center;
font-size:3vw;
}
</style>
</head>
<body>
<div id="container">
<div id="loading">Please wait while loading ...</div>
</div>
</body>
</html>
"use strict"
var renderer, project, scene, camera, controls, buildingsTextures = [];
const MAX_TEX_NUM = 16; // 4 x 4 = 16 cell
const TEX_DIV = 4;// UV座標の分割数
const TEX_DIV_R = 1 / TEX_DIV;// UV座標の分割数の逆数
class BoundingUVGenerator {
constructor() {
}
// THREE.ExtrudeGeometryの前に呼び出す
setShape({
extrudedShape, // 押し出すShape
extrudedOptions// THREE.ExtrudeGeometryのオプション
}) {
// texIndexTop = MAX_TEX_NUM - texIndexTop - 1;
// texIndexSide = MAX_TEX_NUM - texIndexSide - 1;
this.extrudedShape = extrudedShape;
this.bb = new THREE.Box2();
// this.texIndexTopV = Math.floor(texIndexTop / TEX_DIV) * TEX_DIV_R;
// this.texIndexTopU = (texIndexTop % TEX_DIV) * TEX_DIV_R;
// this.texIndexSideV = Math.floor(texIndexSide / TEX_DIV) * TEX_DIV_R;
// this.texIndexSideU = (texIndexSide % TEX_DIV) * TEX_DIV_R;
this.bb.setFromPoints(this.extrudedShape.extractAllPoints().shape);
this.extrudedOptions = extrudedOptions;
}
generateTopUV(geometry, vertices, indexA, indexB, indexC) {
const ax = vertices[indexA * 3],
ay = vertices[indexA * 3 + 1],
bx = vertices[indexB * 3],
by = vertices[indexB * 3 + 1],
cx = vertices[indexC * 3],
cy = vertices[indexC * 3 + 1],
bb = this.bb,//extrudedShape.getBoundingBox(),
bbx = (bb.max.x - bb.min.x),
bby = (bb.max.y - bb.min.y);
return [
new THREE.Vector2((ax - bb.min.x) / bbx, (1.0 - (ay - bb.min.y) / bby)),
new THREE.Vector2((bx - bb.min.x) / bbx, (1.0 - (by - bb.min.y) / bby)),
new THREE.Vector2((cx - bb.min.x) / bbx, (1.0 - (cy - bb.min.y) / bby))
];
}
generateSideWallUV(geometry, vertices, indexA, indexB, indexC, indexD) {
const ax = vertices[indexA * 3],
ay = vertices[indexA * 3 + 1],
az = vertices[indexA * 3 + 2],
bx = vertices[indexB * 3],
by = vertices[indexB * 3 + 1],
bz = vertices[indexB * 3 + 2],
cx = vertices[indexC * 3],
cy = vertices[indexC * 3 + 1],
cz = vertices[indexC * 3 + 2],
dx = vertices[indexD * 3],
dy = vertices[indexD * 3 + 1],
dz = vertices[indexD * 3 + 2];
const amt = this.extrudedOptions.amount,
bb = this.bb,//extrudedShape.getBoundingBox(),
bbx = (bb.max.x - bb.min.x),
bby = (bb.max.y - bb.min.y);
if (Math.abs(ay - by) < 0.01) {
return [
new THREE.Vector2(ax / bbx, 1.0 - az / amt),
new THREE.Vector2(bx / bbx, 1.0 - bz / amt),
new THREE.Vector2(cx / bbx, 1.0 - cz / amt),
new THREE.Vector2(dx / bbx, 1.0 - dz / amt)
];
} else {
return [
new THREE.Vector2((ay / bby), 1.0 - az / amt),
new THREE.Vector2((by / bby), 1.0 - bz / amt),
new THREE.Vector2((cy / bby), 1.0 - cz / amt),
new THREE.Vector2((dy / bby), 1.0 - dz / amt)
];
}
}
};
const vertexShader =
`#define PHONG
varying vec3 vViewPosition;
#ifndef FLAT_SHADED
varying vec3 vNormal;
#endif
#include <common>
#include <uv_pars_vertex>
#include <uv2_pars_vertex>
#include <displacementmap_pars_vertex>
#include <envmap_pars_vertex>
#include <color_pars_vertex>
#include <fog_pars_vertex>
#include <morphtarget_pars_vertex>
#include <skinning_pars_vertex>
#include <shadowmap_pars_vertex>
#include <logdepthbuf_pars_vertex>
#include <clipping_planes_pars_vertex>
attribute float texIndex;
attribute float amount;
varying float vTexIndex;
varying float vAmount;
varying vec3 vNormalView;
void main() {
#include <uv_vertex>
#include <uv2_vertex>
#include <color_vertex>
#include <beginnormal_vertex>
#include <morphnormal_vertex>
#include <skinbase_vertex>
#include <skinnormal_vertex>
#include <defaultnormal_vertex>
#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED
vNormal = normalize( transformedNormal );
#endif
#include <begin_vertex>
#include <displacementmap_vertex>
#include <morphtarget_vertex>
#include <skinning_vertex>
#include <project_vertex>
#include <logdepthbuf_vertex>
#include <clipping_planes_vertex>
vViewPosition = - mvPosition.xyz;
#include <worldpos_vertex>
#include <envmap_vertex>
#include <shadowmap_vertex>
#include <fog_vertex>
vTexIndex = texIndex;
vAmount = amount;
vNormalView = normal;
}
`;
const fragmentShader =
`#define PHONG
uniform vec3 diffuse;
uniform vec3 emissive;
uniform vec3 specular;
uniform float shininess;
uniform float opacity;
#include <common>
#include <packing>
#include <dithering_pars_fragment>
#include <color_pars_fragment>
#include <uv_pars_fragment>
#include <uv2_pars_fragment>
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <aomap_pars_fragment>
#include <lightmap_pars_fragment>
#include <emissivemap_pars_fragment>
#include <envmap_pars_fragment>
#include <gradientmap_pars_fragment>
#include <fog_pars_fragment>
#include <bsdfs>
#include <lights_pars>
#include <lights_phong_pars_fragment>
#include <shadowmap_pars_fragment>
#include <bumpmap_pars_fragment>
#include <normalmap_pars_fragment>
#include <specularmap_pars_fragment>
#include <logdepthbuf_pars_fragment>
#include <clipping_planes_pars_fragment>
varying float vTexIndex;
varying float vAmount;
varying vec3 vNormalView;
void main() {
#include <clipping_planes_fragment>
vec4 diffuseColor = vec4( diffuse, opacity );
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
vec3 totalEmissiveRadiance = emissive;
#include <logdepthbuf_fragment>
//#include <map_fragment>
//float ycomp = dot(vec3(0.,0.,1.),vNormalView);
float texIdx;
if(vNormalView.z != 0.0){
texIdx = MAX_TEX_NUM - vTexIndex - 8.0 - 1.0;
} else {
texIdx = MAX_TEX_NUM - vTexIndex - 1.0;
}
vec2 uv;
uv.y = floor(texIdx / TEX_DIV) * TEX_DIV_R;
uv.x = mod(texIdx,TEX_DIV ) * TEX_DIV_R ;
vec2 vuv;
if(vNormalView.z == 0.0){
vuv = vec2(vUv.x * TEX_DIV_R,mod(vUv.y , 1.0 / vAmount) * vAmount * TEX_DIV_R / 8.0);
} else {
vuv = vUv * TEX_DIV_R;
}
vec4 texelColor = texture2D(map, vuv + uv);
//vec4 texelColor = texture2D( map, vUv );
texelColor = mapTexelToLinear( texelColor );
diffuseColor *= texelColor;
#include <color_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <specularmap_fragment>
#include <normal_flip>
#include <normal_fragment>
#include <emissivemap_fragment>
// accumulation
#include <lights_phong_fragment>
#include <lights_template>
// modulation
#include <aomap_fragment>
vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
#include <envmap_fragment>
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
#include <tonemapping_fragment>
#include <encodings_fragment>
#include <fog_fragment>
#include <premultiplied_alpha_fragment>
#include <dithering_fragment>
}
`;
// `
// //varying vec2 vUv;
// varying float vTexIndex;
// varying float vAmount;
// //uniform sampler2D map;
// void main(){
// float texIdx = MAX_TEX_NUM - vTexIndex - 1.0;
// vec2 uv;
// uv.y = floor(texIdx / TEX_DIV) * TEX_DIV_R;
// uv.x = mod(texIdx,TEX_DIV ) * TEX_DIV_R ;
// vec2 vuv;
// if(vTexIndex < 4.0){
// vuv = vec2(vUv.x * TEX_DIV_R,mod(vUv.y , 1.0 / vAmount) * vAmount * TEX_DIV_R / 8.0);
// } else {
// vuv = vUv * TEX_DIV_R;
// }
// gl_FragColor = texture2D(map, vuv + uv);
// }
// `;
function toFloatString(number) {
const v = number.toString();
return v.match(/\./) ? v : v + '.0';
}
document.addEventListener('DOMContentLoaded', function () {
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xa0a0d0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
//renderer.shadowMapEnabled = true;
document.getElementById('container').appendChild(renderer.domElement);
let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(100, 100, -100);
//light.castShadow = true;
scene.add(light);
let light1 = new THREE.DirectionalLight(0xffffff, 0.7);
light1.position.set(-100, -1000, -100);
scene.add(light1);
//scene.fog = new THREE.FogExp2(0xc0c0c0, 0.00015);
let am = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(am);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 40000);
camera.position.set(0, 0, 50);
scene.add(camera);
let pr = Promise.resolve(0);
let texloader = new THREE.TextureLoader();
let textures = [
'./texture.jpg'
];
textures.forEach((url) => {
pr = pr.then(() => new Promise((resolve, reject) => {
texloader.load(url, (tex) => {
tex.wrapS = THREE.RepeatWrapping;
tex.wrapT = THREE.RepeatWrapping;
// tex.repeat.set(5, 5);
buildingsTextures.push(tex);
resolve();
});
}));
});
pr.then(() => {
const mesh = new THREE.Object3D();
mesh.add(new THREE.LineSegments(
new THREE.Geometry(),
new THREE.LineBasicMaterial({
color: 0xffffff,
transparent: true,
opacity: 0.5
})
));
const baseShader = THREE.ShaderLib['phong'];
const mat = new THREE.ShaderMaterial({
uniforms:THREE.UniformsUtils.clone(baseShader.uniforms),
defines: {
MAX_TEX_NUM: toFloatString(MAX_TEX_NUM),
TEX_DIV: toFloatString(TEX_DIV),
TEX_DIV_R: toFloatString(TEX_DIV_R),
USE_MAP:''
},
lights:true,
vertexShader: vertexShader,
fragmentShader: fragmentShader
});
mat.uniforms.emissive.value = new THREE.Color(0x000000);
mat.uniforms.ambientLightColor.value = new THREE.Color(0x303030);
mat.uniforms.map.value = buildingsTextures[0];
mesh.add(new THREE.Mesh(
new THREE.Geometry(),
mat
));
const gui = new dat.GUI();
const uvGenerator = new BoundingUVGenerator();
const data = {
steps: 1,
amount: 16,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1,
texNo: 0,
UVGenerator: uvGenerator
};
const length = 12, width = 8;
const shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.lineTo(0, width);
shape.lineTo(length, width);
shape.lineTo(length, 0);
shape.lineTo(0, 0);
function updateGroupGeometry(mesh, geometry) {
mesh.children[0].geometry.dispose();
mesh.children[1].geometry.dispose();
mesh.children[0].geometry = new THREE.WireframeGeometry(geometry);
mesh.children[1].geometry = geometry;
geometry.computeFaceNormals();
geometry.computeVertexNormals(true);
const texIndexs = new Float32Array(geometry.attributes.position.count);
const amounts = new Float32Array(geometry.attributes.position.count);
for (let i = 0, e = geometry.attributes.position.count; i < e; ++i) {
texIndexs[i] = data.texNo;
amounts[i] = data.amount;
}
geometry.addAttribute('texIndex', new THREE.BufferAttribute(texIndexs, 1));
geometry.addAttribute('amount', new THREE.BufferAttribute(amounts, 1));
}
function generateGeometry() {
updateGroupGeometry(mesh,
new THREE.ExtrudeBufferGeometry(shape, data)
);
render();
}
//const folder = gui.addFolder('THREE.ExtrudeBufferGeometry');
gui.add(data, 'texNo', 0, 3).step(1).onChange(generateGeometry);
gui.add(data, 'steps', 1, 100).step(1).onChange(generateGeometry);
gui.add(data, 'amount', 1, 100).step(1).onChange(generateGeometry);
gui.add(data, 'bevelEnabled').onChange(generateGeometry);
gui.add(data, 'bevelThickness', 1, 5).step(1).onChange(generateGeometry);
gui.add(data, 'bevelSize', 1, 5).step(1).onChange(generateGeometry);
gui.add(data, 'bevelSegments', 1, 5).step(1).onChange(generateGeometry);
uvGenerator.setShape({ extrudedShape: shape, extrudedOptions: data, texIndexSide: 0 });
generateGeometry();
mesh.rotation.x = Math.PI / 2;
scene.add(mesh);
gui.open();
d3.select('#loading').style('display', 'none');
// マウスでぐりぐりできるようにする
controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
render();
}).catch((e) => {
console.log('error' + e.stack);
});
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
});
});
// レンダリング処理
function render() {
// controls.update();
renderer.render(scene, camera); // レンダリング
// requestAnimationFrame(render); // ループ処理
}
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment