Van Buren Resources Exported!

Discussion in 'Fallout General Modding' started by Dude101, Oct 15, 2009.

  1. Lexx

    Lexx Background Radiant
    Moderator Modder

    Apr 24, 2005
    The shadow looks interesting, indeed. Guess it's an advantage of the FOnline engine again, because it supports half-transparent graphics like that.
     
  2. Jotisz

    Jotisz Mildly Dipped

    557
    Aug 28, 2007
    The shadow looks nice though I think instead of using tiles for it a shadow scenery would be easier and faster
     
  3. Master92

    Master92 It Wandered In From the Wastes

    135
    Dec 26, 2010
    Where I can find the graphics from VB in FO2 format?
    This was much well for my work...
     
  4. Lexx

    Lexx Background Radiant
    Moderator Modder

    Apr 24, 2005
    Either in this thread or here. I converted various stuff into frm back when we worked in this thread.
     
  5. Fallout1FTW

    Fallout1FTW Still Mildly Glowing

    211
    Oct 25, 2010
    Can you reupload Van Buren FRMs because they are deleted
     
  6. .Pixote.

    .Pixote. Venerable Relic of the Wastes
    Modder

    Sep 14, 2009
    Yes, but you need to adjust the frame offset in such a way to avoid things falling behind the shadow, and becoming unreachable.

    The advantage of a tile shadow is that the shadow doesn't need to be 100% opaque, you can make it 70% and have some of the tile (brick, dirt, etc) coming through. But then again it's more work... :roll:
     
  7. kvark

    kvark First time out of the vault

    6
    Aug 8, 2010
    latest Blender import script

    Hi!

    Could anyone provide a link for the freshest blender importer of g3d?

    Thanks!
     
  8. Horatio

    Horatio First time out of the vault

    39
    Jul 9, 2012
    Wow, this topic is fresh.

    kvark, if you're still alive, you might find this handy.
    http://glest.wikia.com/wiki/G3D_support

    Or maybe not.
    Because the scripts that are supposed to import g3d files, may have the same extension, but wrong header.
    Blender will say, that is NOT a g3d file. I tried to manipulate the script, but my Python skills were not sufficient enough.
    Blender 2.5 and 2.6 doesn't import anything at all. Since it has no console i can't see what he is saying, but probably the same.

    Next story, 3ds max. Struggled 2 days to find a working demo of 2009, everything dead everywhere, found it on my own old HDD.
    The only script for import i found is this.
    [spoiler:8094287630]
    Code:
    g3d = fopen "C:\\F3_Demo\\props\\DS_Dunebuggy.g3d" "rb"
    
    function byte2Char b =(
    local Char=" !'#$%&'()*+,-./0123456789:;<=>?
    
    @ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™
    
    š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×
    
    ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö[]()÷ø"ùúûüýþÿ"
      return Char[b-31]
    )
    
    function StringRead f =(
      s = ""
      len = readshort f
      for i = 0 to len - 1 do (
        n = readbyte f
        s += byte2Char(n)
      )
      return s
    )
    
    struct g3d_header (
        Sign			 = "",	--: array[0..7]of char; // "B3D 1.1 "
        Unknown1		 = 0,	--: byte;
        Unknown2		 = 0,	--: byte;
        Unknown3		 = 0,	--: byte; //Header ID??
        GlobalScaleFactor= 0.0,	--: single;
        Unknown4	     = 0,	--: byte; //Header ID??
        CoordinateScale  = 0.0,	--: single;
        Unknown5		 = 0,	--: byte; //Header ID??
        CoordinateSystem = "", --: TCharArray;
        Unknown6		 = 0,	--: byte;
        Unknown7		 = 0,	--: longword;
    	function ReadFromFile f =
    	(
      	  for i = 0 to 7 do (
            n = readbyte f
            Sign += byte2Char(n)
          )
    	  Unknown1 = readbyte f; Unknown2 = readbyte f; Unknown3 = readbyte f
    	  GlobalScaleFactor = readfloat f; Unknown4 = readbyte f
    	  CoordinateScale = readfloat f; Unknown5 = readbyte f
    	  CoordinateSystem = StringRead f
    	  Unknown6	= readbyte f; Unknown7 = readlong f
    	)   
    )
    
    Model_Vertex_Position = #()
    Model_Vertex_Normal   = #()
    Model_Faces_Index     = #()
    
    Vertex_Type_Flag      = 0
    
    FS = 0
    Zone_Flag = 0;
    
    struct TVertex64 (
      Coordinate = Point3 0.0 0.0 0.0,      --: array[0..2]of single;
      Normal	 = Point3 0.0 0.0 0.0,      --: array[0..2]of single;
      Color	     = Point4 0.0 0.0 0.0 0.0,  --: array[0..3]of single;
      Unknown1   = Point2 0.0 0.0,          --: array[0..1]of single;
      Unknown2   = Point2 0.0 0.0,          --: array[0..1]of single;
      Unknown3   = Point2 0.0 0.0,          --: array[0..1]of single;
      function ReadFromFile f = (
        Coordinate.x = readfloat f; Coordinate.z = readfloat f; Coordinate.y = readfloat 
    
    f	 
        Normal.x = readfloat f; Normal.y = readfloat f; Normal.z = readfloat f	 
        --for i = 1 to 4 do Color[i] = readlong f
    	Color.x = readfloat f; Color.y = readfloat f; Color.z = readfloat f; Color.w 
    
    = readfloat f
        Unknown1.x = readfloat f; Unknown1.y = readfloat f
        Unknown2.x = readfloat f; Unknown2.y = readfloat f
        Unknown3.x = readfloat f; Unknown3.y = readfloat f
      )  
    )
    
    struct TVertex44 (
      Coordinate   = Point3 0.0 0.0 0.0, -- Координата точки (x, y, z: single)
      Normal	   = Point3 0.0 0.0 0.0, -- Нормаль точки (x, y, z: single)
      Color	       = #(0, 0, 0, 0),      -- Цвет точки (r, g, b, a: byte)
      TextureCoord = Point2 0.0 0.0,     -- Текстурные координаты (s, t: single);
      Unknown1     = #(),     -- Неизвестно
      function ReadFromFile f = (
        Coordinate.x = readfloat f; Coordinate.z = readfloat f; Coordinate.y = readfloat 
    
    f
    	Model_Vertex_Position[Model_Vertex_Position.count + 1] = Coordinate
        Normal.x = readfloat f; Normal.y = readfloat f; Normal.z = readfloat f
        for i = 1 to 4 do Color[i] = readbyte f
    	TextureCoord .x = readfloat f; TextureCoord .y = readfloat f
        Unknown1[1] = readlong f; Unknown1[2] = readlong f
      ) 
    )
    
    struct TVert_Bones_Data (
    	Bone   = 0,   --: longword
    	Weight = 0.0, --: single
    	function ReadFromFile f = (
    	  Bone = readlong f
    	  Weight = readfloat f
    	)
    )
    
    struct TMaterial_Data (
        Name		  = "",		
        Mtl_ID		  = "",	    
        Unknown1	  = 0.0, --: array[0..16]of single; //Most likely Ambient, Diffuse, 
    
    Emissive, Specular, Shininess, and Alpha
        BLEND_STATE   = "",	--: TCharArray;
        MATERIAL_TYPE = "", --: TCharArray;
        Unknown2	  = 0, --: array[0..63]of byte; //Flags??
        Zone		  = "", --: TCharArray;
        Unknown3	  = 0, --: longword;
    	function ReadFromFile f = (
          Name = StringRead f; Mtl_ID = StringRead f
          for i = 0 to 16 do Unknown1 = readfloat f
          BLEND_STATE = StringRead f; MATERIAL_TYPE = StringRead f
          for i = 0 to 63 do Unknown2 = readbyte f
          Zone = StringRead f; Unknown3 = readlong f
    	)
    )
    
    struct TVertex_Node (
        Unknown1       = 0,		-- Неизвестно
    	Unknown2       = 0,		-- Неизвестно
    	VertexTypeFlag = 0, 	-- 
    	NumberVerts    = 0,		-- Количество точек
    	SizeOfVerts    = 0,		-- размер одной точки
        Unknown3       = #(),	-- Неизвестно
    	Unknown4       = 0,     -- Неизвестно
    	BonesPerVert   = 0,		-- Максимальное количество костей на точку
    	NumberMaterial = 0,		-- Количество материалов
        function ReadFromFile f = (
          Unknown1 = readbyte f;
    	  Unknown2 = readbyte f;
    	  VertexTypeFlag = readbyte f;
    	  Vertex_Type_Flag = VertexTypeFlag
    	  NumberVerts = readlong f;
    	  format "Количество точек - %\n"" NumberVerts
          if Vertex_Type_Flag == 1 then (
    	    SizeOfVerts = readlong f;
    		format "Размер данный одной точки - %\n" SizeOfVerts
    		for i = 1 to NumberVerts do (Vertex44 = TVertex44(); 
    
    Vertex44.ReadFromFile f)
    		for i = 1 to 6 do (Unknown3[i] = readfloat f); Unknown4 = readbyte f
            BonesPerVert = readlong f
    		format "Максимальное количество костей на точку - %\n" BonesPerVert
    		for i = 1 to NumberVerts * BonesPerVert do (VBD = TVert_Bones_Data(); 
    
    VBD.ReadFromFile f;) --print VBD)
    		NumberMaterial = readlong f
    		format "Количество материалов - %\n" NumberMaterial
    		for i = 1 to NumberMaterial do (MD = TMaterial_Data(); 
    
    MD.ReadFromFile f; print MD)
    		for i = 1 to NumberMaterial do (
    		  Zone = ""; S = ""
    		  for j = 1 to Zone_Flag + 1 do (
    		    S = StringRead f; Zone += S
    		  )
    		  print Zone
    		  pos = ftell f; print Pos
    		)
    			
    		NumVert = 0; NumTri = 0
    		for i = 1 to NumberMaterial do (a = readlong f; NumVert +=a; b = 
    
    readlong f; NumTri +=b)
    		print NumVert; print NumTri
    		for i = 1 to NumTri - 1 do (
    		  pos = ftell f
    		  if pos == (FS - 3) then exit
    		  a = 0; a = readshort f #unsigned
    		  b = 0; b = readshort f #unsigned
    		  c = 0; c = readshort f #unsigned
    		  a = a + 1;  b = b + 1; c = c + 1;
    		  Model_Faces_Index[Model_Faces_Index.count + 1] = [c, b, a]
    		)
    	  ) else (
    	    Vertex64.ReadFromFile f
    --		Print Vertex64
    	  )
    --	  Print Model_Vertex_Position
        )
    )
    
    struct TMaterial_Data (
        Name		  = "",	--: TCharArray;
        Mtl_ID		  = "",	--: TCharArray;
        Unknown1	  = 0.0, --: array[0..16]of single; //Most likely Ambient, Diffuse, 
    
    Emissive, Specular, Shininess, and Alpha
        BLEND_STATE   = "",	--: TCharArray;
        MATERIAL_TYPE = "", --: TCharArray;
        Unknown2	  = 0, --: array[0..63]of byte; //Flags??
        Zone		  = "", --: TCharArray;
        Unknown3	  = 0, --: longword;
    	function ReadFromFile f = (
          Name = StringRead f; Mtl_ID = StringRead f
          for i = 0 to 16 do Unknown1 = readfloat f
          BLEND_STATE = StringRead f; MATERIAL_TYPE = StringRead f
          for i = 0 to 63 do Unknown2 = readbyte f
          Zone = StringRead f; Unknown3 = readlong f; Zone_Flag = Unknown3
    	)
    )
    
    struct TBone (
        Name	    = "",
        Unknown1	= 0, --: word;
        Flag  	    = 0, --: byte;  //Header ID?? For "Transform"
        Translation	= point3 0.0 0.0 0.0, --: array[0..2]of single;
        Rotation	= quat 0.0 0.0 0.0 0.0, --: array[0..3]of single;
    	function ReadFromFile f = (
    	Name = StringRead f; Unknown1 = readshort f; Flag = readbyte f
        Translation.x = readfloat f; Translation.z = readfloat f; Translation.y = 
    
    readfloat f;
        if Flag == 3 then (Rotation.x = readfloat f; Rotation.z = readfloat f; Rotation.y 
    
    = readfloat f; Rotation.w = readfloat f)
    --	b = mybox = box length:0.01 width:0.01 height:0.01;
    --	b.name = Name
    --	b.rotation = Rotation
    --	b.pos = Translation	
    	)
    )
    
    struct TColor (
      r = 0, g = 0, b = 0, a = 0,
      function ReadFromFile f = (r = readfloat f; g = readfloat f; b = readfloat f; a = 
    
    readfloat f
      )
    )
    
    struct TMater (
      Ambient   = TColor(),
      Diffuse   = TColor(),
      Emissive  = TColor(),
      Specular  = TColor(),
      Shininess = 0,
      Alpha     = 0,
      function ReadFromFile f = (
        Ambient.ReadFromFile f; Diffuse.ReadFromFile f
        Emissive.ReadFromFile f; Specular.ReadFromFile f
        Shininess = readfloat f; Alpha = readfloat f
      )
    )
    
    struct TMaterials (
        Mtl_ID = "",
        Name = "",
        Mater = TMater(),
        BLEND_STATE = "",
        MATERIAL_TYPE = "",
        Flag_1 = 0,
    	Flag_2 = 0,
    	function ReadFromFile f = (
          Mtl_ID = StringRead f; Name = StringRead f
          Mater.ReadFromFile f
          BLEND_STATE = StringRead f; MATERIAL_TYPE = StringRead f
          Flag_1 = readlong f; Flag_2 = readlong f
    	)
    )
    
    struct TTextures (
        Unknown1 = 0, --: byte;
        Name = "", --: TCharArray;
        FileName = "", --: TCharArray;
        Width = 0, --: longword;
        Height = 0, --: longword;
    	function ReadFromFile f = (
          Unknown1 = readbyte f; Name = StringRead f; FileName = StringRead f
          Width = readlong f; Height = readlong f
    	)
    )
    
    struct TNodes (
      Unknown1 = 0, --: byte;
      Name = "", --: TCharArray;
      function ReadFromFile f = (
        Unknown1 = readbyte f; Name = StringRead f
      )
    )
    
    struct TMat_Data (
        Unknown1 = 0, --: array[0..2]of byte;
        Name     = "", --: TCharArray;
        TextureOn = 0, --: longword;
        Texture  = "", --: TCharArray;
        Unknown3 = 0, --: longword;
        Unknown4 = 0, --: byte;
        NumOfPoints = 0, --: longword;
        function ReadFromFile f = (
          for i = 0 to 2 do (Unknown1 = readbyte f)
    	  Name = StringRead f
    	  print Name
    	  TextureOn = readlong f
    	  if TextureOn != 0 then Texture = StringRead f
    	  Unknown3 = readlong f
    	  Unknown4 = readbyte f
    	  NumOfPoints = readlong f
          print NumOfPoints
        )
    	
    )
    --   Points                      : array of longword;
    --    MatID                       : array of byte;
    struct TMaterial_Node (
        NumberMaterialNodes	= 0, --: longword;
        Unknown1            = 0, --: byte;
        function ReadFromFile f = (
     	  NumberMaterialNodes = readlong f
    	  Unknown4 = readbyte f
          print NumberMaterialNodes 
        )
     --   Mat_Data                    : array of TMat_Data;
    )
    
    function FileSizeGet f = (
      fseek f 0 #seek_end
      size = ftell f
      return size
    )
    
    function FilePosGet f = (
      pos = ftell f
      return pos
    )
    
    function main f = (
      local FileSize = 0
      local FilePos = 0
      FileSize = FileSizeGet f
      FS = FileSize
      fseek f 0 #seek_set
      g3d_head = g3d_header(); g3d_head.ReadFromFile f; print g3d_head
      Material_Node = TMaterial_Node()
      do (
        b = 0; b = readbyte f
    	case b of (
          0x07: (Materials = TMaterials(); Materials.ReadFromFile f; print Materials; pos 
    
    = ftell f; print pos)
    	  0x08: (Textures = TTextures(); Textures.ReadFromFile f; print Textures; pos 
    
    = ftell f; print pos)
    	  0x0A: (Nodes = TNodes(); Nodes.ReadFromFile f; print Nodes; pos = ftell f; 
    
    print pos)
    	  0x0E: (Bone = TBone(); Bone.ReadFromFile f; print Bone; pos = ftell f; 
    
    print pos)
    	  0x0F: (Vertex_Node = TVertex_Node(); Vertex_Node.ReadFromFile f; pos = 
    
    ftell f; print pos)
    	  default: exit
    	) 
    	FilePos = FilePosGet f
      )
      while FilePos != FileSize
    
    --Model_Faces_Index.count=1
    --for i = 1 to 1 do Model_Faces_Index[i]= [2018,20,18]
    mnode = mesh vertices:Model_Vertex_Position faces:Model_Faces_Index
    mmesh = mnode.mesh
    --  buildTVFaces mmesh 
    --  for i = 1 to mmesh.numfaces do (setTVFace mmesh i (getFace mmesh i))
    )
    
    main g3d
    
    fclose g3d
    
    [/spoiler:8094287630]

    Syntax errors everywhere, can't fix anything with my scripting skills.
    Senpay fixed it, though, but his link is, as you guess, is dead.

    Another script for importing .tre scenery, that at least have no syntax errors is here.
    [spoiler:8094287630]
    Code:
    function String4Read f = (
    	s = ""
    	for i = 1 to 4 do (
    		n = readbyte f
    		s+= bit.intAsChar n
    	)
    	return s
    )
    
    struct TSectionHeader
    (
    	id = "", -- name
    	size = 0,
    	
    	function ReadFromFile f =
    	(
    		id = String4Read f
    		size = readlong f
    	)
    )
    
    function ReadSectionHead f =
    (
    	head = TSectionHeader()
    	head.ReadFromFile f
    	return head
    )
    
    
    GVP = #() -- vertex position
    GVN = #() -- vertex normal
    GVD = #() -- vertex diffuse color
    GVT = #() -- texture coords
    GVL = #() -- lightmap coords
    IDX = #() -- face indexes
    
    buffer_index = 0  -- current vertex buffer index
    buffer_offset = #() -- 
    
    Flag = 1
    
    struct TREE_Data
    (
    	
    	function FileSizeGet f = 
    	(
    		prev = ftell f
    		fseek f 0 #seek_end
    		size = ftell f
    		fseek f prev #seek_set
    		return size
    	),
    	
    	function FilePosGet f =
    	(
    		ret = ftell f
    		return ret
    	),
    	
    	function IsHeader s =
    	(
    		return case s of
    		(
    			"NODE" 	: true
    			"LEAF" 	: true
    			"INFO"	: true
    			"IDXD"	: true
    			"IDXS"	: true
    			"FLGS"	: true
    			"TREE"	: true
    			"LVL0"	: true
    			"XYZ "	: true
    			"MATR"	: true
    			"MATD"	: true
    			"TXTD"	: true
    			"TREE"	: true
    			"VTXD"	: true
    			"VTXB"	: true
    			"TXUV"	: true
    			"LMUV"	: true
    			"DIFU"	: true
    			"NRML"	: true
    			"LVLD"	: true
    			"LVL0"	: true
    			"HEAD"	: true
    			"8TRE"	: true
    			"LGTD"	: true
    			"LGTR"	: true
    			default	: false
    		)
    	),
    
    	function ReadBlock f size= 
    	(
    		header = ReadSectionHead f
    		
    	    if header.id == "FLGS" do
    		(			
    			fseek f (header.size*Flag) #seek_cur
    			return 0
    		)
    		
    		if header.id == "IDXD" do
    		(
    			fseek f -16 #seek_cur
    			tmp =1 + (readlong f)
    			if tmp >= 1 and tmp <= buffer_offset.count do 
    				buffer_index = tmp
    			--format "vertex buffer : % / %" buffer_index buffer_offset.count
    			fseek f 12 #seek_cur
    		)
    		
    		if header.id == "TXTR" do
    		(
    			s = ""
    			for i = 1 to header.size do s += (bit.IntAsChar (readbyte f) )
    			print s
    			return 0
    		)
    		
    		if header.id == "IDXS" do
    		(
    			--print header
    			end = (ftell f) + header.size
    			
    		
    			while ((ftell f)+12) < end do
    			(
    				tmp = readshort f #unsigned
    				if tmp == 0 do
    				(
    					tmp = readshort f #unsigned
    					--print tmp
    				)
    				
    				if bit.and tmp 0xFF00 == 0x8000 do fseek f 8 #seek_cur
    				if bit.and tmp 0xFF00 == 0x4000 do fseek f 4 #seek_cur
    					
    				size = readshort f
    				
    				for i = 1 to (size/3) do
    				(
    					a = buffer_offset[buffer_index] + readshort f #unsigned
    					b = buffer_offset[buffer_index] + readshort f #unsigned
    					c = buffer_offset[buffer_index] + readshort f #unsigned
    					
    					IDX[IDX.count+1] = [a,c,b]
    				)
    				
    			)
    			
    			fseek f end #seek_set			
    			return 0
    		)
    		
    		if header.id == "VTXB" do
    		(
    			readlong f
    			header.size -= 4
    			buffer_offset[buffer_offset.count+1] = GVP.count+1
    			--format "vertex buffer offset % = %\n" buffer_offset.count  (GVP.count+1)
    		)
    		
    		if header.id == "VTXD" do
    		(
    			readlong f
    			header.size -= 4 
    		)
    		
    		if header.id == "XYZ " do
    		(
    			--print header
    			
    			for i = 1 to header.size/12 do
    			(
    				x = readfloat f
    				y = readfloat f
    				z = readfloat f
    				
    				GVP[GVP.count+1] = [x,z,y]
    			)
    			
    			return 0
    		)
    		
    		if IsHeader header.id then
    		(
    			--print header
    			
    			end = ( ftell f ) + header.size
    			
    			while (ftell f ) < end do
    			(				
    				ReadBlock f header.size
    			)
    		)
    		else
    		(
    			fseek f -8 #seek_cur
    			if size < 4  and size != 0 do size = 4
    			fseek f size #seek_cur
    		)
    	),
    
    	
    	function ReadFromFile f =
    	(
    		ReadBlock f 0
    	)
    )
    
    
    function tre_file f  = 
    (	
    	
    	reader = TREE_Data()
    	reader.ReadFromFile f
    	
    	obj = Editable_Mesh()
    	obj.mesh.numverts = GVP.count
    	obj.mesh.numfaces = IDX.count
    	
    	for i = 1 to obj.mesh.numverts do
    	  SetVert obj.mesh i GVP[i]
      
    	for i = 1 to obj.mesh.numfaces do
    			SetFace obj.mesh i IDX[i]
    	  
    	
    	update obj
    )
    
    m_roll=newrolloutfloater "TRE Importer" 400 130
    
    rollout TREImport "TRE Import" width:400 height:104
    (
    	edittext filename "File:" pos:[9,6] width:312 height:17
    	button OpenBtn "Open" pos:[326,7] width:56 height:21 enabled:true
    	button ImportBtn "Import" pos:[9,68] width:80 height:21
    	checkbox Flgs "FLGS Size" pos:[9,39] width:94 height:12
    	
    	on OpenBtn pressed do
    	(
    		s = GetOpenFileName types:"TRE file(*.tre)|*.tre" historyCategory:"TREImports"
    		if s != undefined do
    		(
    			filename.text = s
    		)	
    	)
    	on ImportBtn pressed do
    	(
    		if FileName.text != "" do
    		(
    			Flag = if Flgs.checked then 4 else 1
    			tre_file (fopen FileName.text "rb")
    			fclose FileName	
    			closeRolloutFloater m_roll			
    		)
    	)
    )
    
    addrollout TREImport m_roll
    
    
    [/spoiler:8094287630]
    At least they will prevail the teeth of time as text.

    As for now, i will call it a day for internet archaeology and start learn scripting tomorrow, because i asked already here for these materials and received no reaction. I doubt anyone is still interested in this old topic.

    If i get something, i'll post it here.

    edit: there, every succesful export of Van Buren maps in Wavefront.
    Van Buren maps
    Get it as long it's fresh.

    Now onward to scripting stuff.

    Oh, and find working scripts here.
    http://fonline2238.net/forum/index.php/topic,26470.msg224618.html#new

    Thanks for...your attention(?), NMA.
     
  9. Verleyk

    Verleyk First time out of the vault

    1
    Apr 19, 2013
  10. alec

    alec White heterosexual male Orderite

    May 21, 2003
    Meh. It works. Probably would be awful with moving characters, but that one screen works very well.