;to store the temps indexesGlobal TempsCount%Dim TempI%(16);to store the normals of all triangles of a surfaceGlobal TrianglesCount%Dim TriangleNX#(16000)Dim TriangleNY#(16000)Dim TriangleNZ#(16000);to store the normals of the triangles which use a vertexGlobal NormalsCount%Dim NormalNX#(16)Dim NormalNY#(16)Dim NormalNZ#(16)Function UpdateVerticesNormals(Surface,Mesh) ;for each triangle of the surface TrianglesCount% = 0 For TI% = 0 To CountTriangles(Surface)-1 Step 1 ;retrieve the X,Y,Z world coordinates of Vertex0, Vertex1, Vertex2 of this triangle ;V0 V0I% = TriangleVertex(Surface,TI,0) TFormPoint(VertexX(Surface,V0I),VertexY(Surface,V0I),VertexZ(Surface,V0I),Mesh,0) V0GX# = TFormedX() : V0GY# = TFormedY() : V0GZ# = TFormedZ() ;V1 V1I% = TriangleVertex(Surface,TI,1) TFormPoint(VertexX(Surface,V1I),VertexY(Surface,V1I),VertexZ(Surface,V1I),Mesh,0) V1GX# = TFormedX() : V1GY# = TFormedY() : V1GZ# = TFormedZ() ;V2 V2I% = TriangleVertex(Surface,TI,2) TFormPoint(VertexX(Surface,V2I),VertexY(Surface,V2I),VertexZ(Surface,V2I),Mesh,0) V2GX# = TFormedX() : V2GY# = TFormedY() : V2GZ# = TFormedZ() ;calculate the normal of the triangle by using the world position of its vertices ;Vector 0->1 Vec01X# = V0GX - V1GX : Vec01Y# = V0GY - V1GY : Vec01Z# = V0GZ - V1GZ ;Vector 0->2 Vec02X# = V0GX - V2GX : Vec02Y# = V0GY - V2GY : Vec02Z# = V0GZ - V2GZ CPX# = ( Vec01Y * Vec02Z ) - ( Vec01Z * Vec02Y ) : CPY# = ( Vec01Z * Vec02X ) - ( Vec01X * Vec02Z ) : CPZ# = ( Vec01X * Vec02Y ) - ( Vec01Y * Vec02X ) Length# = Sqr( ( CPX * CPX ) + ( CPY * CPY ) + ( CPZ * CPZ ) ) NX# = CPX / Length : NY# = CPY / Length : NZ# = CPZ / Length ;store the normal in the triangles list TrianglesCount = TrianglesCount + 1 : TriI% = TrianglesCount TriangleNX(TriI) = NX : TriangleNY(TriI) = NY : TriangleNZ(TriI) = NZ Next ;for each vertex For VI% = 0 To CountVertices(Surface)-1 Step 1 ;identify which triangles use this vertex TempsCount% = 0 For TI% = 0 To CountTriangles(Surface)-1 Step 1 If( TriangleVertex(Surface,TI,0) = VI Or TriangleVertex(Surface,TI,1) = VI Or TriangleVertex(Surface,TI,2) = VI ) ;add the triangle to the temps list TempsCount = TempsCount + 1 : TemI% = TempsCount TempI(TemI) = TI EndIf Next ;for each identified triangle NormalsCount% = 0 For TemI% = 1 To TempsCount Step 1 TI% = TempI(TemI) ;get the triangle normal (previously calculated) NX# = TriangleNX(TI+1) : NY# = TriangleNY(TI+1) : NZ# = TriangleNZ(TI+1) ;add the normal to the normals list NormalsCount = NormalsCount + 1 : NorI% = NormalsCount NormalNX(NorI) = NX : NormalNY(NorI) = NY : NormalNZ(NorI) = NZ Next ;calculate the average normal vector, by considering the normals of the triangles using this vertex VNX# = 0 : VNY# = 0 : VNZ# = 0 For NorI% = 1 To NormalsCount Step 1 VNX = VNX + NormalNX(NorI) : VNY = VNY + NormalNY(NorI) : VNZ = VNZ + NormalNZ(NorI) Next VNX = VNX / NormalsCount : VNY = VNY / NormalsCount : VNZ = VNZ / NormalsCount ;set the normal of this vertex VertexNormal(Surface,VI,VNX,VNY,VNZ) NextEnd Function

It's quite slow though (10 seconds)

Graphics(640,360,32,2)Dim NormalNX#(10)For n% = 1 To 10 Step 1 NormalNX(n) = Rnd(0.0,1.0)NextVerNX# = 0For n% = 1 To 10 Step 1 VerNX = ( VerNX + NormalNX(n) ) / 2 NextDebugLog(VerNX)VerNX# = 0For n% = 1 To 10 Step 1 VerNX = VerNX + NormalNX(n) NextVerNX = VerNX / 10DebugLog(VerNX)WaitKey()End()

For my case it is fast enough (rooms made with premade parts), and for your case it is useless

Graphics3D 640,360,32,2SetBuffer BackBuffer()AmbientLight 64,64,64light = CreateLight() : LightColor light, 128,128,128camera = CreateCamera() : PositionEntity camera, 0,0,-10cube = CreateCube(): PositionEntity cube, -3,0,0 : EntityColor cube, 128,128,0copy = CopyMesh( cube ) : PositionEntity copy, 3, 0,0 : EntityColor copy, 0,128,128RotateMesh copy, 45,0,-45While Not KeyHit(1) TurnEntity cube, .1,0,.1 TurnEntity copy, .1,0, .1 RenderWorld() FlipWend

if a coder was sent models with no smoothing groups it would be cool to have a tool to process normals and maybe other things,

Copymesh does copy vertex normals. - not sure why you think it doesn't?

Graphics3D 640,360,32,2SeedRnd(MilliSecs())camera = CreateCamera() PositionEntity(camera,0,0,-10,True)cube = CreateCube() ScaleMesh(cube,1.0/2,1.0/2,1.0/2)PositionEntity(cube,-3,0,0,True)nmesh = CreateMesh() : nsurface = CreateSurface(nmesh)For n% = 1 To 5 Step 1 part = CopyMesh(cube) RotateMesh(part,Rand(-180,180),Rand(-180,180),0) PositionMesh(part,Rnd(-0.5,0.5),Rnd(-0.5,0.5),Rnd(-0.5,0.5)) ;AddMesh(part,nmesh) : FreeEntity(part) AddSurfaceToOtherSurface(GetSurface(part,1),part,GetSurface(nmesh,1),nmesh) : FreeEntity(part)NextPositionEntity(nmesh,3,0,0,True)light = CreateLight(1) LightColor(light,255,255,255)PositionEntity(light,-1000,1000,1000,True)RotateEntity(light,45,-45,0,True)AmbientLight(064,64,64)While Not KeyHit(1) TurnEntity cube, 0.1,0,0.1 TurnEntity nmesh, 0.1,0,0.1 SetBuffer(BackBuffer()) RenderWorld() Flip()WendFunction AddSurfaceToOtherSurface(Surface,Mesh,OSurface,OMesh) SurfaceVerticesCount% = CountVertices(Surface) ;DebugLog("SurfaceVerticesCount = "+SurfaceVerticesCount) OSurfaceVerticesCount% = CountVertices(OSurface) ;DebugLog("OSurfaceVerticesCount = "+OSurfaceVerticesCount) For VI% = 0 To CountVertices(Surface)-1 Step 1 ;DebugLog("VI = "+VI) VX# = VertexX(Surface,VI) VY# = VertexY(Surface,VI) VZ# = VertexZ(Surface,VI) VNX# = VertexNX(Surface,VI) VNY# = VertexNY(Surface,VI) VNZ# = VertexNZ(Surface,VI) VR% = VertexRed(Surface,VI) VG% = VertexGreen(Surface,VI) VB% = VertexBlue(Surface,VI) VA# = VertexAlpha(Surface,VI) VU# = VertexU(Surface,VI,0) VV# = VertexV(Surface,VI,0) If( OSurfaceVerticesCount = 0 ) NVI = VI Else If( OSurfaceVerticesCount > 0 ) NVI% = OSurfaceVerticesCount+VI EndIf ;DebugLog("NVI = "+NVI) AddVertex(OSurface,VX,VY,VZ) VertexNormal(OSurface,NVI,VNX,VNY,VNZ) VertexColor(OSurface,NVI,VR,VG,VB,VA) VertexTexCoords(OSurface,NVI,VU,VB) ;WaitKey() Next SurfaceTrianglesCount% = CountTriangles(Surface) ;DebugLog("SurfaceTrianglesCount = "+SurfaceTrianglesCount) OSurfaceTrianglesCount% = CountTriangles(OSurface) ;DebugLog("OSurfaceTrianglesCount = "+OSurfaceTrianglesCount) For TI% = 0 To CountTriangles(Surface)-1 Step 1 V0I% = TriangleVertex(Surface,TI,0) ;vertex0 V1I% = TriangleVertex(Surface,TI,1) ;vertex1 V2I% = TriangleVertex(Surface,TI,2) ;vertex2 ;DebugLog("oldtriangle"+TI+" "+V0I+","+V1I+","+V2I) If( OSurfaceVerticesCount = 0 ) NV0I% = V0I NV1I% = V1I NV2I% = V2I Else If( OSurfaceVerticesCount > 0 ) NV0I% = OSurfaceVerticesCount+V0I NV1I% = OSurfaceVerticesCount+V1I NV2I% = OSurfaceVerticesCount+V2I EndIf ;DebugLog("newtriangle"+TI+" "+NV0I+","+NV1I+","+NV2I) AddTriangle(OSurface,NV0I,NV1I,NV2I) Next ;WaitKey()End Function

VertexNormal(OSurface,NVI,NX,NY,NZ)

VertexNormal(OSurface,NVI,VNX,VNY,VNZ)