home *** CD-ROM | disk | FTP | other *** search
/ World of Graphics / WOGRAPH.BIN / 766.TGA2POV2.BAS < prev    next >
BASIC Source File  |  1992-11-02  |  13KB  |  374 lines

  1. '   TGA2POV 2.0 copyright 1992 Scott Steeves
  2. '   Converts B&W 8-bit Targas to PoV 1.0 objects
  3. '
  4. '   This program is given as freeware, in the spirit of PoV.
  5. '
  6. '   Feel free to change this code, but if you do,
  7. '   please send me a copy and a message at one of the following BBSes:
  8. '
  9. '   You Can Call Me Ray  1-708-358-8721
  10. '   Channel 1            1-617-354-8873
  11.  
  12. DECLARE SUB smoothleft (wide, xbmin%)  ' Sub to do smoothing, if turned on
  13. DECLARE SUB smoothright (wide, xbmax%) ' Sub to do smoothing, if turned on
  14. DECLARE SUB usage () ' Prints command line syntax.
  15. DECLARE SUB getcommand (inputfile$, outputfile$, objectname$, smooth, bound%, scale%)
  16. DECLARE SUB readblock (linesleft%, smooth) ' Sub to read in a number of lines
  17.                                            ' per bound
  18.  
  19. DIM SHARED wide AS SINGLE  ' Width of image
  20. DIM SHARED primitives AS INTEGER  ' Counts primitives output
  21. DIM SHARED x AS INTEGER  ' X and Y coordinates.
  22. DIM SHARED y AS INTEGER  ' Shared because they are used in smoothing subs.
  23. DIM SHARED smoothpixel AS STRING * 1  ' Used in smoothing subs.
  24. DIM SHARED pixel AS STRING * 1   ' Single character string so that we GET
  25.                                  ' only one byte at a time.
  26. DIM SHARED corner AS STRING * 77
  27. DIM SHARED xmin AS INTEGER  ' Used to find extreme limits of object.
  28. DIM SHARED xmax AS INTEGER  ' Used to define the final bounding box.
  29. DIM SHARED ymin AS INTEGER
  30. DIM SHARED ymax AS INTEGER
  31. DIM SHARED high AS LONG
  32.  
  33. xmax = 0      '  Declare some variables to find the outside
  34. ymax = 0      '  edges of the object.
  35. xmin = 10000  '  These will be used to define the Bounding Box
  36. ymin = 10000  '  at the end of the object.
  37.  
  38. linesleft% = 10000  ' Used by SUB READBLOCK to ensure that it doesn't
  39.                     ' read past the end of the image.
  40.  
  41. corner = "intersection{box{<-0 -0 -.5><1 1 .5>}plane{<0 1 0>0 rotate<0 0 45>}"
  42.   ' Corner is the smoothing shape, if smoothing in enabled.
  43.  
  44. PRINT "TGA2POV version 2"
  45. PRINT ""
  46.  
  47. CALL getcommand(inputfile$, outputfile$, objectname$, smooth, bound%, scale%)
  48.  
  49. OPEN inputfile$ FOR BINARY AS #1
  50. OPEN outputfile$ FOR APPEND AS #2
  51.  
  52. GET #1, 13, imagewidth%   ' Bytes 13 & 14 are an integer declaring the width of the image
  53. GET #1, 15, imageheight%  ' Bytes 15 & 16 are the integer declaring height.
  54.  
  55. wide = imagewidth%       ' Convert to long integer so that the program
  56. high = imageheight%     ' doesn't bomb out on >32K files.
  57.  
  58. IF LOF(1) = 0 THEN
  59.     PRINT "Input Targa file either does not exist "
  60.     PRINT "or it has an incorrect file size."
  61.     END
  62. END IF
  63.   ' (Height * Width) + Header (18 bytes) should be the LOF
  64.   ' Exit the program if not
  65.  
  66. GET #1, 3, pixel
  67. IF NOT ASC(pixel) = 3 THEN
  68.     PRINT "Input Targa file is not a B&W 8-bit image. (Type 3)"
  69.     END
  70. END IF
  71.   ' If not 03, the the file is not a Type 3 Targa (1 byte / pixel B&W)
  72.  
  73. PRINT #2, "#declare Texture1 = texture { color red 1 }"
  74. PRINT #2, ""
  75. PRINT #2, "#declare "; objectname$; " = composite {"
  76.   ' Header to declare the object
  77.  
  78. PRINT "Converting "; inputfile$; " to "; outputfile$; "."
  79. LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
  80. PRINT "/"
  81.  
  82.  
  83. FOR y = 1 TO high       ' Start read the rows
  84.    
  85.     IF y + bound% > high THEN    ' Test to make sure that the block won't
  86.         linesleft% = high - y    ' read past the end of the image.
  87.     ELSE
  88.         linesleft% = bound%
  89.     END IF
  90.  
  91.     CALL readblock(linesleft%, smooth)
  92.               
  93.     wheel! = wheel! + 1         ' Makes that stupid little spinner so that
  94.     SELECT CASE wheel! MOD 4    ' you know the PC hasn't locked up.
  95.         CASE 0
  96.             LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
  97.             PRINT "/"
  98.         CASE 1
  99.             LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
  100.             PRINT "-"
  101.         CASE 2
  102.             LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
  103.             PRINT "\"
  104.         CASE 3
  105.             LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
  106.             PRINT "|"
  107.     END SELECT
  108.  
  109. NEXT y      ' Go to the next row
  110.  
  111. LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
  112. PRINT " "
  113.  
  114.   ' Done scanning the file.
  115.  
  116. PRINT #2, "bounded_by{ box{<"; (xmin - 1) - .02; (ymin - 1) - .02; "-.52><"; xmax + .02; ymax + .02; ".52>} }"
  117.   ' Prints out the bounding box, which speeds render time.
  118.   ' The box is a little larger to insure that we enclose the entire object
  119.  
  120. PRINT #2, "translate <"; ((xmax + xmin - 1) / 2) * -1; ((ymax + ymin - 1) / 2) * -1; "0>"
  121.   ' Prints out the translation so that the object is centered.
  122.  
  123. IF scale% = 1 THEN
  124.     chartop& = ymax
  125.     charbot& = ymin
  126.     scaleratio! = 1 / (chartop& - charbot& + 1)
  127.     PRINT #2, USING "& #.###### #.###### &"; "scale <"; scaleratio!; scaleratio!; " 1>"
  128. END IF
  129.   ' If SCALING is enabled (/1) the output object is scaled to a height (Y)
  130.   ' of 1 unit, and the width (X) is scaled proportionately.
  131.  
  132. PRINT #2, "}"
  133. PRINT #2, ""
  134.  
  135. CLOSE
  136.  
  137. PRINT ""
  138. PRINT "Number of primitives in output object: "; primitives
  139. PRINT ""
  140.  
  141. SUB getcommand (inputfile$, outputfile$, objectname$, smooth, bound%, scale%)
  142. commandline$ = RTRIM$(COMMAND$)
  143.  
  144. bound% = VAL(MID$(COMMAND$, INSTR(COMMAND$, "/B") + 2, 1))
  145. IF INSTR(COMMAND$, "/B") = 0 THEN bound% = 3
  146.  
  147. scale% = 0
  148. IF INSTR(COMMAND$, "/1") > 1 THEN scale% = 1
  149.  
  150. smooth = INSTR(COMMAND$, "/S")
  151. IF INSTR(commandline$, "/S") > 0 THEN smooth = 1
  152.  
  153. space1% = INSTR(1, commandline$, " ")
  154.  
  155. IF space1% > 0 THEN space2% = INSTR(space1% + 1, commandline$, " ")
  156. IF space1% > 0 AND space2% > 0 THEN space3% = INSTR(space2% + 1, commandline$, " ")
  157.  
  158. IF space1% = 0 THEN CALL usage
  159. IF space3% > 0 AND INSTR(space3% + 1, COMMAND$, " ") > 0 THEN CALL usage
  160.   ' IF space3% > 0 AND smooth = 0 THEN CALL usage
  161.  
  162. inputfile$ = MID$(commandline$, 1, space1% - 1)
  163. objectname$ = inputfile$
  164.  
  165. IF space2% > 0 THEN
  166.     outputfile$ = MID$(commandline$, space1% + 1, space2% - space1% - 1)
  167. ELSE
  168.     outputfile$ = MID$(commandline$, space1% + 1)
  169. END IF
  170.  
  171.  
  172. IF LEN(inputfile$) > 8 THEN
  173.     PRINT "Invalid Filename: "; inputfile$
  174.     END
  175. END IF
  176. IF LEN(outputfile$) > 8 THEN
  177.     PRINT "Invalid Filename: "; outputfile$
  178.     END
  179. END IF
  180.  
  181. IF INSTR(inputfile$, ".") > 0 THEN
  182.     PRINT "Invalid filename: "; inputfile$
  183.     END
  184. END IF
  185.  
  186. IF INSTR(outputfile$, ".") > 0 THEN
  187.     PRINT "Invalid filename: "; outputfile$
  188.     END
  189. END IF
  190.  
  191. SELECT CASE bound%
  192.     CASE IS = 0
  193.         bound% = 10000
  194.     CASE IS = 1
  195.         bound% = 4
  196.     CASE IS = 2
  197.         bound% = 7
  198.     CASE IS = 3
  199.         bound% = 10
  200.     CASE IS = 4
  201.         bound% = 13
  202.     CASE IS = 5
  203.         bound% = 16
  204.     CASE IS = 6
  205.         bound% = 20
  206.     CASE IS = 7
  207.         bound% = 25
  208.     CASE IS = 8
  209.         bound% = 35
  210.     CASE IS = 9
  211.         bound% = 50
  212.     CASE IS > 9
  213.         PRINT "Bounding option incorrect!"
  214.         PRINT "Option must be 1-9!"
  215.         END
  216. END SELECT
  217.  
  218. inputfile$ = inputfile$ + ".TGA"
  219. outputfile$ = outputfile$ + ".INC"
  220.  
  221. END SUB
  222.  
  223. SUB readblock (linesleft%, smooth)
  224.  
  225. xbmin% = 10000
  226. ybmin% = 10000
  227. xbmax% = 0
  228. ybmax% = 0
  229. objectinblock% = 0
  230.  
  231.  
  232. FOR y = y TO y + linesleft%
  233.  
  234.     FOR x = 1 TO wide   ' Start reading the pixels in each row
  235.              
  236.         byte! = ((y - 1) * wide) + 18 + x
  237.         GET #1, byte!, pixel ' Get the pixel value
  238.          
  239.             IF ASC(pixel) = 0 THEN            ' If the pixel is Black then...
  240.                 objectinblock% = objectinblock% + 1
  241.                 IF objectinblock% = 1 THEN
  242.                     PRINT #2, "    object {"
  243.                     PRINT #2, "        union {"
  244.                 END IF
  245.  
  246.                 IF smooth = 1 THEN CALL smoothleft(wide, xbmin%)
  247.  
  248.                 IF x < xbmin% THEN xbmin% = x ' Test to see if this pixel
  249.                 IF x > xbmax% THEN xbmax% = x ' is one of the extreme
  250.                 IF y < ybmin% THEN ybmin% = y ' pixels in the character.
  251.                 IF y > ybmax% THEN ybmax% = y ' (Used for the bounding box)
  252.               
  253.                 xsegmentstart% = x               ' Declare the left edge of this segment of pixels
  254.                   
  255.                     DO WHILE ASC(pixel) = 0 AND x <= wide   ' Check the next pixels in this segment for black
  256.                         x = x + 1
  257.                         byte! = ((y - 1) * wide) + 18 + x
  258.                         GET #1, byte!, pixel ' Get the pixel value
  259.                         IF x > xbmax% THEN xbmax% = x - 1' is one of the extreme
  260.                     LOOP
  261.               
  262.                 PRINT #2, "            box { <"; xsegmentstart% - 1; y - 1; "-.5><"; x - 1; y; ".5>}"
  263.                 ' Above prints the box defining the segment.
  264.              
  265.                 IF smooth = 1 THEN CALL smoothright(wide, xbmax%)
  266.  
  267.                 primitives = primitives + 1 ' Info for number of primitives in output object
  268.               
  269.             END IF  ' End of tests when we find a black pixel
  270.   
  271.     NEXT x  ' Go to the next pixel in the row
  272.  
  273. NEXT y
  274.  
  275.  
  276. IF objectinblock% > 0 THEN
  277.     PRINT #2, "        }"
  278.     PRINT #2, "    bounded_by{ box{<"; (xbmin% - 1) - .01; (ybmin% - 1) - .01; "-.51><"; xbmax% + .01; ybmax% + .01; ".51>} }"
  279.     PRINT #2, "    texture { Texture1 }"
  280.     PRINT #2, "    }"
  281.     PRINT #2, ""
  282. END IF
  283.  
  284. y = y - 1
  285.  
  286. IF xbmin% < xmin THEN xmin = xbmin% ' Test to see if this pixel
  287. IF xbmax% > xmax THEN xmax = xbmax% ' is one of the extreme
  288. IF ybmin% < ymin THEN ymin = ybmin% ' pixels in the character.
  289. IF ybmax% > ymax THEN ymax = ybmax% ' (Used for the bounding box)
  290.  
  291. END SUB
  292.  
  293. SUB smoothleft (wide, xbmin%)
  294.  
  295. lowerleftbyte! = ((y - 1) * wide) + 18 + x - wide - 1
  296. upperleftbyte! = ((y - 1) * wide) + 18 + x + wide - 1
  297. ' ((y * wide) + 18 + x) is the byte that the main module is testing
  298. ' We want to test the pixel one line down and back one (lowerleftbyte%)
  299. ' and the pixel one line up and back one (upperleftbyte%)
  300.  
  301.  
  302. IF upperleftbyte! < (high * wide) + 18 THEN ' Make sure that the byte to be tested isn't
  303.                                 ' past the end of the file.
  304.    GET #1, upperleftbyte!, smoothpixel' Get the pixel value
  305.     IF ASC(smoothpixel) = 0 THEN
  306.         PRINT #2, corner
  307.         PRINT #2, "rotate <0 0 90> translate<"; x - 1; y - 1; "0>}"
  308.         primitives = primitives + 1
  309.         IF (upperleftbyte% MOD wide) - 3 < xbmin% THEN xbmin% = (upperleftbyte! MOD wide) - 3
  310.     END IF
  311. END IF
  312.  
  313. IF lowerleftbyte! > 18 THEN  ' Make sure that the byte to be tested is
  314.                              ' actually part of the image, and not the header
  315.     GET #1, lowerleftbyte!, smoothpixel' Get the pixel value
  316.     IF ASC(smoothpixel) = 0 THEN
  317.         PRINT #2, corner
  318.         PRINT #2, "translate<"; x - 2; y - 1; "0>}"
  319.         primitives = primitives + 1
  320.         IF (lowerleftbyte% MOD wide) - 3 < xbmin% THEN xbmin% = (lowerleftbyte! MOD wide) - 3
  321.     END IF
  322. END IF
  323.  
  324. END SUB
  325.  
  326. SUB smoothright (wide, xbmax%)
  327.  
  328. lowerrightbyte! = ((y - 1) * wide) + 18 + x - wide
  329. upperrightbyte! = ((y - 1) * wide) + 18 + x + wide
  330.   ' ((y * wide) + 18 + x) is the byte that the main module is testing
  331.   ' We want to test the pixel below and to the right (lowerleftbyte%)
  332.   ' and the pixel above and to the right (upperleftbyte%)
  333.  
  334. IF upperrightbyte! < (high * wide) + 18 THEN ' Make sure that the byte to be tested
  335.                                  ' isn't past the end of the file.
  336.     GET #1, upperrightbyte!, smoothpixel  ' Get the pixel value
  337.     IF ASC(smoothpixel) = 0 THEN
  338.         PRINT #2, corner
  339.         PRINT #2, "rotate <0 0 180> translate<"; x; y; "0>}"
  340.         primitives = primitives + 1
  341.         IF (upperrightbyte! MOD wide) - 2 > xbmax% THEN xbmax% = (upperrightbyte! MOD wide) - 2
  342.     END IF
  343. END IF
  344.  
  345. IF x < wide AND y > 1 THEN  ' Make sure that the byte to be tested
  346.                             ' is part of the image.
  347.     GET #1, lowerrightbyte!, smoothpixel  ' Get the pixel value
  348.     IF ASC(smoothpixel) = 0 THEN
  349.         PRINT #2, corner
  350.         PRINT #2, "rotate <0 0 -90> translate<"; x - 1; y; "0>}"
  351.         primitives = primitives + 1
  352.         IF (lowerrightbyte% MOD wide) - 2 > xbmax% THEN xbmax% = (lowerrightbyte! MOD wide) - 2
  353.     END IF
  354. END IF
  355.  
  356. END SUB
  357.  
  358. SUB usage
  359.        PRINT "Usage:"
  360.        PRINT "TGA2POV INPUT OUTPUT [/Bn] [/S] [/1]"
  361.        PRINT ""
  362.        PRINT "INPUT is the Targa file (.TGA added)"
  363.        PRINT "OUTPUT is the POV #include file (.INC added)"
  364.        PRINT "/S  - Enables smoothing."
  365.        PRINT "/Bn - Indicates a bounding level.  Must be 1-9, default is 3."
  366.        PRINT "/1  - Scales object to a height of 1 unit."
  367.        PRINT ""
  368.        PRINT "Examples:"
  369.        PRINT "TGA2POV a-bookmn bookman"
  370.        PRINT "TGA2POV mypic-z z-object /s /b6"
  371.        END
  372. END SUB
  373.  
  374.