CHDIR ".\programs\samples\n54\big\3dsviewer" '----sub declarations '--file stuff DECLARE SUB ReadChunkInfo (ChunkInfoHolder AS ANY, BytePosition AS LONG) DECLARE SUB SkipChunk (ChunkInfoHolder AS ANY, BytePosition AS LONG) DECLARE SUB SearchForChunk (ChunkInfoHolder AS ANY) DECLARE SUB ReadObject () '--3D engine stuff DECLARE SUB multiplyMatrices (matrixA(), matrixB(), result()) DECLARE SUB getScalingMatrix (sX, sY, sZ, result()) DECLARE SUB getRotationXMatrix (rX, result()) DECLARE SUB getRotationYMatrix (rY, result()) DECLARE SUB getRotationZMatrix (rZ, result()) DECLARE SUB getTranslationMatrix (tX, tY, tZ, result()) DECLARE SUB getCombinedMatrix (sX, sY, sZ, rX, rY, rZ, tX, tY, tZ, temp(), temp2(), result()) DECLARE SUB getNewXYZ (X, Y, Z, combinedMatrix()) DECLARE SUB getScreenXY (X, Y, Z) '----global declarations REM $DYNAMIC DIM SHARED PointsArray(0, 0) AS SINGLE DIM SHARED NewPointsArray(0, 0) AS LONG DIM SHARED FaceArray(0, 0) AS INTEGER REM $STATIC DIM SHARED numberVertices AS INTEGER DIM SHARED numberFaces AS INTEGER DIM SHARED CurrentBytePosition AS LONG DIM SHARED FindChunk$ '----type definitions TYPE ChunkInfo ID AS INTEGER Size AS LONG Position AS LONG END TYPE '----open file CLS PRINT "Would you like to view car.3ds (y/n)?" DO k$ = INKEY$ LOOP UNTIL k$<>"" IF UCASE$(k$) = "N" THEN INPUT "Please input the file you wish to load:", fileName$ ELSE fileName$="car.3ds" END IF OPEN fileName$ FOR BINARY AS #1 '----initialise variables sX = 5 sY = 5 sZ = 5 rX = 0 rY = 0 rZ = 0 tX = 0 tY = 0 tZ = 500 currentFrame = 0 '----allocate space for matrix calcs DIM temp(3, 3) DIM temp2(3, 3) DIM result(3, 3) '----MAIN PROGRAM CLS PRINT "3DS Object Viewer 0.5" PRINT "---------------------" PRINT "By David Llewellyn" PRINT "24/10/2004" PRINT "" CALL ReadObject PRINT "" PRINT "Press any key to continue" DO LOOP UNTIL INKEY$ > CHR$(0) '3D-Section SCREEN 7, , 0, 1 Colour = 4 oldTime = TIMER DO CALL getCombinedMatrix(sX, sY, sZ, rX, rY, rZ, tX, tY, tZ, temp(), temp2(), result()) CLS FOR i = 0 TO numberVertices'load screen coordinates into new array X = PointsArray(0, i) Y = PointsArray(1, i) Z = PointsArray(2, i) CALL getNewXYZ(X, Y, Z, result()) CALL getScreenXY(X, Y, Z) NewPointsArray(0, i) = X NewPointsArray(1, i) = Y NEXT i'load screen coordinates into new array FOR i = 0 TO numberFaces - 1'draw faces 'line from point 0 to 1 LINE (NewPointsArray(0, FaceArray(0, i)), NewPointsArray(1, FaceArray(0, i)))-(NewPointsArray(0, FaceArray(1, i)), NewPointsArray(1, FaceArray(1, i))), Colour 'line from point 1 to 2 LINE (NewPointsArray(0, FaceArray(1, i)), NewPointsArray(1, FaceArray(1, i)))-(NewPointsArray(0, FaceArray(2, i)), NewPointsArray(1, FaceArray(2, i))), Colour 'line from point 2 to 0 LINE (NewPointsArray(0, FaceArray(2, i)), NewPointsArray(1, FaceArray(2, i)))-(NewPointsArray(0, FaceArray(0, i)), NewPointsArray(1, FaceArray(0, i))), Colour NEXT i'draw faces PCOPY 0, 1 frames = frames + 1 A$ = INKEY$ rX = rX + .00065 rY = rY + .00545 IF A$ = "=" THEN tZ = tZ - 5 IF A$ = "-" THEN tZ = tZ + 5 LOOP UNTIL A$ = CHR$(27) newTime = TIMER timeTaken = newTime - oldTime SCREEN 13 PRINT USING "##.##"; frames / timeTaken PRINT "frames per second" DO LOOP UNTIL INKEY$ > CHR$(0) SYSTEM SUB getCombinedMatrix (sX, sY, sZ, rX, rY, rZ, tX, tY, tZ, temp(), temp2(), result()) ERASE temp2 CALL getScalingMatrix(sX, sY, sZ, result()) CALL getRotationXMatrix(rX, temp()) CALL multiplyMatrices(result(), temp(), temp2())'combine with x rotation CALL getRotationYMatrix(rY, temp()) ERASE result CALL multiplyMatrices(temp2(), temp(), result())'combine with y rotation CALL getRotationZMatrix(rZ, temp()) ERASE temp2 CALL multiplyMatrices(result(), temp(), temp2())'combine with z rotation CALL getTranslationMatrix(tX, tY, tZ, temp()) ERASE result CALL multiplyMatrices(temp2(), temp(), result())'combine with translation END SUB SUB getNewXYZ (X, Y, Z, combinedMatrix()) newX = (combinedMatrix(0, 0) * X) + (combinedMatrix(0, 1) * Y) + (combinedMatrix(0, 2) * Z) + combinedMatrix(0, 3)'new X point newY = (combinedMatrix(1, 0) * X) + (combinedMatrix(1, 1) * Y) + (combinedMatrix(1, 2) * Z) + combinedMatrix(1, 3)'new Y point newZ = (combinedMatrix(2, 0) * X) + (combinedMatrix(2, 1) * Y) + (combinedMatrix(2, 2) * Z) + combinedMatrix(2, 3)'new Z point X = newX Y = newY Z = newZ END SUB SUB getRotationXMatrix (rX, result()) result(0, 0) = 1 result(1, 0) = 0 result(2, 0) = 0 result(3, 0) = 0 result(0, 1) = 0 result(1, 1) = COS(rX) result(2, 1) = SIN(rX) result(3, 1) = 0 result(0, 2) = 0 result(1, 2) = -SIN(rX) result(2, 2) = COS(rX) result(3, 2) = 0 result(0, 3) = 0 result(1, 3) = 0 result(2, 3) = 0 result(3, 3) = 1 END SUB SUB getRotationYMatrix (rY, result()) result(0, 0) = COS(rY) result(1, 0) = 0 result(2, 0) = -SIN(rY) result(3, 0) = 0 result(0, 1) = 0 result(1, 1) = 1 result(2, 1) = 0 result(3, 1) = 0 result(0, 2) = SIN(rY) result(1, 2) = 0 result(2, 2) = COS(rY) result(3, 2) = 0 result(0, 3) = 0 result(1, 3) = 0 result(2, 3) = 0 result(3, 3) = 1 END SUB SUB getRotationZMatrix (rZ, result()) result(0, 0) = COS(rZ) result(1, 0) = SIN(rZ) result(2, 0) = 0 result(3, 0) = 0 result(0, 1) = -SIN(rZ) result(1, 1) = COS(rZ) result(2, 1) = 0 result(3, 1) = 0 result(0, 2) = 0 result(1, 2) = 0 result(2, 2) = 1 result(3, 2) = 0 result(0, 3) = 0 result(1, 3) = 0 result(2, 3) = 0 result(3, 3) = 1 END SUB SUB getScalingMatrix (sX, sY, sZ, result()) result(0, 0) = sX result(1, 0) = 0 result(2, 0) = 0 result(3, 0) = 0 result(0, 1) = 0 result(1, 1) = sY result(2, 1) = 0 result(3, 1) = 0 result(0, 2) = 0 result(1, 2) = 0 result(2, 2) = sZ result(3, 2) = 0 result(0, 3) = 0 result(1, 3) = 0 result(2, 3) = 0 result(3, 3) = 1 END SUB SUB getScreenXY (X, Y, Z) IF Z = 0 THEN X = X * 280 Y = Y * 240 ELSE X = (X * 280) / Z Y = (Y * 240) / Z END IF X = INT(X + 160) Y = INT(Y + 100) END SUB SUB getTranslationMatrix (tX, tY, tZ, result()) result(0, 0) = 1 result(1, 0) = 0 result(2, 0) = 0 result(3, 0) = 0 result(0, 1) = 0 result(1, 1) = 1 result(2, 1) = 0 result(3, 1) = 0 result(0, 2) = 0 result(1, 2) = 0 result(2, 2) = 1 result(3, 2) = 0 result(0, 3) = tX result(1, 3) = tY result(2, 3) = tZ result(3, 3) = 1 END SUB SUB multiplyMatrices (matrixA(), matrixB(), result()) FOR i = 0 TO 3 FOR j = 0 TO 3 FOR k = 0 TO 3 result(j, i) = result(j, i) + (matrixB(j, k) * matrixA(k, i)) NEXT k NEXT j NEXT i END SUB SUB ReadChunkInfo (ChunkInfoHolder AS ChunkInfo, BytePosition AS LONG) GET #1, BytePosition, ChunkInfoHolder.ID GET #1, BytePosition + 2, ChunkInfoHolder.Size ChunkInfoHolder.Position = BytePosition END SUB SUB ReadObject DIM ChunkH AS ChunkInfo CurrentBytePosition = 1'start of file CALL ReadChunkInfo(ChunkH, CurrentBytePosition) FindChunk$ = "3D3D" CALL SearchForChunk(ChunkH)'CBP should now be 3D3D(EDIT3DS) CALL ReadChunkInfo(ChunkH, CurrentBytePosition) FindChunk$ = "4000" CALL SearchForChunk(ChunkH)'CBP should now be 4000(NAMED_OBJECT) '\/Read & display object name i = 0 DO ObjectName$ = " " GET #1, CurrentBytePosition + 6 + i, ObjectName$ i = i + 1 LOOP UNTIL ASC(ObjectName$) = 0 ObjectName$ = STRING$(i - 1, " ") GET #1, CurrentBytePosition + 6, ObjectName$ PRINT "Object Name: "; ObjectName$ '/\Read & display object name CALL ReadChunkInfo(ChunkH, CurrentBytePosition) ChunkH.Position = CurrentBytePosition + i'skip past name area ChunkH.Size = ChunkH.Size - i'skip past name area FindChunk$ = "4100" CALL SearchForChunk(ChunkH) 'CBP should now be 4100(OBJ_MESH) CALL ReadChunkInfo(ChunkH, CurrentBytePosition) DIM BackupBytePosition AS LONG BackupBytePosition = CurrentBytePosition FindChunk$ = "4110" CALL SearchForChunk(ChunkH)'CBP should now be 4110(MESH_VERTICES) '\/Read & display vertices 'Number of vertices CurrentBytePosition = CurrentBytePosition + 6 GET #1, CurrentBytePosition, numberVertices PRINT "Number of vertices:"; numberVertices REDIM PointsArray(2, numberVertices) AS SINGLE'allocate space for 3d points REDIM NewPointsArray(1, numberVertices) AS LONG'allocate space for screen points CurrentBytePosition = CurrentBytePosition + 2 'Actual vertice data DIM vertex AS SINGLE FOR i = 0 TO numberVertices GET #1, CurrentBytePosition, vertex 'PRINT "X-vertex"; vertex PointsArray(0, i) = vertex CurrentBytePosition = CurrentBytePosition + 4 GET #1, CurrentBytePosition, vertex 'PRINT "Y-vertex"; vertex PointsArray(1, i) = vertex CurrentBytePosition = CurrentBytePosition + 4 GET #1, CurrentBytePosition, vertex 'PRINT "Z-vertex"; vertex PointsArray(2, i) = vertex CurrentBytePosition = CurrentBytePosition + 4 NEXT i '/\Read & display vertices CALL ReadChunkInfo(ChunkH, BackupBytePosition)'ChunkH should now be 4100(OBJ_MESH) FindChunk$ = "4120" CALL SearchForChunk(ChunkH)'CBP should now be 4120(MESH_FACES) '\/Read & display faces 'Number of faces CurrentBytePosition = CurrentBytePosition + 6 GET #1, CurrentBytePosition, numberFaces PRINT "Number of faces:"; numberFaces REDIM FaceArray(2, numberFaces) AS INTEGER'allocate space for face points CurrentBytePosition = CurrentBytePosition + 2 'Actual face data DIM face AS INTEGER FOR i = 0 TO numberFaces GET #1, CurrentBytePosition, face 'PRINT "Face-point 1:"; face FaceArray(0, i) = face CurrentBytePosition = CurrentBytePosition + 2 GET #1, CurrentBytePosition, face 'PRINT "Face-point 2:"; face FaceArray(1, i) = face CurrentBytePosition = CurrentBytePosition + 2 GET #1, CurrentBytePosition, face 'PRINT "Face-point 3:"; face FaceArray(2, i) = face CurrentBytePosition = CurrentBytePosition + 2 GET #1, CurrentBytePosition, face 'PRINT "Face-visibility:"; face CurrentBytePosition = CurrentBytePosition + 2 NEXT i '\/Read & display faces END SUB SUB SearchForChunk (ChunkInfoHolder AS ChunkInfo) DIM InnerBytePosition AS LONG DIM MaxBytePosition AS LONG InnerBytePosition = ChunkInfoHolder.Position + 6 MaxBytePosition = ChunkInfoHolder.Position + ChunkInfoHolder.Size ChunkName$ = HEX$(ChunkInfoHolder.ID) Found = 0 DO CALL ReadChunkInfo(ChunkInfoHolder, InnerBytePosition) IF FindChunk$ = HEX$(ChunkInfoHolder.ID) THEN Found = 1 ELSE CALL SkipChunk(ChunkInfoHolder, InnerBytePosition) END IF LOOP UNTIL InnerBytePosition >= MaxBytePosition OR Found = 1 OR INKEY$ = CHR$(27) OR ChunkInfoHolder.Size = 0 IF Found = 0 THEN PRINT "" PRINT FindChunk$; " was not found within "; ChunkName$; "!" PRINT "" SYSTEM ELSE CurrentBytePosition = ChunkInfoHolder.Position END IF END SUB SUB SkipChunk (ChunkInfoHolder AS ChunkInfo, BytePosition AS LONG) BytePosition = BytePosition + ChunkInfoHolder.Size END SUB