Data Files for “Table Tennis” Tutorial

CreateTable.p3dat

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
fish define dim_table
  xTable=array.create(1,2)
  yTable=array.create(1,2)
  xTable(1,1) = -1
  xTable(1,2) = 1
  Lx = math.abs(xTable(1,1))+math.abs(xTable(1,2))
  Ly = Lx*0.6
  yTable(1,1) = domain.min.y*0.95
  yTable(1,2) = yTable(1,1)+Ly
  zTable = (domain.min.z+domain.max.z)*0.5
end
@dim_table

; creation of the table
wall generate group 'table' polygon ...
            @xTable(1,2) @yTable(1,1) @zTable ...
            @xTable(1,2) @yTable(1,2) @zTable ...
            @xTable(1,1) @yTable(1,1) @zTable ...
            @xTable(1,1) @yTable(1,2) @zTable

; insertion of table legs
wall generate group 'table' cylinder ...
    axis 0 0 -1 ...
    base @xTable(1,2) @yTable(1,1) @zTable ...
    height [Ly*0.5] ...
    one-wall ...
    radius [Lx*0.02]

wall generate group 'table' cylinder ...
    axis 0 0 -1 ...
    base @xTable(1,2) @yTable(1,2) @zTable ...
    height [Ly*0.5] ...
    one-wall ...
    radius [Lx*0.02]
    
wall generate group 'table' cylinder ...
    axis 0 0 -1 ...
    base @xTable(1,1) @yTable(1,1) @zTable ...
    height [Ly*0.5] ...
    one-wall ...
    radius [Lx*0.02]
    
wall generate group 'table' cylinder ...
    axis 0 0 -1 ...
    base @xTable(1,1) @yTable(1,2) @zTable ...
    height [Ly*0.5] ...
    one-wall ...
    radius [Lx*0.02]

; creation of the net
wall generate group 'net' polygon ...
           [(xTable(1,1)+xTable(1,2))*0.5] @yTable(1,1) @zTable ...
           [(xTable(1,1)+xTable(1,2))*0.5] @yTable(1,2) @zTable ...
           [(xTable(1,1)+xTable(1,2))*0.5] @yTable(1,1) [zTable+Lx*0.075] ...
           [(xTable(1,1)+xTable(1,2))*0.5] @yTable(1,2) [zTable+Lx*0.075]

;creation of the rackets
wall generate group 'player1' disk ... ;racket Player1
    dip 90 ...
    dip-direction 90 ...
    position @xTable(1,1) [(yTable(1,1)+yTable(1,2))*0.5] [zTable+Ly*0.3] ...
    rad [Lx*0.05]

wall generate group 'player2' disk ... ;racket Player2
    dip 90 ...
    dip-direction 90 ...
    position @xTable(1,2) [(yTable(1,1)+yTable(1,2))*0.5] [zTable+Ly*0.3] ...
    rad [Lx*0.05]

model save 'table'

TennisTable.p3dat

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
; fname: TableTennis.p3dat
; The example shows how to create a table tennis game!
;
; ====================================================
model new

;define the initial velocity of the ball
[XballInitialVelocity = -3.0]
[ZballInitialVelocity = 2.0]

; definition of extent and condition
model domain extent -1.5 1.5
model domain condition destroy

;creation of the table
call 'CreateTable.p3dat'

;creation of the ball
ball create id 1 ...
            radius   [Lx*0.005]                      ...
            position [xTable(1,2)*0.98]              ...
                     [(yTable(1,1)+yTable(1,2))*0.5] ...
                     [zTable+Ly*0.3]
ball trace id 1
ball attribute density 10            ...
    velocity-x @XballInitialVelocity ...
    velocity-z @ZballInitialVelocity
[bp = ball.find(1)]

;linear model for ball-facet contacts
contact cmat default type ball-facet model linear ...
   property kn 1e6 ks 1e6 fric 0.009

model gravity 0 0 -9.81

;check for ball-net contacts
fish define checknet(arr)
    ct=arr(1)
    ;in case of ball-facet contacts, contact.end1 refers to the ball, 
    ;contact.end2 refers to the facet
    if wall.group(wall.facet.wall(contact.end2(ct)),"Default") == "net"
      io.out("Net!!")
      ball.vel(bp,1)=0
      ball.vel(bp,3)=0
    endif
end

;check fi=ot ball-table contacts!
fish define tablecontact(ct)
    con = ct(1)
    ;in case of ball-facet contacts, contact.end1 refers to the ball,
    ;contact.end2 refers to the facet
    if wall.group(wall.facet.wall(contact.end2(con)),"Default") == "table"
      moverackets
    endif
end

;compute the new position of the racket and move it!
fish define moverackets
  xvel = ball.vel.x(bp)
  zvel = ball.vel.z(bp)
  xpos = ball.pos.x(bp)
  zpos = ball.pos.z(bp)
  if xvel < 0
    if xpos > 0   
      ball.vel(bp,1)=0
      ball.vel(bp,3)=0
	  io.out("Fault!!")
    endif
    wp = wall.find(7)
    L = xTable(1,1) - xpos
  else
    if xpos < 0   
      ball.vel(bp,1)=0
      ball.vel(bp,3)=0
	  io.out("Fault!!")
    endif
    wp = wall.find(8)
    L = xTable(1,2) - xpos
  endif
    zM = -(zvel/xvel)*L + (-9.81/2)*((L/xvel)^2)
  if zM > domain.min.z
    if zM < domain.max.z
      wall.pos.z(wp) = zM + zpos
    endif
  endif
end

;set fish callbacks to check if the ball touches the net
fish callback add @checknet event contact_activated
;set fish callback to prepare the racket position
fish callback add @tablecontact event contact_activated
model solve time 1.0
model save 'game'
;==============================================================
;eof: TableTennis.p3dat