# Align models using normals

**URL:** <https://discourse.threejs.org/t/align-models-using-normals/81666>\
**Category:** Questions\
**Tags:** geometry\
**Created:** [April 26, 2025, 9:47pm UTC](https://discourse.threejs.org/t/align-models-using-normals/81666 "2025-04-26T21:47:05Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jaime\_Torrealba\_Cordova](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/jaime_torrealba_cordova/32/59223_2.png) [@Jaime\_Torrealba\_Cordova](https://discourse.threejs.org/u/Jaime_Torrealba_Cordova)\
**Post date:** [April 26, 2025, 9:47pm UTC](https://discourse.threejs.org/t/align-models-using-normals/81666/1 "2025-04-26T21:47:05Z")

</div>

You can see for example that when I call the function it get align but only the half of the base (sphere) and my rocks are random positioned. So far I got

```javascript
  alignToSurfaceNormal() {
        this.group.children.forEach((child) => {
            const position = child.position.clone();

            // Reset the quaternion to avoid cumulative transformations
            child.quaternion.identity();

            // Dynamically adjust the ray's origin to ensure it starts far enough above the geometry
            const boundingBox = new THREE.Box3().setFromObject(new THREE.Mesh(this.base));
            const rayOrigin = position.clone().add(new THREE.Vector3(0, boundingBox.max.y - boundingBox.min.y + 1, 0));

            // Cast a single downward ray
            const raycaster = new THREE.Raycaster();
            raycaster.set(rayOrigin, new THREE.Vector3(0, -1, 0));

            const intersects = raycaster.intersectObject(new THREE.Mesh(this.base), true);

            if (intersects.length > 0) {
                const closestIntersection = intersects[0];
                let normal = closestIntersection.face?.normal.clone();

                if (normal) {
                    // Transform the normal to world space
                    const matrix = closestIntersection.object.matrixWorld;
                    normal.applyMatrix3(new THREE.Matrix3().getNormalMatrix(matrix)).normalize();

                    // Skip alignment if normal.y > 0.5
                    if (normal.y > 0.5) {
                        //Check why normal act like this
                        return;
                    }
                    // Align the object's up direction to the normal
                    const quaternion = new THREE.Quaternion();
                    quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), normal);

                    child.quaternion.premultiply(quaternion);
                }
            }
        });
    }

```

---

<div class="post-metadata">

**Author:** ![Oxyn](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/oxyn/32/12902_2.png) [@Oxyn](https://discourse.threejs.org/u/Oxyn)\
**Post date:** [April 27, 2025, 3:32am UTC](https://discourse.threejs.org/t/align-models-using-normals/81666/2 "2025-04-27T03:32:32Z")

</div>

I personally use a virtual triangle after obtaining the face/points I want.  
it’s a (very) primitive aproach. Shouldn’t require world conversion, very consistent. Then using `lookAt` instead of quaternion operation.

```javascript
	//init a virtual triangle
	const tri = new THREE.Triangle(),
	//init points
	const a = new THREE.Vector3(), 
    const b = new THREE.Vector3(), 
    const c = new THREE.Vector3(),
	//vector to store normal
	const nRot = new THREE.Vector3();

	//copy position of vertices 
    a.fromBufferAttribute( positionAttribute, indexA );
    b.fromBufferAttribute( positionAttribute, indexB );
	c.fromBufferAttribute( positionAttribute, indexC );

	tri.set( a, b, c ); //create the triangle
    tri.getNormal( nRot );//get the normal

    myMesh.lookAt(nRot);

```

This is a multipurpose method. Doesn’t require raycast at all, if you know the vertices index.

---

<div class="post-metadata">

**Author:** ![Jaime\_Torrealba\_Cordova](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/jaime_torrealba_cordova/32/59223_2.png) [@Jaime\_Torrealba\_Cordova](https://discourse.threejs.org/u/Jaime_Torrealba_Cordova)\
**Post date:** [May 22, 2025, 9:28pm UTC](https://discourse.threejs.org/t/align-models-using-normals/81666/3 "2025-05-22T21:28:35Z")

</div>

At the end your answer did guide me but was not what I was looking for, the problem is the lookAt, just point to the face not aligning the Y axis to my normals. But I solve it like this:

```javascript
const normal = myTriangle.getNormal(new THREE.Vector3());
const quat = new THREE.Quaternion();
quat.setFromUnitVectors(new THREE.Vector3(0, 1, 0), normal.normalize());
child.quaternion.copy(quat);

```

Thanks man
