Просмотр исходного кода

ColladaLoader: Add suport for `polygons` primitive. (#33143)

Michael Herzog 1 месяц назад
Родитель
Сommit
ec9dc3fd32

+ 101 - 7
examples/jsm/loaders/collada/ColladaComposer.js

@@ -32,10 +32,12 @@ import {
 	Skeleton,
 	Skeleton,
 	SkinnedMesh,
 	SkinnedMesh,
 	SpotLight,
 	SpotLight,
+	Triangle,
 	Vector2,
 	Vector2,
 	Vector3,
 	Vector3,
 	VectorKeyframeTrack,
 	VectorKeyframeTrack,
-	SRGBColorSpace
+	SRGBColorSpace,
+	ShapeUtils
 } from 'three';
 } from 'three';
 
 
 import { getElementsByTagName, parseFloats } from './ColladaParser.js';
 import { getElementsByTagName, parseFloats } from './ColladaParser.js';
@@ -1626,6 +1628,7 @@ class ColladaComposer {
 					count = primitive.count * 3;
 					count = primitive.count * 3;
 					break;
 					break;
 
 
+				case 'polygons':
 				case 'polylist':
 				case 'polylist':
 
 
 					for ( let g = 0; g < primitive.count; g ++ ) {
 					for ( let g = 0; g < primitive.count; g ++ ) {
@@ -1674,7 +1677,7 @@ class ColladaComposer {
 
 
 				const input = inputs[ name ];
 				const input = inputs[ name ];
 
 
-				switch ( name )	{
+				switch ( name ) {
 
 
 					case 'VERTEX':
 					case 'VERTEX':
 						for ( const key in vertices ) {
 						for ( const key in vertices ) {
@@ -1856,13 +1859,103 @@ class ColladaComposer {
 
 
 				} else if ( count > 4 ) {
 				} else if ( count > 4 ) {
 
 
-					for ( let k = 1, kl = ( count - 2 ); k <= kl; k ++ ) {
+					const vertices = [];
 
 
-						const a = index + stride * 0;
-						const b = index + stride * k;
-						const c = index + stride * ( k + 1 );
+					// prepare vertices which represent the polygon's contour
 
 
-						pushVector( a ); pushVector( b ); pushVector( c );
+					for ( let k = 0; k < count; k ++ ) {
+
+						const a = index + stride * k;
+						const positionIndex = indices[ a ] * sourceStride;
+
+						const x = sourceArray[ positionIndex ];
+						const y = sourceArray[ positionIndex + 1 ];
+						const z = sourceArray[ positionIndex + 2 ];
+
+						vertices.push( new Vector3( x, y, z ) );
+
+					}
+
+					// determine surface normal
+
+					const normal = new Vector3();
+					const _triangle = new Triangle();
+
+					_triangle.a = vertices[ 0 ];
+					_triangle.b = vertices[ 1 ];
+					_triangle.c = vertices[ 2 ];
+					_triangle.getNormal( normal );
+
+					// project to 2D and triangulate
+
+					const vertices2D = [];
+
+					if ( Math.abs( normal.x ) > Math.abs( normal.y ) && Math.abs( normal.x ) > Math.abs( normal.z ) ) {
+
+						for ( let k = 0; k < count; k ++ ) {
+
+							vertices2D.push( new Vector2( vertices[ k ].y, vertices[ k ].z ) );
+
+						}
+
+					} else if ( Math.abs( normal.y ) > Math.abs( normal.z ) ) {
+
+						for ( let k = 0; k < count; k ++ ) {
+
+							vertices2D.push( new Vector2( vertices[ k ].x, vertices[ k ].z ) );
+
+						}
+
+					} else {
+
+						for ( let k = 0; k < count; k ++ ) {
+
+							vertices2D.push( new Vector2( vertices[ k ].x, vertices[ k ].y ) );
+
+						}
+
+					}
+
+					const isClockWise = ShapeUtils.isClockWise( vertices2D );
+
+					if ( isClockWise === true ) {
+
+						vertices2D.reverse();
+
+					}
+
+					const faces = ShapeUtils.triangulateShape( vertices2D, [] );
+
+					// build indices
+
+					for ( let k = 0; k < faces.length; k ++ ) {
+
+						const face = faces[ k ];
+
+						let i0, i1, i2;
+
+						if ( isClockWise === false ) {
+
+							i0 = face[ 0 ];
+							i1 = face[ 1 ];
+							i2 = face[ 2 ];
+
+
+						} else {
+
+							i0 = count - 1 - face[ 0 ];
+							i1 = count - 1 - face[ 2 ];
+							i2 = count - 1 - face[ 1 ];
+
+						}
+
+						const a = index + stride * i0;
+						const b = index + stride * i1;
+						const c = index + stride * i2;
+
+						pushVector( a );
+						pushVector( b );
+						pushVector( c );
 
 
 					}
 					}
 
 
@@ -2627,6 +2720,7 @@ class ColladaComposer {
 					break;
 					break;
 
 
 				case 'triangles':
 				case 'triangles':
+				case 'polygons':
 				case 'polylist':
 				case 'polylist':
 					if ( skinning ) {
 					if ( skinning ) {
 
 

+ 6 - 3
examples/jsm/loaders/collada/ColladaParser.js

@@ -1231,9 +1231,6 @@ class ColladaParser {
 					break;
 					break;
 
 
 				case 'polygons':
 				case 'polygons':
-					console.warn( 'THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName );
-					break;
-
 				case 'lines':
 				case 'lines':
 				case 'linestrips':
 				case 'linestrips':
 				case 'polylist':
 				case 'polylist':
@@ -1353,6 +1350,12 @@ class ColladaParser {
 
 
 		}
 		}
 
 
+		if ( primitive.type === 'polygons' ) {
+
+			primitive.vcount = [ primitive.p.length / primitive.stride ];
+
+		}
+
 		return primitive;
 		return primitive;
 
 
 	}
 	}

+ 47 - 0
examples/models/collada/test/polygons.dae

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+  <asset>
+    <created>2026-03-09T12:00:00Z</created>
+    <modified>2026-03-09T12:00:00Z</modified>
+    <unit name="meter" meter="1.0"/>
+    <up_axis>Y_UP</up_axis>
+  </asset>
+  <library_geometries>
+    <geometry id="QuadGeom" name="Quad">
+      <mesh>
+        <source id="Quad-pos">
+          <float_array id="Quad-pos-array" count="12">
+            -1.0 0.0  1.0
+             1.0 0.0  1.0
+             1.0 0.0 -1.0
+            -1.0 0.0 -1.0
+          </float_array>
+          <technique_common>
+            <accessor source="#Quad-pos-array" count="4" stride="3">
+              <param name="X" type="float"/>
+              <param name="Y" type="float"/>
+              <param name="Z" type="float"/>
+            </accessor>
+          </technique_common>
+        </source>
+        <vertices id="Quad-vertices">
+          <input semantic="POSITION" source="#Quad-pos"/>
+        </vertices>
+        <polygons count="1">
+          <input semantic="VERTEX" source="#Quad-vertices" offset="0"/>
+          <p>0 1 2 3</p>
+        </polygons>
+      </mesh>
+    </geometry>
+  </library_geometries>
+  <library_visual_scenes>
+    <visual_scene id="Scene" name="Scene">
+      <node id="QuadNode" name="QuadNode">
+        <instance_geometry url="#QuadGeom"/>
+      </node>
+    </visual_scene>
+  </library_visual_scenes>
+  <scene>
+    <instance_visual_scene url="#Scene"/>
+  </scene>
+</COLLADA>

+ 49 - 0
examples/models/collada/test/polygons_concave.dae

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+  <asset>
+    <created>2026-03-09T12:30:00Z</created>
+    <modified>2026-03-09T12:30:00Z</modified>
+    <unit name="meter" meter="1.0"/>
+    <up_axis>Y_UP</up_axis>
+  </asset>
+  <library_geometries>
+    <geometry id="ConcaveGeom" name="ConcaveL">
+      <mesh>
+        <source id="Concave-pos">
+          <float_array id="Concave-pos-array" count="18">
+             0.0 0.0 -1.0
+            -1.0 0.0 -1.0
+            -1.0 0.0  1.0
+             2.0 0.0  1.0
+             2.0 0.0  0.0
+             0.0 0.0  0.0
+          </float_array>
+          <technique_common>
+            <accessor source="#Concave-pos-array" count="6" stride="3">
+              <param name="X" type="float"/>
+              <param name="Y" type="float"/>
+              <param name="Z" type="float"/>
+            </accessor>
+          </technique_common>
+        </source>
+        <vertices id="Concave-vertices">
+          <input semantic="POSITION" source="#Concave-pos"/>
+        </vertices>
+        <polygons count="1">
+          <input semantic="VERTEX" source="#Concave-vertices" offset="0"/>
+          <p>0 1 2 3 4 5</p>
+        </polygons>
+      </mesh>
+    </geometry>
+  </library_geometries>
+  <library_visual_scenes>
+    <visual_scene id="Scene">
+      <node id="ConcaveNode">
+        <instance_geometry url="#ConcaveGeom"/>
+      </node>
+    </visual_scene>
+  </library_visual_scenes>
+  <scene>
+    <instance_visual_scene url="#Scene"/>
+  </scene>
+</COLLADA>

粤ICP备19079148号