home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Graphics
/
WOGRAPH.BIN
/
766.TGA2POV2.BAS
< prev
next >
Wrap
BASIC Source File
|
1992-11-02
|
13KB
|
374 lines
' TGA2POV 2.0 copyright 1992 Scott Steeves
' Converts B&W 8-bit Targas to PoV 1.0 objects
'
' This program is given as freeware, in the spirit of PoV.
'
' Feel free to change this code, but if you do,
' please send me a copy and a message at one of the following BBSes:
'
' You Can Call Me Ray 1-708-358-8721
' Channel 1 1-617-354-8873
DECLARE SUB smoothleft (wide, xbmin%) ' Sub to do smoothing, if turned on
DECLARE SUB smoothright (wide, xbmax%) ' Sub to do smoothing, if turned on
DECLARE SUB usage () ' Prints command line syntax.
DECLARE SUB getcommand (inputfile$, outputfile$, objectname$, smooth, bound%, scale%)
DECLARE SUB readblock (linesleft%, smooth) ' Sub to read in a number of lines
' per bound
DIM SHARED wide AS SINGLE ' Width of image
DIM SHARED primitives AS INTEGER ' Counts primitives output
DIM SHARED x AS INTEGER ' X and Y coordinates.
DIM SHARED y AS INTEGER ' Shared because they are used in smoothing subs.
DIM SHARED smoothpixel AS STRING * 1 ' Used in smoothing subs.
DIM SHARED pixel AS STRING * 1 ' Single character string so that we GET
' only one byte at a time.
DIM SHARED corner AS STRING * 77
DIM SHARED xmin AS INTEGER ' Used to find extreme limits of object.
DIM SHARED xmax AS INTEGER ' Used to define the final bounding box.
DIM SHARED ymin AS INTEGER
DIM SHARED ymax AS INTEGER
DIM SHARED high AS LONG
xmax = 0 ' Declare some variables to find the outside
ymax = 0 ' edges of the object.
xmin = 10000 ' These will be used to define the Bounding Box
ymin = 10000 ' at the end of the object.
linesleft% = 10000 ' Used by SUB READBLOCK to ensure that it doesn't
' read past the end of the image.
corner = "intersection{box{<-0 -0 -.5><1 1 .5>}plane{<0 1 0>0 rotate<0 0 45>}"
' Corner is the smoothing shape, if smoothing in enabled.
PRINT "TGA2POV version 2"
PRINT ""
CALL getcommand(inputfile$, outputfile$, objectname$, smooth, bound%, scale%)
OPEN inputfile$ FOR BINARY AS #1
OPEN outputfile$ FOR APPEND AS #2
GET #1, 13, imagewidth% ' Bytes 13 & 14 are an integer declaring the width of the image
GET #1, 15, imageheight% ' Bytes 15 & 16 are the integer declaring height.
wide = imagewidth% ' Convert to long integer so that the program
high = imageheight% ' doesn't bomb out on >32K files.
IF LOF(1) = 0 THEN
PRINT "Input Targa file either does not exist "
PRINT "or it has an incorrect file size."
END
END IF
' (Height * Width) + Header (18 bytes) should be the LOF
' Exit the program if not
GET #1, 3, pixel
IF NOT ASC(pixel) = 3 THEN
PRINT "Input Targa file is not a B&W 8-bit image. (Type 3)"
END
END IF
' If not 03, the the file is not a Type 3 Targa (1 byte / pixel B&W)
PRINT #2, "#declare Texture1 = texture { color red 1 }"
PRINT #2, ""
PRINT #2, "#declare "; objectname$; " = composite {"
' Header to declare the object
PRINT "Converting "; inputfile$; " to "; outputfile$; "."
LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
PRINT "/"
FOR y = 1 TO high ' Start read the rows
IF y + bound% > high THEN ' Test to make sure that the block won't
linesleft% = high - y ' read past the end of the image.
ELSE
linesleft% = bound%
END IF
CALL readblock(linesleft%, smooth)
wheel! = wheel! + 1 ' Makes that stupid little spinner so that
SELECT CASE wheel! MOD 4 ' you know the PC hasn't locked up.
CASE 0
LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
PRINT "/"
CASE 1
LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
PRINT "-"
CASE 2
LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
PRINT "\"
CASE 3
LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
PRINT "|"
END SELECT
NEXT y ' Go to the next row
LOCATE CSRLIN - 1, LEN(inputfile$) + LEN(outputfile$) + 18
PRINT " "
' Done scanning the file.
PRINT #2, "bounded_by{ box{<"; (xmin - 1) - .02; (ymin - 1) - .02; "-.52><"; xmax + .02; ymax + .02; ".52>} }"
' Prints out the bounding box, which speeds render time.
' The box is a little larger to insure that we enclose the entire object
PRINT #2, "translate <"; ((xmax + xmin - 1) / 2) * -1; ((ymax + ymin - 1) / 2) * -1; "0>"
' Prints out the translation so that the object is centered.
IF scale% = 1 THEN
chartop& = ymax
charbot& = ymin
scaleratio! = 1 / (chartop& - charbot& + 1)
PRINT #2, USING "& #.###### #.###### &"; "scale <"; scaleratio!; scaleratio!; " 1>"
END IF
' If SCALING is enabled (/1) the output object is scaled to a height (Y)
' of 1 unit, and the width (X) is scaled proportionately.
PRINT #2, "}"
PRINT #2, ""
CLOSE
PRINT ""
PRINT "Number of primitives in output object: "; primitives
PRINT ""
SUB getcommand (inputfile$, outputfile$, objectname$, smooth, bound%, scale%)
commandline$ = RTRIM$(COMMAND$)
bound% = VAL(MID$(COMMAND$, INSTR(COMMAND$, "/B") + 2, 1))
IF INSTR(COMMAND$, "/B") = 0 THEN bound% = 3
scale% = 0
IF INSTR(COMMAND$, "/1") > 1 THEN scale% = 1
smooth = INSTR(COMMAND$, "/S")
IF INSTR(commandline$, "/S") > 0 THEN smooth = 1
space1% = INSTR(1, commandline$, " ")
IF space1% > 0 THEN space2% = INSTR(space1% + 1, commandline$, " ")
IF space1% > 0 AND space2% > 0 THEN space3% = INSTR(space2% + 1, commandline$, " ")
IF space1% = 0 THEN CALL usage
IF space3% > 0 AND INSTR(space3% + 1, COMMAND$, " ") > 0 THEN CALL usage
' IF space3% > 0 AND smooth = 0 THEN CALL usage
inputfile$ = MID$(commandline$, 1, space1% - 1)
objectname$ = inputfile$
IF space2% > 0 THEN
outputfile$ = MID$(commandline$, space1% + 1, space2% - space1% - 1)
ELSE
outputfile$ = MID$(commandline$, space1% + 1)
END IF
IF LEN(inputfile$) > 8 THEN
PRINT "Invalid Filename: "; inputfile$
END
END IF
IF LEN(outputfile$) > 8 THEN
PRINT "Invalid Filename: "; outputfile$
END
END IF
IF INSTR(inputfile$, ".") > 0 THEN
PRINT "Invalid filename: "; inputfile$
END
END IF
IF INSTR(outputfile$, ".") > 0 THEN
PRINT "Invalid filename: "; outputfile$
END
END IF
SELECT CASE bound%
CASE IS = 0
bound% = 10000
CASE IS = 1
bound% = 4
CASE IS = 2
bound% = 7
CASE IS = 3
bound% = 10
CASE IS = 4
bound% = 13
CASE IS = 5
bound% = 16
CASE IS = 6
bound% = 20
CASE IS = 7
bound% = 25
CASE IS = 8
bound% = 35
CASE IS = 9
bound% = 50
CASE IS > 9
PRINT "Bounding option incorrect!"
PRINT "Option must be 1-9!"
END
END SELECT
inputfile$ = inputfile$ + ".TGA"
outputfile$ = outputfile$ + ".INC"
END SUB
SUB readblock (linesleft%, smooth)
xbmin% = 10000
ybmin% = 10000
xbmax% = 0
ybmax% = 0
objectinblock% = 0
FOR y = y TO y + linesleft%
FOR x = 1 TO wide ' Start reading the pixels in each row
byte! = ((y - 1) * wide) + 18 + x
GET #1, byte!, pixel ' Get the pixel value
IF ASC(pixel) = 0 THEN ' If the pixel is Black then...
objectinblock% = objectinblock% + 1
IF objectinblock% = 1 THEN
PRINT #2, " object {"
PRINT #2, " union {"
END IF
IF smooth = 1 THEN CALL smoothleft(wide, xbmin%)
IF x < xbmin% THEN xbmin% = x ' Test to see if this pixel
IF x > xbmax% THEN xbmax% = x ' is one of the extreme
IF y < ybmin% THEN ybmin% = y ' pixels in the character.
IF y > ybmax% THEN ybmax% = y ' (Used for the bounding box)
xsegmentstart% = x ' Declare the left edge of this segment of pixels
DO WHILE ASC(pixel) = 0 AND x <= wide ' Check the next pixels in this segment for black
x = x + 1
byte! = ((y - 1) * wide) + 18 + x
GET #1, byte!, pixel ' Get the pixel value
IF x > xbmax% THEN xbmax% = x - 1' is one of the extreme
LOOP
PRINT #2, " box { <"; xsegmentstart% - 1; y - 1; "-.5><"; x - 1; y; ".5>}"
' Above prints the box defining the segment.
IF smooth = 1 THEN CALL smoothright(wide, xbmax%)
primitives = primitives + 1 ' Info for number of primitives in output object
END IF ' End of tests when we find a black pixel
NEXT x ' Go to the next pixel in the row
NEXT y
IF objectinblock% > 0 THEN
PRINT #2, " }"
PRINT #2, " bounded_by{ box{<"; (xbmin% - 1) - .01; (ybmin% - 1) - .01; "-.51><"; xbmax% + .01; ybmax% + .01; ".51>} }"
PRINT #2, " texture { Texture1 }"
PRINT #2, " }"
PRINT #2, ""
END IF
y = y - 1
IF xbmin% < xmin THEN xmin = xbmin% ' Test to see if this pixel
IF xbmax% > xmax THEN xmax = xbmax% ' is one of the extreme
IF ybmin% < ymin THEN ymin = ybmin% ' pixels in the character.
IF ybmax% > ymax THEN ymax = ybmax% ' (Used for the bounding box)
END SUB
SUB smoothleft (wide, xbmin%)
lowerleftbyte! = ((y - 1) * wide) + 18 + x - wide - 1
upperleftbyte! = ((y - 1) * wide) + 18 + x + wide - 1
' ((y * wide) + 18 + x) is the byte that the main module is testing
' We want to test the pixel one line down and back one (lowerleftbyte%)
' and the pixel one line up and back one (upperleftbyte%)
IF upperleftbyte! < (high * wide) + 18 THEN ' Make sure that the byte to be tested isn't
' past the end of the file.
GET #1, upperleftbyte!, smoothpixel' Get the pixel value
IF ASC(smoothpixel) = 0 THEN
PRINT #2, corner
PRINT #2, "rotate <0 0 90> translate<"; x - 1; y - 1; "0>}"
primitives = primitives + 1
IF (upperleftbyte% MOD wide) - 3 < xbmin% THEN xbmin% = (upperleftbyte! MOD wide) - 3
END IF
END IF
IF lowerleftbyte! > 18 THEN ' Make sure that the byte to be tested is
' actually part of the image, and not the header
GET #1, lowerleftbyte!, smoothpixel' Get the pixel value
IF ASC(smoothpixel) = 0 THEN
PRINT #2, corner
PRINT #2, "translate<"; x - 2; y - 1; "0>}"
primitives = primitives + 1
IF (lowerleftbyte% MOD wide) - 3 < xbmin% THEN xbmin% = (lowerleftbyte! MOD wide) - 3
END IF
END IF
END SUB
SUB smoothright (wide, xbmax%)
lowerrightbyte! = ((y - 1) * wide) + 18 + x - wide
upperrightbyte! = ((y - 1) * wide) + 18 + x + wide
' ((y * wide) + 18 + x) is the byte that the main module is testing
' We want to test the pixel below and to the right (lowerleftbyte%)
' and the pixel above and to the right (upperleftbyte%)
IF upperrightbyte! < (high * wide) + 18 THEN ' Make sure that the byte to be tested
' isn't past the end of the file.
GET #1, upperrightbyte!, smoothpixel ' Get the pixel value
IF ASC(smoothpixel) = 0 THEN
PRINT #2, corner
PRINT #2, "rotate <0 0 180> translate<"; x; y; "0>}"
primitives = primitives + 1
IF (upperrightbyte! MOD wide) - 2 > xbmax% THEN xbmax% = (upperrightbyte! MOD wide) - 2
END IF
END IF
IF x < wide AND y > 1 THEN ' Make sure that the byte to be tested
' is part of the image.
GET #1, lowerrightbyte!, smoothpixel ' Get the pixel value
IF ASC(smoothpixel) = 0 THEN
PRINT #2, corner
PRINT #2, "rotate <0 0 -90> translate<"; x - 1; y; "0>}"
primitives = primitives + 1
IF (lowerrightbyte% MOD wide) - 2 > xbmax% THEN xbmax% = (lowerrightbyte! MOD wide) - 2
END IF
END IF
END SUB
SUB usage
PRINT "Usage:"
PRINT "TGA2POV INPUT OUTPUT [/Bn] [/S] [/1]"
PRINT ""
PRINT "INPUT is the Targa file (.TGA added)"
PRINT "OUTPUT is the POV #include file (.INC added)"
PRINT "/S - Enables smoothing."
PRINT "/Bn - Indicates a bounding level. Must be 1-9, default is 3."
PRINT "/1 - Scales object to a height of 1 unit."
PRINT ""
PRINT "Examples:"
PRINT "TGA2POV a-bookmn bookman"
PRINT "TGA2POV mypic-z z-object /s /b6"
END
END SUB