33
44import {
55 AsyncController ,
6+ BoundingBox ,
67 command ,
78 Component ,
89 ComponentNode ,
910 GeometryNode ,
11+ LineType ,
1012 MathUtils ,
1113 Matrix4 ,
12- MeshLike ,
1314 MeshNode ,
1415 Plane ,
1516 PlaneAngle ,
@@ -34,7 +35,7 @@ export class ArrayCommand extends MultistepCommand {
3435 private _planeAngle : PlaneAngle | undefined ;
3536 private _meshId : number | undefined = undefined ;
3637 protected models ?: VisualNode [ ] ;
37- protected meshData ?: MeshLike ;
38+ protected positions ?: number [ ] ;
3839
3940 @Property . define ( "common.isGroup" )
4041 get isGroup ( ) {
@@ -130,71 +131,26 @@ export class ArrayCommand extends MultistepCommand {
130131 }
131132
132133 protected override async canExcute ( ) : Promise < boolean > {
134+ if ( this . positions ) return true ;
135+
133136 if ( ! ( await this . ensureSelectedModels ( ) ) ) return false ;
134137
135- const meshes = this . collectFaceMeshes ( ) ;
136- this . meshData = this . concatFaceMeshData ( meshes ) ;
138+ this . collectionPosition ( ) ;
137139
138140 return true ;
139141 }
140142
141- private collectFaceMeshes ( ) : MeshLike [ ] {
142- return (
143- this . models ?. map ( ( model ) => {
144- let mesh : MeshLike | undefined ;
145- if ( model instanceof MeshNode ) {
146- mesh = model . mesh as MeshLike ;
147- } else if ( model instanceof GeometryNode ) {
148- mesh = model . mesh . faces ! ;
149- } else if ( model instanceof ComponentNode ) {
150- mesh = this . concatFaceMeshData ( [
151- model . component . mesh . face ,
152- model . component . mesh . surface as MeshLike ,
153- ] ) ;
154- }
155- if ( ! mesh ) {
156- throw new Error ( "model not support array" ) ;
157- }
158-
159- return {
160- position : new Float32Array ( model . transform . ofPoints ( mesh . position ) ) ,
161- normal : new Float32Array ( model . transform . ofVectors ( mesh . normal ) ) ,
162- index : mesh . index ,
163- uv : mesh . uv ,
164- } ;
165- } ) ?? [ ]
166- ) ;
167- }
168-
169- private concatFaceMeshData ( datas : MeshLike [ ] ) {
170- const positionLength = datas . reduce ( ( prev , cur ) => prev + cur . position . length , 0 ) ;
171- const position = new Float32Array ( positionLength ) ;
172- const normal = new Float32Array ( positionLength ) ;
173- const uv = new Float32Array ( datas . reduce ( ( prev , cur ) => prev + cur . uv . length , 0 ) ) ;
174- const index = new Uint32Array ( datas . reduce ( ( prev , cur ) => prev + cur . index . length , 0 ) ) ;
175-
176- let uvOffset = 0 ;
177- let positionOffset = 0 ;
178- let indexOffset = 0 ;
179- for ( const data of datas ) {
180- position . set ( data . position , positionOffset ) ;
181- normal . set ( data . normal , positionOffset ) ;
182- index . set (
183- data . index . map ( ( x ) => x + positionOffset / 3 ) ,
184- indexOffset ,
185- ) ;
186- uv . set ( data . uv , uvOffset ) ;
187-
188- uvOffset += data . uv . length ;
189- positionOffset += data . position . length ;
190- indexOffset += data . index . length ;
191- }
192- return {
193- position,
194- normal,
195- index,
196- uv,
197- } ;
143+ private collectionPosition ( ) {
144+ this . positions = this . models ! . flatMap ( ( model ) => {
145+ if ( model instanceof MeshNode ) {
146+ return model . mesh . position ? model . transform . ofPoints ( model . mesh . position ) : [ ] ;
147+ } else if ( model instanceof GeometryNode ) {
148+ return model . mesh . edges ?. position ? model . transform . ofPoints ( model . mesh . edges . position ) : [ ] ;
149+ } else if ( model instanceof ComponentNode ) {
150+ return Array . from ( BoundingBox . wireframe ( model . boundingBox ( ) ! ) . position ) ;
151+ }
152+ return [ ] ;
153+ } ) ;
198154 }
199155
200156 override afterExecute ( ) {
@@ -217,10 +173,28 @@ export class ArrayCommand extends MultistepCommand {
217173 if ( ! this . circularPattern ) {
218174 count = this . numberX * this . numberY * this . numberZ ;
219175 }
220- const matrixs = new Array < Matrix4 > ( count ) . fill ( new Matrix4 ( ) ) ;
221- this . _meshId = this . document . visual . context . displayInstancedMesh ( this . meshData ! , matrixs , 0.2 ) ;
176+
177+ const positions = new Float32Array ( this . positions ! . length * count ) ;
178+ for ( let i = 0 ; i < count ; i ++ ) {
179+ positions . set ( this . positions ! , i * this . positions ! . length ) ;
180+ }
181+
182+ this . _meshId = this . document . visual . context . displayLineSegments ( {
183+ position : positions ,
184+ lineType : LineType . Solid ,
185+ range : [ ] ,
186+ } ) ;
222187 }
223188
189+ private readonly updatePosition = ( matrixs : Matrix4 [ ] ) => {
190+ const positions = new Float32Array ( this . positions ! . length * matrixs . length ) ;
191+ for ( let i = 0 ; i < matrixs . length ; i ++ ) {
192+ positions . set ( matrixs [ i ] . ofPoints ( this . positions ! ) , i * this . positions ! . length ) ;
193+ }
194+
195+ this . document . visual . context . setPosition ( this . _meshId ! , positions ) ;
196+ } ;
197+
224198 private getBoxTransforms ( xvec : XYZ , yvec : XYZ , zvec : XYZ ) {
225199 const count = this . numberX * this . numberY * this . numberZ ;
226200 const transforms = new Array < Matrix4 > ( count ) ;
@@ -323,7 +297,7 @@ export class ArrayCommand extends MultistepCommand {
323297 this . _planeAngle ! . plane . normal ,
324298 MathUtils . degToRad ( this . _planeAngle ! . angle ) ,
325299 ) ;
326- this . document . visual . context . setInstanceMatrix ( this . _meshId ! , transforms ) ;
300+ this . updatePosition ( transforms ) ;
327301
328302 result . push (
329303 this . meshCreatedShape (
@@ -354,7 +328,7 @@ export class ArrayCommand extends MultistepCommand {
354328 }
355329 const vector = p . sub ( this . stepDatas [ 0 ] . point ! ) ;
356330 const matrixs = this . getBoxTransforms ( vector , XYZ . zero , XYZ . zero ) ;
357- this . document . visual . context . setInstanceMatrix ( this . _meshId ! , matrixs ) ;
331+ this . updatePosition ( matrixs ) ;
358332
359333 return [
360334 this . meshPoint ( this . stepDatas [ 0 ] . point ! ) ,
@@ -379,7 +353,7 @@ export class ArrayCommand extends MultistepCommand {
379353 }
380354
381355 const matrixs = this . boxArrayMatrixs ( index , xvec , yvec , normal , p ) ;
382- this . document . visual . context . setInstanceMatrix ( this . _meshId ! , matrixs ) ;
356+ this . updatePosition ( matrixs ) ;
383357 return [
384358 this . meshLine ( this . stepDatas [ 1 ] . point ! , p ) ,
385359 this . meshPoint ( p ) ,
@@ -389,25 +363,33 @@ export class ArrayCommand extends MultistepCommand {
389363 } ;
390364 } ;
391365
392- private boxArrayMatrixs ( index : number , xvec : XYZ , yvec : XYZ , normal : XYZ , end : XYZ ) {
366+ private boxArrayMatrixs ( index : 2 | 3 , xvec : XYZ , yvec : XYZ , normal : XYZ , end : XYZ ) {
367+ const x = xvec . multiply ( this . stepDatas [ 1 ] . point ! . sub ( this . stepDatas [ 0 ] . point ! ) . dot ( xvec ) ) ;
393368 let y : XYZ , z : XYZ ;
394369 if ( index === 2 ) {
395- y = yvec . multiply ( end . sub ( this . stepDatas [ 1 ] . point ! ) . dot ( yvec ) ) ;
370+ y = yvec . multiply ( end . sub ( this . stepDatas [ 0 ] . point ! ) . dot ( yvec ) ) ;
396371 z = XYZ . zero ;
397372 } else {
398- y = yvec . multiply ( this . stepDatas [ 2 ] . point ! . sub ( this . stepDatas [ 1 ] . point ! ) . dot ( yvec ) ) ;
399- z = normal . multiply ( end . sub ( this . stepDatas [ 1 ] . point ! ) . dot ( normal ) ) ;
373+ y = yvec . multiply ( this . stepDatas [ 2 ] . point ! . sub ( this . stepDatas [ 0 ] . point ! ) . dot ( yvec ) ) ;
374+ z = normal . multiply ( end . sub ( this . stepDatas [ 0 ] . point ! ) . dot ( normal ) ) ;
400375 }
401- return this . getBoxTransforms ( xvec , y , z ) ;
376+ return this . getBoxTransforms ( x , y , z ) ;
402377 }
403378
404379 private boxPlaneInfo ( index : number ) {
405380 const plane =
406381 this . stepDatas [ 1 ] . plane ??
407382 this . findPlane ( this . stepDatas [ 1 ] . view , this . stepDatas [ 0 ] . point ! , this . stepDatas [ 1 ] . point ) ;
408- const xvec = this . stepDatas [ 1 ] . point ! . sub ( this . stepDatas [ 0 ] . point ! ) ;
409- const yvec = plane . normal . isParallelTo ( xvec ) ? XYZ . unitY : plane . normal . cross ( xvec ) . normalize ( ) ! ;
410- const normal = xvec . cross ( yvec ) . normalize ( ) ! ;
383+
384+ const xvec = this . stepDatas [ 1 ] . point ! . sub ( this . stepDatas [ 0 ] . point ! ) . normalize ( ) ! ;
385+ let normal = plane . normal ;
386+ if ( normal . isEqualTo ( xvec ) ) {
387+ normal = XYZ . unitZ ;
388+ } else if ( normal . isEqualTo ( xvec . reverse ( ) ) ) {
389+ normal = XYZ . unitZ . reverse ( ) ;
390+ }
391+ const yvec = normal . cross ( xvec ) . normalize ( ) ! ;
392+
411393 const ray =
412394 index === 2
413395 ? new Ray ( this . stepDatas [ 1 ] . point ! , yvec )
0 commit comments