VRCar Game Tcl/Lightning Script


This is the source of my little Virtual Reality driving game VRCar scripted in Tcl using Lightning modules. Sadly there are no images available at this time. You may reuse this source or adapt it to your needs, for example to control the car using a Wii steering wheel. I hope it can help out in certain cases.

Sourcecode


source [ file join [ file dirname [ info script ] ] viewer.ltcl ]
 
ltmodule ltVisObjOSG ltvisual
ltmodule ltVisGridOSG ltgrid
ltmodule ltVisPolyLineOSG ltpolyline
ltmodule ltMaterialTextureOSG lttexture
 
ltmodule ltXFormLookAt ltlookat
ltmodule ltXForm ltxform
ltmodule ltVisPolyLineOSG ltpolyl
ltmodule ltSensorButtonKey ltsensor
ltmodule ltLightPointOSG ltlight
ltmodule ltLightInfiniteOSG ltinflight
ltmodule ltVisBoxOSG ltbox
 
ltmodule ltXFormLookAt ltlookat
ltmodule ltXForm ltxform
ltmodule ltSensorTime lttime
ltmodule ltVRMLSceneOSG ltvrml
 
puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
puts "Hi there, please answer a few questions to the riddler:\n"
puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
puts "Choice: (1) Start Level #1; (2) Start Level #2; (3) Start Level #3; (4) Start Level #4\n"
gets stdin level
puts "Please enter the road width. (Default: 300)\n"
gets stdin roadDistanceThreshold
 
puts "Loading..."
 
proc abstand2Punkte2D {p1 p2} {
	set opeA [expr ([lindex $p1 0] - [lindex $p2 0])]
	set opeB [expr ([lindex $p1 1] - [lindex $p2 1])]
	return [expr sqrt($opeA * $opeA + $opeB * $opeB)]
}
 
proc langeVec {vi} {
	set v0 [lindex $vi 0]; set v1 [lindex $vi 1]; set v2 [lindex $vi 2]
	return [expr sqrt(($v0 * $v0) + ($v1 * $v1) + ($v2 * $v2))]
}
 
proc kreuzprodukt2vec {v1 v2} {
	set v10 [lindex $v1 0]; set v11 [lindex $v1 1]; set v12 [lindex $v1 2]
	set v20 [lindex $v2 0]; set v21 [lindex $v2 1]; set v22 [lindex $v2 2]
	set return0 [expr ($v11 * $v22) - ($v12 * $v21)]
	set return1 [expr ($v12 * $v20) - ($v10 * $v22)]
	set return2 [expr ($v10 * $v21) - ($v11 * $v20)]
	set ret "$return0 $return1 $return2"
	return $ret
}
 
proc vecoutof2points {p1 p2} {
	set p1a [lindex $p1 0];set p1b [lindex $p1 1];set p1c [lindex $p1 2]
	set p2a [lindex $p2 0];set p2b [lindex $p2 1];set p2c [lindex $p2 2]
	set finalvec "[expr $p2a - $p1a] [expr $p2b - $p1b] [expr $p2c - $p1c]"
	return $finalvec
}
 
proc distanzPunktGerade {p1 p2 vec2} {
	set testMe [abstand2Punkte2D $p1 $p2]
	set hitTestThreshold 70.0
	if {$testMe > $hitTestThreshold} {
		return 1111.0
	}
	set vector2points [vecoutof2points $p2 $p1]
	set kreuzprodukt [kreuzprodukt2vec $vector2points $vec2]
	set langekreuzprod [langeVec $kreuzprodukt]
	set langegeradenvec [langeVec $vec2]
	if {$langegeradenvec == 0} {
		set abstand 1111.0
	} else {
		set abstand [expr $langekreuzprod / $langegeradenvec]
	}
	return $abstand
} 
 
#Recorded way through the terrain for level1:
#NOTE: Windows console "pipe" to .log: "commandhere" > Mylog.log 2>&1
set polylMVec3 [list ]
lappend polylMVec3 "435.0903579063838 -5763.249765428326 5"
lappend polylMVec3 "431.3371103803053 -5766.459828171394 5"
lappend polylMVec3 "427.69644150184484 -5769.573494717128 5"
lappend polylMVec3 "425.93072392858534 -5771.083793985203 5"
lappend polylMVec3 "422.5052321773561 -5774.013507929547 5"
lappend polylMVec3 "189.1672216199219 -5973.567105543562 5"
lappend polylMVec3 "181.85601876312307 -5979.819525793767 5"
lappend polylMVec3 "178.31008518049757 -5982.851861708018 5"
lappend polylMVec3 "171.43097987568456 -5988.73515040702 5"
lappend polylMVec3 "164.75824887184962 -5994.441957806974 5"
lappend polylMVec3 "-10.505212771042842 -6144.329784844002 5"
lappend polylMVec3 "-21.24342960240049 -6153.513045965648 5"
lappend polylMVec3 "-187.01166359742993 -6287.8687002551715 5"
lappend polylMVec3 "-190.18981871607468 -6290.286097313992 5"
lappend polylMVec3 "-196.35545009435273 -6294.975976380624 5"
lappend polylMVec3 "-202.33611455933027 -6299.525221621153 5"
lappend polylMVec3 "-205.2367417173083 -6301.731727490555 5"
lappend polylMVec3 "-210.86394395996865 -6306.012226615505 5"
lappend polylMVec3 "-430.4564954022017 -6473.044602743531 5"
lappend polylMVec3 "-442.75846850160764 -6482.401852418359 5"
#[...]
lappend polylMVec3 "-2006.1848063409925 6454.457608521894 5"
lappend polylMVec3 "-1538.283691604302 6759.112740838695 5"
lappend polylMVec3 "-1530.9423836294225 6763.724926934264 5"
lappend polylMVec3 "-1523.8213147026952 6768.198868009118 5"
lappend polylMVec3 "-1520.3675708840256 6770.368508449259 5"
lappend polylMVec3 "-1513.6673415942228 6774.578021727156 5"
lappend polylMVec3 "-1507.168151736425 6778.661213779819 5"
lappend polylMVec3 "-1504.015975732177 6780.641431202702 5"
lappend polylMVec3 "-558.4976324729595 7110.285317028769 5"
lappend polylMVec3 "-550.0013640486854 7112.843561566153 5"
lappend polylMVec3 "-533.5186071974699 7117.807056574597 5"
lappend polylMVec3 "-517.530362605938 7122.621536276666 5"
lappend polylMVec3 "-509.77603107599384 7124.95656953758 5"
lappend polylMVec3 "-494.73268366184027 7129.486418722207 5"
lappend polylMVec3 "504.9780151397244 7356.167529953581 5"
lappend polylMVec3 "518.8743910419375 7358.308396042434 5"
lappend polylMVec3 "532.3538622578782 7360.385282428235 5"
lappend polylMVec3 "538.8914257670417 7361.39244784486 5"
lappend polylMVec3 "551.5742520644325 7363.346533929056 5"
lappend polylMVec3 "563.8766294643228 7365.242017316171 5"
lappend polylMVec3 "1447.796304132887 7497.777281450921 5"
lappend polylMVec3 "1455.287378883431 7498.61209175684 5"
lappend polylMVec3 "1469.8201147603513 7500.231715628934 5"
lappend polylMVec3 "1483.9168466509252 7501.8027623895605 5"
lappend polylMVec3 "1490.7538073082774 7502.564585731337 5"
lappend polylMVec3 "2235.0175716216186 7563.670985638161 5"
lappend polylMVec3 "2242.9467801156998 7563.554426531503 5"
lappend polylMVec3 "2258.329428153982 7563.328244365078 5"
lappend polylMVec3 "2273.250517056823 7563.108949012388 5"
lappend polylMVec3 "2280.4872556230857 7563.002586650995 5"
lappend polylMVec3 "2294.526633606869 7562.796218331477 5"
lappend polylMVec3 "3110.516323184141 7501.58969993827 5"
lappend polylMVec3 "3125.686546619332 7497.228019564653 5"
lappend polylMVec3 "3133.0440649373986 7495.1125421569 5"
lappend polylMVec3 "3147.3175765823094 7491.008264340051 5"
lappend polylMVec3 "3161.1630495602617 7487.027381581293 5"
 
set polylMVec3Left [list ]
set polylMVec3Right [list ]
 
if {$roadDistanceThreshold != ""} {
	set roadDistance $roadDistanceThreshold
} else {
	set roadDistance 850
}
 
ltlookat calclookat
ltxform calcxform -position2In "1 0 0"
lttexture lefttex -emissiveIn "1 0 0"
set leftmvec ""
 
for {set a 0} {$a < [expr [llength $polylMVec3]-1]} {incr a} {
	set nextidx [expr 1+$a]
	set actualpoint [lindex $polylMVec3 $a]; set ax [lindex $actualpoint 0]; set ay [lindex $actualpoint 1]; set az [lindex $actualpoint 2]
	set nextpoint [lindex $polylMVec3 $nextidx]
 
	ltupdate calclookat -positionIn $actualpoint -positionLookAtIn $nextpoint
	set oriofvector [ltfetch calclookat -orientationOut]
 
	ltupdate calcxform -orientationIn $oriofvector
	set rightvector [ltfetch calcxform -positionOut]; set rx [lindex $rightvector 0]; set ry [lindex $rightvector 1]; set rz [lindex $rightvector 2]
 
	#Calculate leftPoint from origin
	set distancescale $roadDistance
	set lpoint "[expr $ax - $rx*$distancescale] [expr $ay - $ry*$distancescale] [expr $az - $rz*$distancescale]"
	set lpointRight "[expr $ax + $rx*$distancescale] [expr $ay + $ry*$distancescale] [expr $az + $rz*$distancescale]"
	lappend polylMVec3Left $lpoint
	lappend polylMVec3Right $lpointRight
}
 
ltpolyl polylineLeft -widthIn 30.0 -pointListIn $polylMVec3Left
ltpolyl polylineRight -widthIn 30.0 -pointListIn $polylMVec3Right
 
ltupdate renderer -modelpathIn [ list [ file join [ file dirname [ info script ] ] .] ]
 
#Atmosphere
ltvrml atmosphere -scaleIn 220.0 -urlIn "atmosphere.wrl" -orientationIn "0 90 0"
 
if {$level != "2" && $level != "3" && $level != "4" && $level != "1"} {
	ltvrml dynamic -scaleIn 60.0 -urlIn "level1.wrl" -orientationIn "0 90 0"
} else {
	ltvrml dynamic -scaleIn 60.0 -urlIn "level$level.wrl" -orientationIn "0 90 0"
}
 
ltvrml cubex -scaleIn 1.0 -urlIn "car.wrl" -orientationIn "0 90 0" -positionIn "0 -25 0"
ltupdate camera -positionIn "435.0903579063838 -5763.249765428326 5"
 
lttime timer
ltlight light
ltinflight lamp -positionIn "0 0 7000"
ltinflight lamp3 -positionIn "44000 0 7000"
ltinflight lamp4 -positionIn "0 44000 7000"
ltinflight lamp2 -positionIn "44000 44000 7000"
 
ltinflight lamp5 -positionIn "22000 22000 7000"
ltinflight lamp6 -positionIn "0 22000 7000"
ltinflight lamp7 -positionIn "22000 0 7000"
 
ltxform camXForm -position2In "0 +300 +100" -orientation2In "180 0 0"
ltupdate camera -farIn "10000000.000000"
 
ltgroup cube -adjustIn 1 -addChildrenIn { headlight light cubex bxl } -orientationIn "0 0 0" -scaleIn 10.0 -updateParentIn 1
 
puts "Starting ..."
 
ltscript move {
	{ sensorLeftIn int In 0 }
	{ sensorRightIn int In 0 }
	{ timeIn float In 0.0 }
	{ timeLastIn float In 0.0 }
	{ radiusIn float In 20.0 }
	{ omegaIn float In 72.0 }
	{ angleOut float Out 0.0 }
	{ keyIn int In 0 }
	{ posOut vec3 Out "0 0 0" }
	{ FRICTIONMOD float In 0.97 }
	{ turnFun int Out 0.0 }
 
	{ MAXSPEED float In 20.0 }
	{ ACCELERTAION float In 0.9 }
 
	{ REVERSEMAXSPEED float In -11.0 }
	{ REVERSEACCELERTAION float In 0.2 }
	{ MAXTURNRATE float In 0.9 }
	{ TURNIMPACTONSPEED float In 0.8 }
	{ speedOut float Out 0.0 }
	{ oriOut int Out 0 }
	{ oriOutVec3Out vec3 Out "0 0 0" }
	{ camPosOut vec3 Out "0 0 0" }
	{ camNamesIn string In ""}
	{ doHitTestIn int In 0}
} {
	set keyUp 73
	set keyDown 75
	set keyLeft 106
	set keyRight 108
	set keyUpLeft 76
	set keyDownLeft 10
	set keyUpRight 74
	set keyDownRight 12
	#notes for keys: J = 106 L = 108 ShiftJ = 74 ShitftL = 76 Strg+J = 10 Strg+l = 12
	set sensorLeftIn [ ltfetch -sensorLeftIn ]
 
	# vec3: Head Pitch Roll
	set oriOutVec3Out [ ltfetch -oriOutVec3Out ]
	set oriOut [ lindex $oriOutVec3Out 0 ]  
 
	set currentTime [ ltfetch -timeIn ]
	set lastTimeIn [ ltfetch -timeLastIn ]
	set deltaTime [expr 100 * ($currentTime - $lastTimeIn) ]
 
	set posOut [ ltfetch -posOut ]
	set posOutX [ lindex $posOut 0 ]
	set posOutY [ lindex $posOut 1 ]
 
	set camPosOut [ ltfetch -camPosOut ]
	set doHitTest [ ltfetch -doHitTestIn ]
 
	set key [ ltfetch -keyIn ]
	set speed [ ltfetch -speedOut ]
 
	set ACCELERTAION [ ltfetch -ACCELERTAION ]
	set FRICTIONMOD [ ltfetch -FRICTIONMOD ]
	set MAXSPEED [ ltfetch -MAXSPEED ]
	set REVERSEMAXSPEED [ ltfetch -REVERSEMAXSPEED ]
	set REVERSEACCELERTAION [ ltfetch -REVERSEACCELERTAION  ]
	set TURNIMPACTONSPEED [ ltfetch -TURNIMPACTONSPEED  ]
	set MAXTURNRATE [ ltfetch -MAXTURNRATE  ]
	set turnFun [ ltfetch -turnFun ]
 
	if {$key == $keyUp || $key == $keyUpLeft || $key == $keyUpRight} {
		set speed [expr $speed + $ACCELERTAION];
	}
	set speed [expr $speed * $FRICTIONMOD];
	if {$key == $keyDown || $key == $keyDownLeft || $key == $keyDownRight} {
		set speed [expr $speed - $REVERSEACCELERTAION];
	}	
	if {$key == $keyRight || $key == $keyUpRight || $key == $keyDownRight} {
		if {$speed > [expr $MAXSPEED / 4]} {
			set oriOut [expr $oriOut + $MAXTURNRATE];
		} elseif {$speed < ($MAXSPEED / 4) && $speed >= 0} {
			set oriOut [expr $oriOut + (($MAXTURNRATE / 4) * $speed)];
		} elseif {$speed < 0} {
			set oriOut [expr $oriOut + (($MAXTURNRATE * $speed) / ($MAXSPEED / 4) * 3)];
		}
		set speed [expr $speed * $TURNIMPACTONSPEED];	
	}
 
	if {$key == $keyLeft || $key == $keyUpLeft || $key == $keyDownLeft} {
		if {$speed > [expr $MAXSPEED / 4]} {
			set oriOut [expr $oriOut - $MAXTURNRATE];
		} elseif {$speed < ($MAXSPEED / 4) && $speed >= 0} {
			set oriOut [expr $oriOut - (($MAXTURNRATE / 4) * $speed)];
		} elseif {$speed < 0} {
			set oriOut [expr $oriOut - (($MAXTURNRATE * $speed) / ($MAXSPEED / 4) * 3)];
		}
		set speed [expr $speed * $TURNIMPACTONSPEED];	
	}
 
	set turnFunAdd 100
	if {$key == $keyLeft} {
		set turnFun [expr $turnFun - $turnFunAdd]
	} elseif {$key == $keyRight} {
		set turnFun [expr $turnFun + $turnFunAdd]
	} elseif {$turnFun > 0 } {
		set turnFun [expr $turnFun - $turnFunAdd]
	} elseif {$turnFun < 0 } {
		set turnFun [expr $turnFun + $turnFunAdd]
	}
 
	if {abs($speed) > $MAXSPEED} {
		set speed $MAXSPEED;
	}
 
	if {$speed < $REVERSEMAXSPEED} {
		set speed $REVERSEMAXSPEED;
	}
 
	set pi 3.1415926535;
	set xAdd [expr sin($oriOut * $pi / 180.0) * $speed];
	set yAdd [expr cos($oriOut * $pi / 180.0) * (-1 * $speed)];
	set posOutX [expr $posOutX + $xAdd * $deltaTime];
	set posOutY [expr $posOutY + $yAdd * $deltaTime];
 
	if {$doHitTest == 1} {
		#Check for collision
		set dist1 1111
		set dist2 1111
		for {set a 1} {$a < [expr [llength $polylMVec3] - 1]} {set a [expr $a+3]} {
			set dist1 [distanzPunktGerade [lindex $polylMVec3Left $a] "$posOutX $posOutY 0" "$oriOut 0 0"]
			set dist2 [distanzPunktGerade [lindex $polylMVec3Right [expr $a-1]] "$posOutX $posOutY 0" "$oriOut 0 0"]
			set hitTestThreshold 50.0
			# Reaction for collision
			if {$dist1 < $hitTestThreshold | $dist2 < $hitTestThreshold} {
				if {$speed > 0} {
					set speed -20.0
				} else {
					set speed 20.0
				}
			}
		}
	}
 
	ltset -posOut "$posOutX $posOutY 5"
	ltset -oriOutVec3Out "$oriOut 0 0"
	ltset -speedOut "$speed"
	ltset -turnFun "$turnFun"
 
	set camPosX [expr $posOutX - 90]
	set camPosY [expr $posOutY - 90]
 
	ltset -timeLastIn $currentTime
	set speedMul [expr $speed * 3 + 200]
	set speedMulUp [expr $speedMul / 3]
	ltupdate camXForm -position2In "$turnFun $speedMul $speedMulUp"
 
	if {$key == 32} {
		puts "Current Position: lappend polylMVec3 \"$posOutX $posOutY 5\""
		ltset -doHitTestIn 1
		puts "HitTest Reaction ON"
	} elseif {$key == 88 || $key == 79} {
		ltset -doHitTestIn 0
		puts "HitTest Reaction OFF"
	}
}
#Stereo enable: ltupdate move -camNamesIn $cameranames
#Stereo enable2: ltroute "win1 -keyOut" "move -keyIn" 
ltroute "window -keyOut" "move -keyIn"
ltroute "timer -timeOut" "move -timeIn"
ltroute "move -posOut" "cube -positionIn"
ltroute "move -posOut" "camXForm -positionIn"
ltroute "move -oriOutVec3Out" "cube -orientationIn"
ltroute "move -oriOutVec3Out" "camXForm -orientationIn"
ltroute "camXForm -positionOut -orientationOut" "camera -positionIn -orientationIn"