| 1 | # -*- Mode:Python -*- |
|---|
| 2 | |
|---|
| 3 | ########################################################################## |
|---|
| 4 | # # |
|---|
| 5 | # This file is part of AVANGO. # |
|---|
| 6 | # # |
|---|
| 7 | # Copyright 1997 - 2008 Fraunhofer-Gesellschaft zur Foerderung der # |
|---|
| 8 | # angewandten Forschung (FhG), Munich, Germany. # |
|---|
| 9 | # # |
|---|
| 10 | # AVANGO is free software: you can redistribute it and/or modify # |
|---|
| 11 | # it under the terms of the GNU Lesser General Public License as # |
|---|
| 12 | # published by the Free Software Foundation, version 3. # |
|---|
| 13 | # # |
|---|
| 14 | # AVANGO is distributed in the hope that it will be useful, # |
|---|
| 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # |
|---|
| 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # |
|---|
| 17 | # GNU General Public License for more details. # |
|---|
| 18 | # # |
|---|
| 19 | # You should have received a copy of the GNU Lesser General Public # |
|---|
| 20 | # License along with AVANGO. If not, see <http://www.gnu.org/licenses/>. # |
|---|
| 21 | # # |
|---|
| 22 | ########################################################################## |
|---|
| 23 | |
|---|
| 24 | import math |
|---|
| 25 | import avango.script |
|---|
| 26 | from avango.script import field_has_changed |
|---|
| 27 | import avango.osg.simpleviewer |
|---|
| 28 | import avango.osg.particle |
|---|
| 29 | import avango.daemon |
|---|
| 30 | |
|---|
| 31 | class FakeSensor(avango.script.Script): |
|---|
| 32 | TimeIn = avango.SFDouble() |
|---|
| 33 | MatrixOut = avango.osg.SFMatrix() |
|---|
| 34 | |
|---|
| 35 | def evaluate(self): |
|---|
| 36 | self.MatrixOut.value = avango.osg.make_trans_mat(0., -0.03, 0.) |
|---|
| 37 | |
|---|
| 38 | def make_fake_sensor(): |
|---|
| 39 | time = avango.nodes.TimeSensor() |
|---|
| 40 | sensor = FakeSensor() |
|---|
| 41 | sensor.TimeIn.connect_from(time.Time) |
|---|
| 42 | return sensor |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | class DumpMatrix(avango.script.Script): |
|---|
| 46 | Matrix = avango.osg.SFMatrix() |
|---|
| 47 | def evaluate(self): |
|---|
| 48 | trans = self.Matrix.value.get_translate() |
|---|
| 49 | print trans.x, trans.y, trans.z |
|---|
| 50 | |
|---|
| 51 | class Scale(avango.script.Script): |
|---|
| 52 | MatrixIn = avango.osg.SFMatrix() |
|---|
| 53 | MatrixOut = avango.osg.SFMatrix() |
|---|
| 54 | |
|---|
| 55 | def evaluate(self): |
|---|
| 56 | values = self.get_values() |
|---|
| 57 | trans = values.MatrixIn.get_translate() |
|---|
| 58 | trans /= 10000. |
|---|
| 59 | matrix = avango.osg.make_trans_mat(trans) |
|---|
| 60 | values.MatrixOut = matrix |
|---|
| 61 | |
|---|
| 62 | class Accumulate(avango.script.Script): |
|---|
| 63 | MatrixRef = avango.osg.SFMatrix() |
|---|
| 64 | MatrixIn = avango.osg.SFMatrix() |
|---|
| 65 | MatrixOut = avango.osg.SFMatrix() |
|---|
| 66 | |
|---|
| 67 | def evaluate(self): |
|---|
| 68 | self.MatrixOut.value = self.MatrixIn.value * self.MatrixRef.value |
|---|
| 69 | |
|---|
| 70 | class Collision(avango.script.Script): |
|---|
| 71 | MatrixRef = avango.osg.SFMatrix() |
|---|
| 72 | MatrixIn = avango.osg.SFMatrix() |
|---|
| 73 | MatrixOut = avango.osg.SFMatrix() |
|---|
| 74 | RootNode = avango.osg.SFNode() |
|---|
| 75 | |
|---|
| 76 | def evaluate(self): |
|---|
| 77 | values = self.get_values() |
|---|
| 78 | trans_in = values.MatrixIn.get_translate() |
|---|
| 79 | trans_ref = values.MatrixRef.get_translate() |
|---|
| 80 | hit = avango.osg.line_intersect(trans_ref, trans_in, values.RootNode) |
|---|
| 81 | if hit != trans_in: |
|---|
| 82 | new_matrix = values.MatrixRef |
|---|
| 83 | else: |
|---|
| 84 | new_matrix = values.MatrixIn |
|---|
| 85 | values.MatrixOut = new_matrix |
|---|
| 86 | |
|---|
| 87 | class GroundFollowing(avango.script.Script): |
|---|
| 88 | MatrixIn = avango.osg.SFMatrix() |
|---|
| 89 | MatrixOut = avango.osg.SFMatrix() |
|---|
| 90 | RootNode = avango.osg.SFNode() |
|---|
| 91 | Height = avango.SFFloat() |
|---|
| 92 | JumpLength = avango.SFFloat() |
|---|
| 93 | FallLength = avango.SFFloat() |
|---|
| 94 | |
|---|
| 95 | def evaluate(self): |
|---|
| 96 | values = self.get_values() |
|---|
| 97 | matrix = values.MatrixIn |
|---|
| 98 | translation = matrix.get_translate() |
|---|
| 99 | line_start = translation + avango.osg.Vec3(0, 0, values.JumpLength) |
|---|
| 100 | line_end = translation - avango.osg.Vec3(0, 0, values.FallLength) |
|---|
| 101 | hit = avango.osg.line_intersect(line_start, line_end, values.RootNode) |
|---|
| 102 | if hit != line_end: |
|---|
| 103 | height_offset = avango.osg.Vec3(0, 0, values.Height) |
|---|
| 104 | matrix.set_translate(hit+height_offset) |
|---|
| 105 | values.MatrixOut = matrix |
|---|
| 106 | |
|---|
| 107 | |
|---|
| 108 | class MatrixFeedback(avango.script.Script): |
|---|
| 109 | IsSource = avango.SFBool() |
|---|
| 110 | MatrixIn = avango.osg.SFMatrix() |
|---|
| 111 | MatrixOut = avango.osg.SFMatrix() |
|---|
| 112 | |
|---|
| 113 | @field_has_changed(IsSource) |
|---|
| 114 | def set_source(self): |
|---|
| 115 | self.MatrixIn.enable_dependency(not self.IsSource.value) |
|---|
| 116 | |
|---|
| 117 | def evaluate(self): |
|---|
| 118 | self.MatrixOut.value = self.MatrixIn.value |
|---|
| 119 | |
|---|
| 120 | def make_ball(root): |
|---|
| 121 | ball = avango.osg.nodes.Sphere(Color = avango.osg.Vec4(1,1,0,1), Radius = 0.2) |
|---|
| 122 | feedback_source = MatrixFeedback(IsSource = True) |
|---|
| 123 | feedback_sink = MatrixFeedback(IsSource = False) |
|---|
| 124 | feedback_source.MatrixIn.connect_from(feedback_sink.MatrixOut) |
|---|
| 125 | |
|---|
| 126 | #sensor = make_fake_sensor() |
|---|
| 127 | service = avango.daemon.DeviceService() |
|---|
| 128 | sensor = avango.daemon.nodes.DeviceSensor(DeviceService = service, |
|---|
| 129 | Station = "noyo-minispace") |
|---|
| 130 | |
|---|
| 131 | scale = Scale() |
|---|
| 132 | accum = Accumulate() |
|---|
| 133 | collision = Collision() |
|---|
| 134 | ground_following = GroundFollowing(Height = 0.1, JumpLength = 0.1, FallLength = 0.5) |
|---|
| 135 | |
|---|
| 136 | scale.MatrixIn.connect_from(sensor.Matrix) |
|---|
| 137 | accum.MatrixIn.connect_from(scale.MatrixOut) |
|---|
| 138 | accum.MatrixRef.connect_from(feedback_source.MatrixOut) |
|---|
| 139 | ground_following.RootNode.value = root |
|---|
| 140 | ground_following.MatrixIn.connect_from(accum.MatrixOut) |
|---|
| 141 | #collision.RootNode.value = root |
|---|
| 142 | #collision.MatrixIn.connect_from(accum.MatrixOut) |
|---|
| 143 | #collision.MatrixRef.connect_from(feedback_source.MatrixOut) |
|---|
| 144 | |
|---|
| 145 | pipeline_end = ground_following |
|---|
| 146 | feedback_sink.MatrixIn.connect_from(pipeline_end.MatrixOut) |
|---|
| 147 | ball.Matrix.connect_from(pipeline_end.MatrixOut) |
|---|
| 148 | |
|---|
| 149 | return ball |
|---|
| 150 | |
|---|
| 151 | |
|---|
| 152 | def make_precipitation(): |
|---|
| 153 | # setup a precipitation effect with fog |
|---|
| 154 | precip = avango.osg.particle.nodes.PrecipitationEffect(Fog = avango.osg.nodes.Fog()) |
|---|
| 155 | precip.CellSize.value = avango.osg.Vec3(10,10,10) |
|---|
| 156 | |
|---|
| 157 | # setup stateset |
|---|
| 158 | state = avango.osg.nodes.StateSet(FogMode = 1, Fog = precip.Fog.value) |
|---|
| 159 | |
|---|
| 160 | return precip, state |
|---|
| 161 | |
|---|
| 162 | |
|---|
| 163 | def make_land(): |
|---|
| 164 | land = avango.osg.nodes.LoadFile(Filename = 'Models/lzsnow.osg') |
|---|
| 165 | land.Matrix.value = avango.osg.make_rot_mat(math.radians(63), 0, 0, 1) * avango.osg.make_trans_mat(-20, -20, -98) |
|---|
| 166 | return land |
|---|
| 167 | |
|---|
| 168 | |
|---|
| 169 | def make_sky(): |
|---|
| 170 | sky = avango.osg.nodes.LoadFile(Filename = 'Models/skydome.osg') |
|---|
| 171 | sky.Matrix.value = avango.osg.make_trans_mat(-26634.0, -37420.0, -2500) * avango.osg.make_scale_mat(0.07, 0.07, 0.15) |
|---|
| 172 | skystate = avango.osg.nodes.StateSet(Fog = avango.osg.nodes.Fog(), FogMode = 1) |
|---|
| 173 | sky.StateSet.value = skystate |
|---|
| 174 | return sky, skystate.Fog.value |
|---|
| 175 | |
|---|
| 176 | |
|---|
| 177 | class Main(object): |
|---|
| 178 | def __init__(self): |
|---|
| 179 | self.precip, self.state = make_precipitation() |
|---|
| 180 | self.land = make_land() |
|---|
| 181 | self.sky, self.skyfog = make_sky() |
|---|
| 182 | self.skyfog.Color.connect_from(self.precip.Fog.value.Color) |
|---|
| 183 | self.root = avango.osg.nodes.Group(StateSet = self.state) |
|---|
| 184 | self.ball = make_ball(self.root) |
|---|
| 185 | self.root.Children.value = [ self.land, self.sky, self.precip, self.ball] |
|---|
| 186 | |
|---|
| 187 | def run(self): |
|---|
| 188 | # start simpleviewer |
|---|
| 189 | avango.osg.simpleviewer.run(self.root) |
|---|
| 190 | |
|---|
| 191 | def snow(self, value): |
|---|
| 192 | self.precip.Snow.value = value |
|---|
| 193 | self.precip.Fog.value.Density.value *= 1.5 |
|---|
| 194 | self.skyfog.Density.value = self.precip.Fog.value.Density.value * 0.2 |
|---|
| 195 | self.precip.Wind.value = avango.osg.Vec3(value * -4, 0, -1) |
|---|
| 196 | |
|---|
| 197 | def rain(self, value): |
|---|
| 198 | self.precip.Rain = value |
|---|
| 199 | self.precip.Fog.value.Density.value *= 1.5 |
|---|
| 200 | self.skyfog.Density.value = self.precip.Fog.value.Density.value * 0.2 |
|---|
| 201 | self.precip.Wind.value = avango.osg.Vec3(value * -4, 0, -1) |
|---|
| 202 | |
|---|
| 203 | |
|---|
| 204 | def start(): |
|---|
| 205 | main = Main() |
|---|
| 206 | main.snow(0.3) |
|---|
| 207 | main.run() |
|---|
| 208 | |
|---|
| 209 | if __name__ == '__main__': |
|---|
| 210 | start() |
|---|