Page MenuHome

Ter2Blend_new.py

Authored By
Brendon Murphy (meta-androcto)
Nov 13 2013, 1:57 PM
Size
17 KB
Subscribers
None
Tokens
"100" token, awarded by Linkun.

Ter2Blend_new.py

#!BPY
"""
Name: '_Terragen (.ter)'
Blender: 244
Group: 'Wizards'
Tooltip: 'Terragen Terrain Import Script, It also imports camera and light positions'
"""
__author__ = 'Guy Van Rentergem, David Johnson'
__url__ = ('blender','http://wiki.blender.org/index.php/Scripts/Manual/Wizards/Ter2Blend_v4p')
__version__ = '0.4'
__bpydoc__ = """\
Description: Import Terragen Terrains .ter files, tested with Terragen 0.9.43
"""
#
# Ter2Blend
#
# Terragen's terrain file to Blender file converter
#
#
# Copyright (c) 2003 Guy Van Rentergem
# Copyright (c) 2008 David Johnson (Building on the great work by Guy)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.#
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# History
# -------
#
# 10-jul-00: started coding, must've been drunk :)
# 15-jul-00: v0.1 is ready, first tries
# 20-jul-00: announcement to the Blender and Terragen community
# 24-jul-00: 10 days holiday...
# 07-aug-00: v0.2 found that fat bug in the camera code
# left targetx, targety, targetz out of the code
# inserted instead head, pitch, bank
# Started writing a basic tutorial
# 08-aug-00: Putting v0.2 and the tutorial on my website
# Cleared a bug about the maximum mesh size thanks to Frank
# 10-aug-00: started coding v1.0
# 12-aug-00: finished the 100 km Dodentocht at Bornem, Yes on foot!
# 16-aug-00: testing and finishing v1.0
# 17-aug-00: announcement to the Blender and Terragen community
# 20-aug-00: release of v1.0 on the web
# 25-aug-00: Ter2Blend v1.1. Big bug discovered by D. Graham. The camerascript
# only worked correct with scripts produced with Terramin. Campath generated scripts
# couldn't be read. Thanks Dan!
# 29-aug-00: create a ter2blend.txt file containing the settings of the last time
# the program was used. Things to be saved: camera settings, .ter file,
# sun settings and watersetting
# 06-sep-00: facelift of the userinterface
# 14-sep-00: added a status bar while calculating the surface mesh
# 17-sep-00: The scripts now look for ter2blend.txt and ter2blend.tgs in the directory
# where the ter2blend.blend file was started. This allows to work with different
# projects placed in different directories.
# 18-sep-00: Release of v1.2 on the web
# 15-jul-01: Checked script if it works with Blender 2.14
# put in a warning if terrain is to big
# changed version number to v2
# 29-jul-01: Some changes in the texts displayed on the GUI. changed version number to v3.
# 03-oct-03: ************ Ter2Blend v4 ****************
# After a long time again a new release!!! At last Blender has a new and stable
# Python API. Many thanks to Ton and all the other fantastic developers of Blender.
# Fixed that stupid banking bug!!!
# This is worth a new version number of the ter2blend script: v4!
# Blender Rules!!
# 14-jan-08 Work begins again on the project. Added new License copy right
# to the top document, to bring it in to GPL, orginal author credited. License applies
# from this version onwards
# Things to do
# ------------
#
# * make it possible to work with terrains bigger than 257 x 257 (even now
# there is some clipping to 255 x255). The problem is that this will slow
# down the working of Blender considerable and maybe will blow out the memory
# out of the computer ;)
# * do the dishes, mow the lawn,...
# Blender limits
# --------------
# Render faces: 1024 k
# Render vertices: 1024 k
# number of vertices in a mesh: 65535
#
# Additional vertices are permitted in EditMode, but
# Blender generates a warning and blocks EditMode until
# the command "SEPARATE" (PKEY) is used to place some of the
# vertices and faces in separate meshes.
#
# definition of the sun: 1 spotlight (only light that can cast shadows in Blender)
# and one hemilight put far away of the terrain
# Terragen stuff
# --------------
#
# standard terragen terrains can have the following sizes:
# 129 * 129 = 16641 vertices
# 257 * 257 = 66049
# 513 * 513 = 263169
# 1025 * 1025 = 1050625
# 2049 * 2049 = 4198401
# 4097 * 4097 = 16785409 (will blow the memory out of your computer!)
#
# Due to memory and speed considerations let's use only one mesh and
# keep the maximum number of vertices to 65535 (Blender limit)
# So to keep things simple we will only allow terrains up 257 * 257
# This means terrains of 129 * 129 and 257 * 257 (this one already needs some clipping...)
# Later we will do some coding so the mesh can be divided in pieces and all
# kind of formats will be allowed, but then a powerfull machine is needed.
#
# default settings in Terragen: sun heading -60 degrees (from north)
# sun altitude 25 degrees from groundlevel
#
# in Terragen the (0,0) is located in the left bottom corner
#
# important: USE ONLY TERRAIN UNITS FROM TERRAGEN
#
# Blender camera lens 22.70 seems to fit the standard lens of Terragen
# Terragen script file
# --------------------
#
# script commands usefull for Ter2Blend:
# InitAnim BaseName, StartFrame - only use for StartFrame, the first frame to rendered
# CamPos x,y,z - sets the camera's position in Terrain Units
# TarPos x,y,z - sets the target's position in Terrain Units
# CamH head - sets the camera's heading in degrees
# CamP pitch - sets the camera's pitch in degrees
# CamB bank - sets the camera's bank in degrees
# SunDir head, alt - sets the heading and altitude of the sun in degrees (for later...)
# FRend - renders a frame
#
# Forbidden script commands in Ter2Blend:
# Zoom z - sets the Zoom value
# Exp e - sets the Exposure value
#
# Useless script commands in Ter2Blend:
# CloudPos x,y
# CloudVel Speed, Heading
### MOD by pat
### all changes marked like this one
###
### list of changes:
### import glob commented
### removed vertexlimit
###
#################################################################
import Blender
import sys
import string
import struct
import os #,glob
from os import path,name,sep
from math import *
from Blender import NMesh
from Blender.BGL import *
from Blender.Draw import *
from Blender import Scene
from Blender import Lamp
from Blender import Mesh
flagstatusbar=0
valbar=0
maxbar=1
drawcount=1
version=Blender.Get('version')
filename=Blender.Get('filename')
lpath,lname=os.path.split(filename)
inf = lpath+r"\ter2blend.txt"
try:
inffile=open(inf, 'r')
except IOError:
terfile = Create("")
waterlevel = Create(-10.00)
sunheading = Create(-60.00)
sunalt = Create(25.00)
camerax = Create(128.00)
cameray = Create(0.00)
cameraz = Create(0.00)
head = Create(0.00)
pitch = Create(0.00)
bank = Create(0.00)
zoom = Create(1.44)
else:
line = inffile.readline()
L1 = string.split(line,',')
terfile=Create(L1[0])
waterlevel=Create(string.atof(L1[1]))
sunheading=Create(string.atof(L1[2]))
sunalt=Create(string.atof(L1[3]))
camerax=Create(string.atof(L1[4]))
cameray=Create(string.atof(L1[5]))
cameraz=Create(string.atof(L1[6]))
head=Create(string.atof(L1[7]))
pitch=Create(string.atof(L1[8]))
bank=Create(string.atof(L1[9]))
zoom=Create(string.atof(L1[10]))
inffile.close()
#################################################################
def gui():
global terfile
global waterlevel
global sunheading, sunalt
global camerax, cameray, cameraz
global head, pitch, bank
global flagstatusbar,valbar,maxbar
global zoom
glClearColor(0.5,0.5,0.5,0.0)
glClear(GL_COLOR_BUFFER_BIT)
glColor3f(0.0,0.0,0.0)
glRectf(0,0,480,480)
glColor3f(1.0,1.0,1.0)
glRectf(2,2,478,478)
glColor3f(0.0,0.0,0.0)
glRectf(0,288,480,410)
glColor3f(1.0,1.0,1.0)
glRectf(2,290,478,408)
glColor3f(0.0,0.0,0.0)
glRasterPos2i(10,460)
Text(" TER2BLEND v5.0.1")
glRasterPos2i(10,440)
Text("Guy Van Rentergem 2003(c) and David Mark Johnson 2008(c)")
glRasterPos2i(10,420)
Text(" TERRAIN, import a *.ter file")
glColor3f(1.0,0.0,0.0)
glRasterPos2i(10,385)
Text("USE ONLY TERRAGEN TERRAIN UNITS")
glColor3f(0.0,0.0,0.0)
#glRasterPos2i(10,360)
#Text(" The camera lens must have a value of 22.70")
glRasterPos2i(10,330)
Text(" After importing the terrain, select it and")
glRasterPos2i(10,310)
Text(' assign it the "shadow only" material ')
glRasterPos2i(10,223)
Text("Camera position")
glRasterPos2i(10,180)
Text("Camera orientation")
glRasterPos2i(10,267)
Text("Open ter-file, full path name required")
if flagstatusbar==1:
glColor3f(0.0,0.0,0.0)
glRectf(20,310,265,380)
glColor3f(0.8,0.8,0.8)
glRectf(22,312,263,378)
glColor3f(0.0,0.0,0.0)
glRasterPos2i(115,350)
Text("Working...")
glColor3f(0.0,0.0,0.0)
glRectf(28,321,257,340)
glColor3f(1.0,1.0,0.0)
glRectf(30,323,255,338)
glColor3f(0.0,0.0,1.0)
glRectf(30,323,30+(225.0/maxbar)*valbar,338)
terfile = String("Open: ",13,10,244,260,18,terfile.val,100)
camerax = Number("X: ",7,10,200,86,18,camerax.val,0.00,258.00)
cameray = Number("Y: ",8,97,200,86,18,cameray.val,0.00,258.00)
cameraz = Number("Z: ",9,184,200,86,18,cameraz.val,-1000.00,1000.00)
head = Number("head: ",10,10,156,86,18,head.val,-360.00,360.00)
pitch = Number("pitch: ",11,97,156,86,18,pitch.val,-180.00,180.00)
bank = Number("bank: ",12,184,156,86,18,bank.val,-180.00,180.00)
waterlevel = Slider("water level: ",4,10,124,260,18,waterlevel.val,-258.0,258.0)
sunheading = Slider("sun heading: ",5,10,97,260,18,sunheading.val,-180.0,180.0)
sunalt = Slider("sun altitude: ",6,10,70,260,18,sunalt.val,-90.0,90.0)
zoom = Slider("Camera Zoom: ",7,10,43,260,18,zoom.val,0.25,256.0)
Button("Exit",1,190,10,80,19)
Button("Draw",2,10,10,80,19)
#################################################################
def event(evt,val):
if (evt == ESCKEY and not val): Exit()
#################################################################
def bevent(evt):
global drawcount,version
if (evt == 1): Exit()
elif (evt == 2):
if version < 200:
draw(terfile.val,waterlevel.val,sunheading.val,sunalt.val,camerax.val,cameray.val, cameraz.val,head.val,pitch.val,bank.val)
else:
if drawcount==1:
draw(terfile.val,waterlevel.val,sunheading.val,sunalt.val,camerax.val,cameray.val, cameraz.val,head.val,pitch.val,bank.val)
else:
drawcount=1
#################################################################
def draw(terfile,waterlevel,sunheading,sunalt,camerax,cameray,cameraz,head,pitch,bank):
global drawcount
global flagstatusbar
drawcount=drawcount+1
flagstatusbar=1
gui()
Register(gui,event,bevent)
Blender.Redraw()
createfile()
createnewscene()
camera(camerax,cameray,cameraz,head,pitch,bank)
terrain(terfile)
sun(sunheading,sunalt)
water(waterlevel)
flagstatusbar=0
Blender.Redraw()
#################################################################
def createnewscene():
try:
scn = Scene.Get('TerragenScene')
except:
scn = Scene.New('TerragenScene')
else:
i = 1
# scn = Scene.New('TerragenScene')
scn.makeCurrent()
#################################################################
def createfile():
global terfile, inf
global waterlevel
global sunheading, sunalt
global camerax, cameray, cameraz
global head, pitch, bank
inffile=open(inf, 'w')
dummy=terfile.val+','+`waterlevel.val`+','+`sunheading.val`+','+`sunalt.val`+','+`camerax.val`+','+`cameray.val`+','+`cameraz.val`+','+`head.val`+','+`pitch.val`+','+`bank.val`+','+`zoom.val`
inffile.write(dummy)
inffile.close()
#################################################################
def water(waterlevel):
sce = Scene.GetCurrent()
try:
water = Blender.Mesh.Get("TerragenWater")
except:
water = Mesh.New('TerragenWater')
coords = [ [0,0,waterlevel], [size,0,waterlevel], [size,size,waterlevel], [0,size,waterlevel] ]
faces = [ 0,1,2,3 ]
water.verts.extend(coords)
water.faces.extend(faces)
scn = Scene.GetCurrent()
ob = scn.objects.new(water,'TerragenWater')
else:
print "Found water"
#water = Mesh.New('TerrgenWater')
#################################################################
# We need to create the lamps that match the SUN from Terragen.
# so that they can actually be used, So these Lamps are now
# linked in to the Terragen Scene for use in the blender application
# method as recommend in the documents for Blender 2.44
def sun(sunheading,sunalt):
sce = Scene.GetCurrent()
try:
lamp = Blender.Object.Get("TerragenHemi")
except:
lamp = Lamp.New("Sun")
sce.objects.new(lamp,"TerragenHemi")
else:
print "Found hemi!"
try:
lp = Blender.Object.Get("TerragenShadow")
except:
lp = Lamp.New("Spot")
sce.objects.new(lp,"TerragenShadow")
else:
print "Found shadow!"
sunheading = sunheading*pi/180
sunalt=sunalt*pi/180
SunLocX = size/2+750*sin(sunheading)
SunLocY = size/2+750*cos(sunheading)
SunLocZ = 750*sin(sunalt)/cos(sunalt)
SunRotX = pi/2-sunalt
SunRotY = 0
SunRotZ = pi-sunheading
shadow = Blender.Object.Get("TerragenShadow")
shadow.LocX = SunLocX
shadow.LocY = SunLocY
shadow.LocZ = SunLocZ
shadow.RotX = SunRotX
shadow.RotY = SunRotY
shadow.RotZ = SunRotZ
shadowdata = shadow.getData()
shadowdata.setDist(1.1*sqrt((SunLocZ)**2+562500))
shadowdata.setSpotSize( 2*atan(200/shadowdata.getDist())*180/pi) #save angle
hemi = Blender.Object.Get("TerragenHemi")
hemi.LocX = SunLocX
hemi.LocY = SunLocY
hemi.LocZ = SunLocZ
hemi.RotX = SunRotX
hemi.RotY = SunRotY
hemi.RotZ = SunRotZ
#################################################################
def camera(camerax,cameray,cameraz,head,pitch,bank):
sce = Blender.Scene.Get('TerragenScene')
try:
camera = Blender.Object.Get('TerragenCamera')
except:
camera = Blender.Camera.New('persp')
camera.name = ("TerragenCamera")
camera.setLens(22.70)
sce.objects.new(camera,'TerragenCamera')
else:
print "Found camera!"
# Field of view needs to be in degrees so calculate that from the Zoom value we have
camera = Blender.Camera.Get('TerragenCamera')
print zoom
invzoom = 1/(zoom.val)
FOV = 2*atan(invzoom)
lens = 16/tan(FOV/2)
camera.setLens(lens)
print lens
camera = Blender.Object.Get('TerragenCamera')
camera.LocX = camerax
camera.LocY = cameray
camera.LocZ = cameraz
# pitch
# -----
# (Blender) 0 is down, 90 is horizontal (rad)
# (Terragen) -90 is down, 0 is horizontal (deg)
camerax = pi/2 + pi/180*pitch
# bank
# ----
# (Blender) / 45 (rad)
# (Terragen) / 45 (deg)
cameray = bank*pi/180
# head
# ----
# (Blender) 0 is top, 90 is left, -90 is right
# (Terragen) 0 is top, 90 is right, -90 is left
cameraz = -head*pi/180
camera.setEuler(camerax,cameray,cameraz)
Blender.Redraw()
#################################################################
def terrain(terfile):
global size,maxbar,valbar
sce = Scene.GetCurrent()
try:
terrianName = Blender.Obeject.Get('TerragenMesh')
except:
size=0
try:
ter=open(terfile, 'rb')
except IOError:
if terfile=="":
print "Terragen ter file does not exist!"
Exit()
else:
print terfile + " does not exist!"
Exit()
else:
if ter.read(8) == 'TERRAGEN':
if ter.read(8) == 'TERRAIN ':
print 'Terragen terrain file: continue'
keys=['SIZE','XPTS','YPTS','SCAL','CRAD','CRVM','ALTW']
totest = ter.read(4)
while 1:
if totest in keys:
if totest == 'SIZE':
(size,) = struct.unpack('h',ter.read(2))
garbage = ter.read(2)
if totest == 'XPTS':
(xpts,) = struct.unpack('h',ter.read(2))
garbage = ter.read(2)
if totest == 'YPTS':
(ypts,) = struct.unpack('h',ter.read(2))
garbage = ter.read(2)
if totest == 'SCAL':
(scalx,) = struct.unpack('f',ter.read(4))
(scaly,) = struct.unpack('f',ter.read(4))
(scalz,) = struct.unpack('f',ter.read(4))
if totest == 'CRAD':
(crad,) = struct.unpack('f',ter.read(4))
if totest == 'CRVM':
(crvm,) = struct.unpack('H',ter.read(2))
garbage = ter.read(2)
if totest == 'ALTW':
(heightscale,) = struct.unpack('h',ter.read(2))
(baseheight,) = struct.unpack('h',ter.read(2))
break
totest = ter.read(4)
else:
break
if xpts==0:xpts=size+1
if ypts==0:ypts=size+1
### MOD by pat
### commented 2 lines
#if (xpts>257 or ypts>257):
# print str(xpts)+" X "+str(ypts)+" to big! Terragen terrain must be 257 X 257."
maxbar=xpts*ypts*2
stepbar=maxbar/25
valbar=0
terrainName = Mesh.New()
vertexlist = []
# Create vertices
# ---------------
# read them all...
for y in xrange(ypts):
for x in xrange(xpts):
(h,) = struct.unpack('h',ter.read(2))
### MOD by pat: 1 line commented
### 10 lines unindeted
#if x < 254 and y < 254:
z = baseheight + h*heightscale/65536.0
vertexlist.append((x,y,z))
valbar=valbar+1
if valbar%stepbar==0:
gui()
Register(gui,event,bevent)
Blender.Redraw()
xmax=x+1
ymax=y+1
### end of unindented block
ter.close()
terrainName.verts.extend(vertexlist)
# Create faces
# ------------
print "Building Faces"
faces = []
for y in range(0,ymax-1):
for x in range (0,xmax-1):
a=x+y*(ymax)
faces.append(( terrainName.verts[a], terrainName.verts[a+ymax], terrainName.verts[a+ymax+1], terrainName.verts[a+1] ))
valbar=valbar+1
if valbar%stepbar==0:
gui()
Register(gui,event,bevent)
Blender.Redraw()
terrainName.faces.extend(faces)
scn = Scene.GetCurrent()
ob = scn.objects.new(terrainName,"TerragenMesh")
valbar=0
maxbar=1
drawcount=1
else:
print "Found Terrain"
Register(gui,event,bevent)
#########################END OF CODE##############################

File Metadata

Mime Type
text/x-python
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
58/1e/92f12f771bfdff0a12f993cfc3cd

Event Timeline