# Problems applying texture to Extruded Geometry

**URL:** <https://discourse.threejs.org/t/problems-applying-texture-to-extruded-geometry/29935>\
**Category:** Questions\
**Tags:** textures, materials, geometry\
**Created:** [September 14, 2021, 9:46pm UTC](https://discourse.threejs.org/t/problems-applying-texture-to-extruded-geometry/29935 "2021-09-14T21:46:43Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![willsor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/willsor/32/20948_2.png) [@willsor](https://discourse.threejs.org/u/willsor)\
**Post date:** [September 14, 2021, 9:46pm UTC](https://discourse.threejs.org/t/problems-applying-texture-to-extruded-geometry/29935/1 "2021-09-14T21:46:43Z")

</div>

Hello,

I am trying to make some 3d playing cards in the browser. I have generated a rounded-rectangle shape by using ExtrudeGeometry with some lines I’ve drawn. I’m having three issues:

1. The Image texture isn’t applying to the full shape.
2. I cant specify an image for the back of the extruded texture.
3. The shadows are catching on the rounded corner pieces:

 ![card](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/5/1/51207fed137161e01f40845b1d57c192afd3c1a4.png)

```javascript
function createCardGeometry( width, depth, height, radius) {
    let shape = new THREE.Shape();
    shape.moveTo(0, width-radius)

    shape.lineTo(0, width-radius)
    shape.absarc(radius, width-radius, radius, 0, Math.PI/2, true)

    shape.lineTo(height-radius, width)
    shape.absarc(height-radius, width-radius, radius, 3*Math.PI/2, 2*Math.PI, true);

    shape.lineTo(height,radius)
    shape.absarc(height-radius, radius, radius, Math.PI/2, 3*Math.PI/2,true)

    shape.lineTo(radius, 0)
    shape.absarc(radius, radius, radius, 0, Math.PI, true)
    const extrudeSettings = {
        steps: 16,
        depth: depth,
        bevelEnabled: false
    }
    let card_shape = new THREE.ExtrudeGeometry( shape, extrudeSettings )    
    card_shape.lookAt(new THREE.Vector3(0,1,0))
    return card_shape;
}

```

The absarc sections were done almost entirely through trial and error. It’s pretty likely those are causing the shading issue

I call that as follows:

```javascript
function createCard(x,y,z,rotation,image){
    
    let pos = {x: x, y: y, z: z};
    let scale = {width: 6.91, depth: 0.1, height: 10.56};
    let quat = {x: 0, y: 0, z: 0, w: 1};
    let mass = 1;

    //threeJS Section
    let texture = new THREE.TextureLoader().load( `../../card_images/${image}.png` );
    texture.anisotropy = 16;
    let texture_back = new THREE.TextureLoader().load( `../../card_images/card_back.png` );
    texture_back.anisotropy = 16;

    var cardMaterialArray = [];
    cardMaterialArray.push(new THREE.MeshStandardMaterial({map: texture}))

    // cardMaterialArray.push(new THREE.MeshPhongMaterial({map: texture_back, color: 0xffffff}))
    var cardTextures = new THREE.MeshStandardMaterial({map: texture})
    let cardGeometry = createCardGeometry(scale.height, scale.depth, scale.width, 0.5)

    let card = new THREE.Mesh(cardGeometry, cardTextures);

    card.castShadow = true;
    card.receiveShadow = true;

    scene.add(card);

    //Ammojs Section
    let transform = new Ammo.btTransform();
    transform.setIdentity();
    transform.setOrigin( new Ammo.btVector3( pos.x, pos.y, pos.z ) );

    let quaternion = new Ammo.btQuaternion( quat.x, quat.y, quat.z, quat.w )
    quaternion.setEulerZYX(0,0,0)
    transform.setRotation(quaternion);

    let motionState = new Ammo.btDefaultMotionState( transform );

    let colShape = new Ammo.btBoxShape( new Ammo.btVector3( scale.width * 0.5, scale.depth * 0.5, scale.height * 0.5 ) );
    colShape.setMargin( 0.05 );

    let localInertia = new Ammo.btVector3( 0, 0, 0 );
    colShape.calculateLocalInertia( mass, localInertia );

    let rbInfo = new Ammo.btRigidBodyConstructionInfo( mass, motionState, colShape, localInertia );
    let body = new Ammo.btRigidBody( rbInfo );

    physicsWorld.addRigidBody(body);
    card.userData.physicsBody = body;
    rigidBodies.push(card);
}

```

I’m pretty sure Ammo handles the positioning in the world as well as the physics.

I’ve googled a lot and found some things about about UV mapping, but every example I’ve found I don’t really understand.

If there’s an easier way of going about this instead of extruding Geometry i’d like to hear it, though I dont see why I shouldn’t be able to get this to work.

---

<div class="post-metadata">

**Author:** ![hofk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hofk/32/44944_2.png) [@hofk](https://discourse.threejs.org/u/hofk)\
**Post date:** [September 15, 2021, 7:38am UTC](https://discourse.threejs.org/t/problems-applying-texture-to-extruded-geometry/29935/2 "2021-09-15T07:38:51Z")

</div>

Maybe you can easily achieve the result with the combination of the two techniques?

> [@RoundedRectangle + Squircle](https://discourse.threejs.org/t/roundedrectangle/28645):
>
> Function to create a rectangle with rounded corners. [RoundedRectangle - Mozilla Firefox 2021-08-04 12.1] See [RoundedRectangle](https://hofk.de/main/discourse.threejs/2021/RoundedRectangle/RoundedRectangle.html) [RoundedRectangle - Mozilla Firefox 2021-08-04 12.3] Example of a video see [Three js video with rounded corners - #14 by hofk](https://discourse.threejs.org/t/three-js-video-with-rounded-corners/28543/14) (slightly different code) [RoundedRectangleVideo - Mozilla Firefox 2021-08-03] // non indexed BufferGeometry function RoundedRectangle( w, h, r, s ) { // width, height, radius corner, smoothness // helper const's const wi = w / 2 - …

> [@How to have different colors/textures on bottom and top side of a Plane?](https://discourse.threejs.org/t/how-to-have-different-colors-textures-on-bottom-and-top-side-of-a-plane/12644):
>
> Hi all, I’ve got a grid of tiles, which have a THREE.DoubleSide material. These tiles flip 180 degrees when clicked, showing the bottom instead of the top. Something I couldn’t figure out: Is there any way to have a different color or texture for the bottom than the top of a plane? (I’m using React-Three-Fiber if that makes any difference)

---

<div class="post-metadata">

**Author:** ![willsor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/willsor/32/20948_2.png) [@willsor](https://discourse.threejs.org/u/willsor)\
**Post date:** [September 15, 2021, 9:31am UTC](https://discourse.threejs.org/t/problems-applying-texture-to-extruded-geometry/29935/3 "2021-09-15T09:31:39Z")

</div>

Thanks for the reply hofk.

The RoundedRectangle I don’t understand. It doesn’t create a rectangle with any depth which I need for physics simulation, and I’m still new to this so adding depth into it is non trivial for me.

Could you explain how the uv’s work? They look like a bunch of magic numbers to me

---

<div class="post-metadata">

**Author:** ![hofk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hofk/32/44944_2.png) [@hofk](https://discourse.threejs.org/u/hofk)\
**Post date:** [September 15, 2021, 3:45pm UTC](https://discourse.threejs.org/t/problems-applying-texture-to-extruded-geometry/29935/4 "2021-09-15T15:45:36Z")

</div>

> [@willsor](#):
>
> Could you explain how the uv’s work? They look like a bunch of magic numbers to me

See e.g.  
[UV mapping - Wikipedia](https://en.wikipedia.org/wiki/UV_mapping)  
[A Brief Introduction to Texture Mapping | Discover three.js](https://discoverthreejs.com/book/first-steps/textures-intro/)

* * *

For a map with thickness it is necessary to generate the rounded rectangle with different z ( i.e. + - half thickness, in the plane variant equal to ` 0,` ).

```javascript
 let positions = [

    -wi, -h2, 0, ...

```

Then you need to connect the two rounded rectangles. This is easy to do because you already have all the coordinates of the two rounded rectangles.

---

<div class="post-metadata">

**Author:** ![hofk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hofk/32/44944_2.png) [@hofk](https://discourse.threejs.org/u/hofk)\
**Post date:** [September 15, 2021, 4:33pm UTC](https://discourse.threejs.org/t/problems-applying-texture-to-extruded-geometry/29935/5 "2021-09-15T16:33:03Z")

</div>

![2021-09-15 18.29.03](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/b/4/b4324fb6fb84e83de685593ce0635a57893661e5.png)

The start is made, give me a little bit more time. I am not the fastest.  
⏳

* * *

The code for the two pages still without the connection.  
Interesting was the necessary change in the calculation of the uv’s.

```javascript

<!DOCTYPE html>
<!-- --> 
<head>
	<title> RoundedEdgeBoxFlat </title>
	<meta charset="utf-8" />
	<style>	
	body { margin: 0; }
	</style>
</head>
<body>
 
</body>
 
 <script type="module">
 
// @author hofk
 
import * as THREE from "../jsm/three.module.130.js";
import { OrbitControls } from "../jsm/OrbitControls.130.js";
 
const scene = new THREE.Scene( );
const camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.01, 10000 );
camera.position.set( 0, 1, 12 );
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xdedede, 1 );	
const container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
const axesHelper = new THREE.AxesHelper( 10 );
scene.add( axesHelper );

const controls = new OrbitControls( camera, renderer.domElement );

const material = new THREE.MeshBasicMaterial( { map: new THREE.TextureLoader( ).load( 'uvgrid01.png' ), side: THREE.DoubleSide, wireframe: false } );
//const material = new THREE.MeshBasicMaterial( { color: 0xff00ff, side: THREE.DoubleSide, wireframe: true } );

const w = 16;	// width
const h = 9;	// height
const t = 0.2;	// thick
const r = 2;	// radius corner
const s = 18;	// smoothness

const geometry = RoundedRectangle2( w, h, t, r, s );
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

animate( );  

function animate( ) {
	
	requestAnimationFrame( animate );
	renderer.render( scene, camera );
		
}

// non indexed BufferGeometry

function RoundedRectangle2( w, h, t, r, s ) { // width, height, thick, radius corner, smoothness
	
	// helper const's and let's
	const wi = w / 2 - r;	// inner width
	const hi = h / 2 - r;	// inner height
	const w2 = w / 2; // half width
	const h2 = h / 2; // half height

	let ul = r / w; // u left front side
	let ur = ( w - r ) / w; // u right front side
	const vl = r / h; // v low
	const vh = ( h - r ) / h;	// v high
	
	let phia, phib, xc, yc, uc, vc, cosa, sina, cosb, sinb;
	
	let positions = [];
	let uvs = [];
	
	// for front side
	let t2 = t / 2; // + half thick
	let u0 = ul;
	let u1 = ur;
	let u2 = 0;
	let u3 = 1;
	let sign = 1;
		
	for( let k = 0; k < 2; k ++ ) { // front and back side
		
		positions.push(
		
			-wi, -h2, t2, wi, -h2, t2, wi, h2, t2,
			-wi, -h2, t2, wi, h2, t2, -wi, h2, t2,
			-w2, -hi, t2, -wi, -hi, t2, -wi, hi, t2,
			-w2, -hi, t2, -wi, hi, t2, -w2, hi, t2,
			 wi, -hi, t2, w2, -hi, t2, w2, hi, t2,
			 wi, -hi, t2, w2, hi, t2, wi, hi, t2
			
		);
		
		uvs.push(
		
			u0, 0, u1, 0, u1, 1,
			u0, 0, u1, 1, u0, 1,
			u2, vl, u0, vl, u0, vh,
			u2, vl, u0, vh, u2, vh,
			u1, vl, u3, vl, u3, vh,
			u1, vl, u3, vh,	u1, vh
		
		);
			
		phia = 0; 
		
		for ( let i = 0; i < s * 4; i ++ ) {
		
			phib = Math.PI * 2 * ( i + 1 ) / ( 4 * s );
			
			cosa = Math.cos( phia );
			sina = Math.sin( phia );
			cosb = Math.cos( phib );
			sinb = Math.sin( phib );
			
			xc = i < s || i >= 3 * s ? wi : -wi;
			yc = i < 2 * s ? hi : -hi;
		
			positions.push( xc, yc, t2, xc + r * cosa, yc + r * sina, t2, xc + r * cosb, yc + r * sinb, t2 );
			
			uc = i < s || i >= 3 * s ? u1 : u0;
			vc = i < 2 * s ? vh : vl;
			
			uvs.push( uc, vc, uc + sign * ul * cosa, vc + vl * sina, uc + sign * ul * cosb, vc + vl * sinb );
 
			phia = phib;
				
		}
		
		// for back side
		t2 = -t2;	// - half thick
		u0 = ur;	// right left exchange
		u1 = ul;
		u2 = 1;
		u3 = 0;
		sign = -1;
		
	}
	
	const geometry = new THREE.BufferGeometry( );
	geometry.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( positions ), 3 ) );
	geometry.setAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( uvs ), 2 ) );
	
	return geometry;
	
}
 
</script>
</html>

```

---

<div class="post-metadata">

**Author:** ![hofk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hofk/32/44944_2.png) [@hofk](https://discourse.threejs.org/u/hofk)\
**Post date:** [September 16, 2021, 6:27pm UTC](https://discourse.threejs.org/t/problems-applying-texture-to-extruded-geometry/29935/6 "2021-09-16T18:27:45Z")

</div>

It works as intended.

 ![2021-09-16 20.19.59](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/d/d/ddc10e2b6e9a9d6db5225edad9f6ed0f927bb325.png)

 ![2021-09-16 20.18.06](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/a/6/a6a6b8e0a3748bbea188d323f8d1b1d18bdbd33e.png)

 ![2021-09-16 20.18.44](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/7/b/7b5f39ca4122bea211dbcc27fc44e09732a76d3c.png)

For the front side, the back side and the connection, one material each can be selected.

* * *

_The code still needs to be optimized. When it is done, I will post it as a resource and attach a link here._

* * *

UPDATE  
**link =\>** [Round-edged box flat](https://discourse.threejs.org/t/round-edged-box-flat/30012)
