-
Notifications
You must be signed in to change notification settings - Fork 0
/
spec.docbook
4029 lines (3886 loc) · 181 KB
/
spec.docbook
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"/usr/share/sgml/docbook/xml-dtd-4.3/docbookx.dtd" [
<!ENTITY Bez "Bézier">
<!ENTITY Types SYSTEM "protocol/types.snip">
<!ENTITY Commands SYSTEM "protocol/cmd.snip">
<!ENTITY Command-Index SYSTEM "protocol/cmd-indx.snip">
<!ENTITY API SYSTEM "protocol/api.snip">
<!ENTITY GNUFDL SYSTEM "fdl.xml">
<!ENTITY time_s "<varname>time_s</varname>">
<!ENTITY time_f "<varname>time_f</varname>">
]>
<book lang="en">
<bookinfo>
<title>The Verse Specification</title>
<subtitle>A platform for sharing 3D data</subtitle>
<author><firstname>Emil</firstname> <surname>Brink</surname></author>
<author><firstname>Eskil</firstname> <surname>Steenberg</surname></author>
<copyright><year>2004-2007</year><holder>PDC, KTH</holder></copyright>
<!-- We mis-use the abstract (apologies) mildly, to contain the version symbol. -->
<abstract>
<para>
This document describes version R6 of the Verse platform. The description
covers the data model, the protocol, and the client API.
</para>
</abstract>
<!-- For reasons unknown, this log isn't actually rendered in the final HTML. -->
<revhistory>
<revision>
<revnumber>R6-2</revnumber>
<date>February, 2007</date>
<authorinitials>eb</authorinitials>
<revremark>Added lots of text in the Security section</revremark>
</revision>
<revision>
<revnumber>R6</revnumber>
<date>June 2006</date>
<authorinitials>eb</authorinitials>
<revremark>Updated for Verse R6 release.</revremark>
</revision>
</revhistory>
<legalnotice>
<para>
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled
<link linkend='gfdl'>GNU Free Documentation License</link>.
</para>
</legalnotice>
</bookinfo>
<preface id='preface'>
<title>Preface</title>
<abstract>
<title>Abstract</title>
<para>This is the Official Verse Specification. It is intended to fully specify the Verse platform,
by breaking it down into manageable parts and then describing each of those in an exhaustive manner.
</para>
<para>
This specification should be complete and precise enough to serve as the basis for creating a
new Verse implementation, while retaining compatibility on all levels with the existing one.
</para>
<para>
While great care has been taken in preparing this document, there will most likely be omissions
or even errors. We apologize, and ask that you help us improve this document whenever you find
a problem, by reporting it to us. Thanks.
</para>
</abstract>
</preface>
<chapter id='introduction'>
<title>Introduction</title>
<para>
</para>
<sect1>
<title>What is Verse?</title>
<para>
Verse is a platform for building networked applications centered around sharing and processing 3D data.
It consists of three parts, on different levels of abstraction:
the <link linkend="datamodel">data model</link>,
the <link linkend="protocol">network protocol</link>, and
the <link linkend="api">programming interface</link>. Below are condensed descriptions of these
three parts, hoping to convey a general idea quickly.
<variablelist>
<varlistentry>
<term><link linkend="datamodel">Data Model</link></term>
<listitem>
<para>
Verse defines a data model, which in turn defines exactly how data is formatted and stored.
The model is optimized and tailored for handling data suitable for building very dynamic
and highly interactive virtual worlds.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><link linkend="protocol">Network Protocol</link></term>
<listitem>
<para>
In order to make the data model accessible remotely, Verse defines a set of commands that can
be used to interact with data hosted on some computer. This set of commands is encoded on the
network in the exact manner described by the network protocol specification.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><link linkend="api">Programming Interface</link></term>
<listitem>
<para>
To make creating applications that use the Verse data model and protocol easy, a reference
application programming interface (<acronym>API</acronym>) has been created.
</para>
</listitem>
</varlistentry>
</variablelist>
The sections linked by the terms above provide plenty of additional detail about these three
parts of the platform, and appear in the order recommended for reading them.
</para>
</sect1>
<sect1 id='about'>
<title>About this Document</title>
<para>
This document is intended to be a complete specification of the Verse system, in all its parts. It begins
by describing the data model, moves along to how the data model is made available over a network, and finally
talks about the Verse standard C application programming interface.
</para>
<para>
The reader is assumed to have a certain level of technical proficiency, since this document often has reason
to be rather low-level. The detail level can be said to increase over the three major parts, but this is more
of a general trend than a struct rule.
</para>
<para>
This document was written by Emil Brink, with much of the initial structure and text coming from an original document
by Eskil Steenberg, and his reference implementation of the Verse standard. Most of the document was written in the
<ulink url='http://www.docbook.org/'>DocBook</ulink> format, although much of the highly structured data
(the type, command and API references) were created programmatically from custom XML data, processed into
DocBook using <ulink url='http://www.w3.org/TR/xslt'>XSLT</ulink>.
</para>
</sect1>
</chapter>
<chapter id="datamodel">
<title>Data Model</title>
<para>
One core part of Verse is a data model for storing 3D data detailed enough to describe a <quote>virtual world</quote>.
The data model tries hard to allow for as much flexibility as possible in what can be stored, while also trying
to be no larger than necessary. This section will describe this data model exhaustively, by presenting the the
abstractions and structures used to represent data throughout Verse. We begin with the underlying idea, the
almost-philosophical concept of perfect data.
</para>
<note>
<para>
Throughout this section, sidebars labelled <quote>API Link</quote> appear, that reference you straight to the
function(s) in the <link linkend='api'>API chapter</link> that deal with that particular aspect of the model.
</para>
</note>
<!-- DO NOT MENTION NODES YET! -->
<sect1>
<title>Perfect Data</title>
<para>
Verse's data model is designed around the philosophy of "perfect data". With this, it is meant that the data
doesn't describe <emphasis>how</emphasis> to render the graphics, but more how the graphics should look.
It is then up to each client to do a "best effort render" of the data. The idea is to support creation of
datasets that are as easy as possible to use independently of the application.
</para>
<para>
The 3D geometry data is based around a single primitive: subdivided polygons. A subdivided polygon is
an ordinary polygon that has been extended with information about its <emphasis>creases</emphasis>,
allowing subdivision algorithms to intelligently split the single polygon into several to create a
3:rd degree curved surface that is smooth. This means that you may display the graphics as
simple, planar, polygons, but you can also subdivide them to increase the smoothness of the surfaces.
Subdivision is compatible with a lot of existing 3D software, since you can convert polygons, B-splines,
patches and NURBS into subdivision surfaces without loss of precision.
</para>
<para>
The Verse data model has many features such as:
<itemizedlist>
<listitem><para>An advanced shader tree supporting surface properties like
color, texture, lighting and displacement.</para></listitem>
<listitem><para>High dynamic range textures.</para></listitem>
<listitem><para>Animation curves.</para></listitem>
<listitem><para>Generic surface properties for storing UV, color, selections and other data.</para></listitem>
<listitem><para>A system-wide <emphasis>tag system</emphasis> lets users store additional custom data.</para></listitem>
</itemizedlist>
</para>
<para>
Verse can store text that lets each object be associated with scripts; these scripts can be read and executed by a
client, which can run on the server side. This is a very flexible way of doing scripting, since engines
can be written by anyone and for any language, making Verse language-independent. In addition to the text node
and tags, object nodes can have generic method calls that can be passed between clients.
</para>
</sect1>
<sect1 id='sessions'>
<title>Sessions</title>
<para>
At the top level, Verse data is always associated with with a <emphasis>session</emphasis>. Session is a name for
the connection between two applications that talk using the Verse protocol. Typically, in such a situation, one
end is called the <emphasis>host</emphasis> and the other is the <emphasis>client</emphasis>.
</para>
<para>
Hosts are mainly passive, acting as containers of data made available to clients. Clients do all the work by
connecting to a host and manipulating (reading, writing, creating, editing, and generally using) the data held
by it. Several clients can connect to the same host simultaneously, and will then be given individual views of
the data contained on the server. Typically, much data will be shared, so that they both get the sensation of
being in the same world and so that data modified by one client is visible to all other clients.
</para>
<para>
At the user level, hosts are perceived as <quote>containing</quote> a world, and making it available to clients
through the Verse protocol. In this regard, Verse hosts are very similar to the server in any common client-server
system, such as a web server for instance. It stores content, and makes it available to clients through a well-defined
communications protocol.
</para>
<sect2>
<title>Time</title>
<para>
Many operations in Verse are independent of time, they happen <emphasis>now</emphasis>, which is as soon as
the data arrives, it is assumed to be valid immediately upon receipt. Some operations, however, do not make
sense without a concept of time. As we'll see later, it is possible for a client to read out the current time,
and receive a value which is (more or less) in sync with the host's idea of what time it is.
</para>
<para>
Time is counted in seconds, with a precision of 64 bits. Of these, 32 bits are the number of whole seconds since
some unspecified previous event (such as the starting of the host), while the remaining 32 bits are fractions.
Fractions are used so that times less than one second can be expressed. So, time is a pair of unsigned 32-bit integers,
one called &time_s; (the whole seconds) and the other &time_f; (the fractional part).
</para>
<para>
The &time_f; fractional part is in units of 1/4,294,967,296:th of a second. This means that the time
<quote>four and a half seconds</quote> is expressed as the pair of values (&time_s;=4, &time_f;=2,147,483,648).
</para>
</sect2>
</sect1>
<sect1 id="subscription">
<title>Subscription</title>
<para>
In order for the client side to be able to participate in the session created by connecting to a host, it must
ask the host for data. This is done by <emphasis>subscribing</emphasis> to data of interest. Only clients are
allowed to subscribe to data, and hosts are only allowed to send data to a client that has been explicitly
requested in the form of a subscription.
</para>
<para>
When a client first subscribes to some piece of data, such as a polygon mesh, the host must send the current
state of that data to the client. Then, whenever the data changes, it must send those changes to the client
for as long as the client remains a subscriber. From the client's point of view, there is no difference in
handling initial data being sent, and handling changes later on: they are all delivered in the same way which
makes it easy to deal data in this fashion.
</para>
<para>
<emphasis>All</emphasis> data made available by a Verse host can be accessed through subscription in one way
or another, and being a subscriber is generally required before data can be read or written easily. This is
because being a subcriber ensures that the client has full access to whatever addressing information is used
for the data in question.
</para>
<note>
<para>
It is not the intent of the subscription system to serve as a security device, to
limit access to data to those clients that are subscribed. For instance, it is perfectly legal to create a
new <link linkend='n-geometry'>geometry node</link>, and then immediately send vertex and polygon data to the
known layers <literal>0</literal> and <literal>1</literal>. Because these layers are known to exist in all
geometry nodes, it is not even necessary to subscribe to the <emphasis>node</emphasis>, much less the layers.
</para>
<para>
The main purpose of the subscription-oriented data access architecture is to limit the bandwidth used by a
client, by permitting a client to tell a host which data it is interested in, and thus which data it needs
to download and receive updates to.
</para>
</note>
<para>
There is no data that cannot be changed at any time during a session, which helps make the system very dynamic.
Being prepared for this and designing data structures accordingly is a great skill to have when writing Verse
applications.
</para>
</sect1>
<sect1 id="nodes">
<title>Nodes</title>
<para>
All data in Verse is arranged into <emphasis>nodes</emphasis>. Nodes group data according to
it's character, and are optimized for storing one particular kind of data per node type. There
are seven distinct node types defined: Object, Geometry, Material, Bitmap, Text, Audio and Curve.
</para>
<para>
Nodes are identified <emphasis>within a session</emphasis> through numbers assigned by the host. All node IDs
are valid only inside that session; two clients running on the same physical machine but connected to the same
host cannot directly exchange node IDs with each other and expect a sensible result. See below for a portable
way to reference nodes, however.
</para>
<para>
As we shall see, most nodes have a lot of internal structure (layers, fragments, buffers, channels, et cetera), that
are always also identified using numerical IDs. Unlike node IDs, these numbers <emphasis>can</emphasis> be shared
as long as the context is also provided. So, if a host contains a geometry node that client A knows as node
number 4096, and client B knows as node number 8999, the layer that A thinks is 4096.17 will be the exact same
data as B sees as 8999.17. This is harder to explain in a simple way, than it is to actually understand, we hope.
</para>
<sect2>
<title>Common Data</title>
<para>
There are some data storage facilities shared by all nodes, regardless of the node's type. These are described
below.
</para>
<sect3>
<title>Name</title>
<para>
All nodes have, in addition to the numerical ID mentioned above, a textual name. Unlike the IDs, the names are
<emphasis>not</emphasis> session-specific but can be shared between sessions. Names should be unique across
all nodes.
</para>
<sidebar>
<title>API Link</title>
<para>To set the name of a node, use the <xref linkend='verse_send_node_name_set'/> function.
</para>
</sidebar>
</sect3>
<sect3>
<title>Tags</title>
<para>
<emphasis>Tags</emphasis> provide a place where applications can store custom data associated with a node. This
is handy for expressing things that do not fit straight into the data model, but are nevertheless required by
applications for processing. Tags are like variables in a programming language; they have a name (and a numerical
ID for reference, as always) and a value of a certain type. There are numerical and textual types, plus some more
intricate ones.
</para>
<para>
To ease management, tags are collected into <emphasis>tag groups</emphasis>. Tag groups are simply named containers
for tags, that allow related tags to be grouped together. Also, tag groups can be subscribed to which gives better
subscription granularity than if individual tags could be. Tag groups do not nest, it is not possible to have
groups within groups within groups.
</para>
<para>
These are the types of tag values supported:
<informaltable>
<tgroup cols='2'>
<thead>
<row>
<entry align='center'>Name</entry>
<entry align='left'>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>VN_TAG_BOOLEAN</entry>
<entry>Boolean value, i.e. true or false only.</entry>
</row>
<row>
<entry>VN_TAG_UINT32</entry>
<entry>Unsigned 32-bit integer value.</entry>
</row>
<row>
<entry>VN_TAG_REAL64</entry>
<entry>64-bit floating point value.</entry>
</row>
<row>
<entry>VN_TAG_STRING</entry>
<entry>A textual string.</entry>
</row>
<row>
<entry>VN_TAG_REAL64_VEC3</entry>
<entry>Vector of three 64-bit floating point values.</entry>
</row>
<row>
<entry>VN_TAG_LINK</entry>
<entry>Link to another node.</entry>
</row>
<row>
<entry>VN_TAG_ANIMATION</entry>
<entry>Link to a <link linkend='n-curve'>curve node</link>. Subject to change.</entry>
</row>
<row>
<entry>VN_TAG_BLOB</entry>
<entry>Unstructured binary data (<quote>binary large object</quote>).</entry>
</row>
</tbody>
</tgroup>
</informaltable>
A tag always has a value, which means that it always has exactly one type. It is possible to rename, delete,
and change the type of tags, as well as create new tags of course. We will see later on how these actions
are performed, in the <link linkend='system-commands'>system commands</link> section.
</para>
<sidebar>
<title>API Links</title>
<para>Tags groups are manipulated using the <xref linkend='verse_send_tag_group_create'/>,
<xref linkend='verse_send_tag_group_destroy'/>,
<xref linkend='verse_send_tag_group_subscribe'/> and
<xref linkend='verse_send_tag_group_unsubscribe'/> functions. Tags are manipulated using the
<xref linkend='verse_send_tag_create'/> and <xref linkend='verse_send_tag_destroy'/> functions.
</para>
</sidebar>
</sect3>
</sect2>
</sect1>
<sect1 id="n-object" xreflabel='object node'>
<title>The Object Node</title>
<para>
The <emphasis>object node</emphasis> acts as the root for data storage in Verse's data model. Its purpose is to
represent <quote>objects</quote> in a virtual world. All data in nodes of other types goes unused unless it is connected
to a tree rooted in an object node. The object node itself does not hold much actual data, but it provides
a transform and various other features.
</para>
<sect2 id='obj-link'>
<title>Links</title>
<para>
The object node has the ability to link to other nodes, specifying different properties (geometry, materials,
associated scripts and so son) of the represented object. Multiple object nodes may all link to the same geometry
node, to share the data and thus create several identical copies of an object.
</para>
<para>
Links are unidirectional, going <emphasis>from</emphasis> an object node and <emphasis>to</emphasis> the link
target which can be a node of any type. Links have textual labels, which are used to denote the purpose of
the link (for instance, the main geometry link from an object node to a geometry node is labelled
<quote><literal>geometry</literal></quote>). Link labels need not be unique; there can be several links sharing a
single label. There is also an integer field in the link definition, called target. This field is used to refer to some
part of the source or destination node.
</para>
<para>
These are the currently defined standard link labels, with their use:
</para>
<variablelist>
<varlistentry>
<term><literal>child</literal></term>
<listitem>
<para>
Links to a child object, that resides in the parent node's coordinate space. This is used to define hierarchical
transform graphs. The <literal>target</literal> should be set to the numerical ID of the <link linkend='geometry-bones'>bone</link>
to which the child is to be attached, or the special value ~0 (<literal>4,294,967,295</literal>) to indicate that the child
resides at the root of the parent's transform. It is valid to link to the same object from several different parent
objects. Transform hierarchies, however, cannot include circular links (a node cannot be its own child, at any level).
It is not guaranteed that a Verse host will not send out circular links, however. Clients need to be careful when
parsing the child link data.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>geometry</literal></term>
<listitem>
<para>
The object's geometry. The referenced node, which should really be a <link linkend='n-geometry'>geometry node</link>,
defines the object's geometry in the world. The geometry will be translated to the object's position, rotated,
scaled, and also given any defined material. This link type does not use the <literal>target</literal> field.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>light</literal></term>
<listitem>
<para>
This specifies how light is emitted by the object. The referenced node should be a <link linkend='n-geometry'>geometry node</link>,
and it defines the shape of the light source. Each polygon of the geometry is taken to be an area light. At the time of writing,
no known renderer supports light links.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>material</literal></term>
<listitem>
<para>
The object's material. The referenced node, which should really be a <link linkend='n-material'>material node</link>,
defines the material to apply to the surface of the object during rendering. There can be more than one such link,
for objects that need more than one material. They are then all given the label <literal>material</literal>, and
assigned unique <literal>target</literal> values. A face integer layer named <literal>material</literal> is then added
to the geometry, and populated with integers from the set of <literal>target</literal> values to pick one of the available
materials for each of the faces.
</para>
</listitem>
</varlistentry>
</variablelist>
<sidebar>
<title>API Link</title>
<para>Object links are set using the <xref linkend='verse_send_o_link_set'/> function.</para>
</sidebar>
</sect2>
<sect2 id='obj-transform'>
<title>Transform</title>
<para>
The object node holds a full 3D transform, with translation, rotation and scaling components that are used
to orient the object in the world. The first two of these properties are modeled not only with absolute values,
but also with time derivatives i.e. speed and acceleration. There is also support for expressing <emphasis>drag</emphasis>,
allowing basic friction to be modeled.
</para>
<para>
For each of these properties, the value is calculated by a 3D vector equation like the following:
<informalequation>
<alt>p(t) = p0 + v0*t + a*t^2 / 2 + drag</alt>
<graphic fileref='media/object/transform-eq.png'/>
</informalequation>
Here, the symbol <varname>p</varname> is used to represent the transform property of interest,
<varname>p0</varname> is the last known absolute position, <varname>v0</varname> the set initial speed,
<varname>a</varname> the acceleration, and <varname>drag</varname> a friction term. The position is
a function of the time, <varname>t</varname>, and thus it is possible to extrapolate into the future
from the last known values of the various parameters. The equation is the same for both position and
rotation of an object. Verse does not currently provide support for extrapolating the scale part of
an object's transform.
</para>
<para>
Hosts will maintain values of an object's transform using fairly high numerical precision, but it is
possible for a client to request a lower precision to conserve bandwidth.
</para>
<para>
The object node is the <emphasis>only</emphasis> node to provide a transform. Other types of data
that need to be associated to a point in space need to do so by being linked from an object node
at the required position.
</para>
<sidebar>
<title>API Links</title>
<para>Object transform is set using the
<xref linkend='verse_send_o_transform_pos_real32'/>,
<xref linkend='verse_send_o_transform_pos_real64'/>,
<xref linkend='verse_send_o_transform_rot_real32'/>,
<xref linkend='verse_send_o_transform_rot_real64'/>,
<xref linkend='verse_send_o_transform_rot_real32'/> and
<xref linkend='verse_send_o_transform_rot_real64'/>
functions.</para>
</sidebar>
</sect2>
<sect2 id='obj-light'>
<title>Light Sources</title>
<para>
Every object node has the ability to become a light source and light the world. A light source on an object
is simply defined by giving it three floating point values that determine how much light is emitted in each
of the primary colors red, green and blue. These values are interpreted so that a perpendicular surface at
a distance of 1.0 unit from a light source whose intensity (in any color) is 1.0 gets a light level of 1.0
(as <quote>seen</quote> by a material node's light fragment, that is).
</para>
<para>
By default, the light intensity is set to 0.0 for all three colors. This means that no light is emitted.
</para>
<para>
The light described here is a simple <quote>point light</quote>, with an equal amount of light being emitted
in each direction spherically, centered on the object's position. To create a more sophisticated light,
create a link to a <link linkend='n-geometry'>geometry node</link> and label it <quote><literal>light</literal></quote>.
This has the semantics of defining an area light, which only emits light from the faces of the geometry.
</para>
<sidebar>
<title>API Link</title>
<para>Object light is set using the <xref linkend='verse_send_o_light_set'/> function.</para>
</sidebar>
</sect2>
<sect2 id="o-methods">
<title>Methods</title>
<para>
The object node has the ability to hold custom entry points, known as <emphasis>methods</emphasis>. Methods are
like procedures in a programming language, they are a representation of the abstract concept of a named
action that takes a set of parameters and can be executed (called) at will. Methods are arranged in the node
into a number of named <emphasis>groups</emphasis>. They do not have return values, and are thus asynchronous
in nature.
</para>
<para>
Once created, method calls can be emitted by any client and any client is free to respond to a method being
called. This mechanism allows clients to create representations of their interfaces inside the world held on
the host.
</para>
<sidebar>
<title>API Links</title>
<para>Object methods are manipulated using the
<xref linkend='verse_send_o_method_group_create'/>, <xref linkend='verse_send_o_method_group_destroy'/>, <xref linkend='verse_send_o_method_group_subscribe'/>,
<xref linkend='verse_send_o_method_group_unsubscribe'/>, <xref linkend='verse_send_o_method_create'/>, <xref linkend='verse_send_o_method_destroy'/> and
<xref linkend='verse_send_o_method_call'/> functions.
</para>
</sidebar>
</sect2>
<sect2 id="o-animations">
<title>Animation</title>
<para>
Object nodes can be animated. Animation is expressed in the data model by creating <link linkend='geometry-bones'>
bones</link> in the object's <link linkend='n-geometry'>geometry node</link>, and also one or more
<link linkend='n-curve'>curve nodes</link>. Once the data is in place, you can instruct the object node
to <link linkend='o_anim_run'>run</link> the animation.
</para>
<sidebar>
<title>API Link</title>
<para>Object animations are controlled using the <xref linkend='verse_send_o_anim_run'/> function.</para>
</sidebar>
</sect2>
<sect2 id="o-hide">
<title>Hiding</title>
<para>
Object nodes can be selectively <emphasis>hidden</emphasis>. Hiding an object makes it invisible in the 3D
world. This is useful to cut down on latency and round-trips, by pre-defining content which can then be
rapidly made visible by just un-hiding the root object node.
</para>
<sidebar>
<title>API Link</title>
<para>Control an object's hidden status using the <xref linkend='verse_send_o_hide'/> function.</para>
</sidebar>
</sect2>
</sect1>
<sect1 id="n-geometry">
<title>The Geometry Node</title>
<para>
The Geometry node describes the shape of the geometry and any additional data that is assigned to the surface
of an object.
</para>
<para>
Verse has a single primitive when it comes to representing geometry: Catmull/Clark <emphasis>subdivision surfaces</emphasis>.
Subdivision allows a simple polygonal mesh to be refined, by letting the algorithm generate more polygons so
that the model finally becomes smooth. Rendering clients in Verse are free to apply subdivision to the meshes
stored, the <emphasis>intent</emphasis> is that they should in order to approach the ideal created by the
artist but they do not have to. Verse's subdivision surfaces support <emphasis>creases</emphasis> with which
one can control the degree of subdivision allowed for each vertex and edge.
</para>
<para>
The data held by a geometry node can be divided into vertex and polygon definitions. Vertex data describe positions
in a local 3D space, and polygons are created by referencing the vertices. All polygons have exactly three or four
corners (vertex references), there is no support for general N-sided polygons. There is always storage reserved for
four corners for a given polygon; if the three first references are valid and the fourth unused, the polygon is a
triangle. If also the fourth reference is to a valid vertex, it is a quadrillion. All polygons are two-sided, and
the front side references its vertices in a clockwise manner.
</para>
<sect2>
<title>Layers</title>
<para>
The geometry data is stored in <emphasis>layers</emphasis>, where each layer has a well-defined type. There are
layer types for storing data per vertex, per polygon corner, and per polygon face. <xref linkend="g-layer-table"/>
is a table that summarizes the available layer formats.
<table align="center" id="g-layer-table">
<title>Geometry Node Layer Types</title>
<tgroup cols="5" align="center">
<thead>
<row rowsep='1'>
<entry>Name</entry>
<entry>Enum Value</entry>
<entry>Value Type</entry>
<entry>Value Size, bits</entry>
<entry>Values per Index</entry>
</row>
</thead>
<tbody>
<row>
<entry align="right"><symbol>VN_G_LAYER_VERTEX_XYZ</symbol></entry><entry><literal>0</literal></entry>
<entry>Floating Point</entry>
<entry>64</entry>
<entry>3</entry>
</row>
<row>
<entry align="right"><symbol>VN_G_LAYER_VERTEX_UINT32</symbol></entry><entry><literal>1</literal></entry>
<entry>Unsigned Integer</entry>
<entry>32</entry>
<entry>1</entry>
</row>
<row>
<entry align="right"><symbol>VN_G_LAYER_VERTEX_REAL</symbol></entry><entry><literal>2</literal></entry>
<entry>Floating Point</entry>
<entry>64</entry>
<entry>1</entry>
</row>
<row>
<entry align="right"><symbol>VN_G_LAYER_POLYGON_CORNER_UINT32</symbol></entry><entry><literal>128</literal></entry>
<entry>Unsigned Integer</entry>
<entry>32</entry>
<entry>4</entry>
</row>
<row>
<entry align="right"><symbol>VN_G_LAYER_POLYGON_CORNER_REAL</symbol></entry><entry><literal>129</literal></entry>
<entry>Floating Point</entry>
<entry>64</entry>
<entry>4</entry>
</row>
<row>
<entry align="right"><symbol>VN_G_LAYER_POLYGON_FACE_UINT8</symbol></entry><entry><literal>130</literal></entry>
<entry>Unsigned Integer</entry>
<entry>8</entry>
<entry>1</entry>
</row>
<row>
<entry align="right"><symbol>VN_G_LAYER_POLYGON_FACE_UINT32</symbol></entry><entry><literal>131</literal></entry>
<entry>Unsigned Integer</entry>
<entry>32</entry>
<entry>1</entry>
</row>
<row>
<entry align="right"><symbol>VN_G_LAYER_POLYGON_FACE_REAL</symbol></entry><entry><literal>132</literal></entry>
<entry>Floating Point</entry>
<entry>64</entry>
<entry>1</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
The first layer, named <quote><literal>vertex</literal></quote> but sometimes referred to as the
<quote>base layer</quote>, is always of type <symbol>VN_G_LAYER_VERTEX_XYZ</symbol>. The second layer is always
used to define the polygons of the subdivision mesh, and must have type <symbol>VN_G_LAYER_POLYGON_CORNER_UINT32</symbol>
and be named <quote><literal>polygon</literal></quote>. These two layers are rigidly defined since a host must be
able to perform validity checking on them, and thus must be able to uniquely identify which layer is the base vertex
layer and which defines the polygons. They are always present in every geometry node.
</para>
<para>
Any other layers can have whatever type is required by the application. More layers than the two basic ones are
often required, for instance to create a texture-mapped surface layers are added to hold the U and V components of
the texture coordinates that define the mapping.
</para>
<para>
The REAL-typed layers can be read and written using either 32 or 64 bits by clients, but always occupy 64 bits in
the host memory. By allowing 32-bit subscriptions, clients that do not need the full precision can reduce their
bandwidth demands.
</para>
<para>
The way to think about layers, is as two <quote>stacks</quote>, one for vertices and one for polygons. The vertex
stack always includes a <quote>base layer</quote> of type <literal>VN_G_LAYER_VERTEX_XYZ</literal> (with the numerical
ID 0 and the name <quote><literal>vertex</literal></quote>, while the polygon stack always has a
<literal>VN_G_LAYER_POLYGON_CORNER_UINT32</literal> layer (with ID 1, and name <quote><literal>polygon</literal></quote>).
Other layers, when created, will end up in one of the stacks depending on whether it is a vertex or polygon layer.
The size of all layers in a stack is controlled by the size of the base layer of that stack, i.e. one of the
aforementioned always-present layers. As vertices and/or polygons are created, the defining data (the XYZ coordinates
or the vertex references, respectively) are placed in a slot in the base layer, and all other layers are grown to
provide a slot of data space of whatever type the layer has for the new addition. This slot is typically initialized
with a default value, to make it well-defined until explicitly set.
</para>
<sidebar>
<title>API Links</title>
<para>
Geometry layers are manipulated using the
<xref linkend='verse_send_g_layer_create'/>, <xref linkend='verse_send_g_layer_destroy'/>, <xref linkend='verse_send_g_layer_subscribe'/>,
<xref linkend='verse_send_g_layer_unsubscribe'/> commands. Layer data is manipulated using the
<xref linkend='verse_send_g_vertex_set_xyz_real32'/>,
<xref linkend='verse_send_g_vertex_delete_real32'/>,
<xref linkend='verse_send_g_vertex_set_xyz_real64'/>,
<xref linkend='verse_send_g_vertex_delete_real64'/>,
<xref linkend='verse_send_g_vertex_set_uint32'/>,
<xref linkend='verse_send_g_vertex_set_real32'/>,
<xref linkend='verse_send_g_vertex_set_real64'/>,
<xref linkend='verse_send_g_polygon_set_corner_uint32'/>,
<xref linkend='verse_send_g_polygon_delete'/>,
<xref linkend='verse_send_g_polygon_set_corner_real32'/>,
<xref linkend='verse_send_g_polygon_set_corner_real64'/>,
<xref linkend='verse_send_g_polygon_set_face_uint32'/>,
<xref linkend='verse_send_g_polygon_set_face_real32'/> and
<xref linkend='verse_send_g_polygon_set_face_real64'/> functions.
</para>
</sidebar>
</sect2>
<sect2>
<title>Creases</title>
<para>
Crease information is used to control the subdivision algorithm, by specifying how sharp a crease a vertex
or edge should have it is possible to avoid getting all <quote>smoothed out</quote> objects. There are two
possible approached supported for the two creases: either they can all be set to a single constant, or crease
information can be stored in a layer and referenced that way. If a layer is used, it must be of type
<symbol>VN_G_LAYER_VERTEX_UINT32</symbol> for vertex creases, and <symbol>VN_G_LAYER_POLYGON_CORNER_UINT32</symbol>
for edges. These values are given the following interpretation: zero represents a smooth surface (no crease),
while <literal>MAX_UINT32</literal> should give the maximum amount of crease to the vertex or edge.
</para>
<para>
Vertex crease information is, as mentioned, stored in a regular <symbol>VN_G_LAYER_VERTEX_UINT32</symbol> layer. This
layer has room for one integer per vertex slot, which is exactly what is needed.
</para>
<para>
For polygon edges, however, perhaps
a bit more explanations are in order. The crease data is stored in a layer of type <symbol>VN_G_LAYER_POLYGON_CORNER_UINT32</symbol>.
Now, such a layer is normally used to associate values with the <emphasis>corners</emphasis> of the polygons, not with
their edges. But, since the difference is small here, and since Verse doesn't provide a specialized per-edge layer,
the layer is simply re-used. The way to interpret edge creases is can be stated like this: <quote>each corner holds the crease data
for the edge that starts in that corner</quote>.
</para>
<sidebar>
<title>API Links</title>
<para>Geometry crease data is set using the <xref linkend='verse_send_g_crease_set_vertex'/> and
<xref linkend='verse_send_g_crease_set_edge'/> functions.</para>
</sidebar>
</sect2>
<sect2 id='geometry-bones'>
<title>Bones</title>
<para>
The geometry node can also store local transformations known as <emphasis>bones</emphasis>. Bones are fairly complex in
their definition, with each bone having a numerical ID, a parent ID, weight and reference layer pointers, a position,
a position curve pointer, a rotation and a rotation curve pointer.
</para>
<para>
The numerical ID simply identifies each bone in the node, as with layer IDs. Bones are typically numbered from zero and
upwards, and the sequence of IDs will typically be kept <quote>tight</quote>, with as few gaps of unused IDs as possible.
</para>
<para>
The weight layer pointer is used to reference a layer that defines the influence of that particular bone on each vertex of
the model. Such layers must be of type <symbol>VN_G_LAYER_VERTEX_UINT32</symbol> or <symbol>VN_G_LAYER_VERTEX_REAL</symbol>.
Integer layers are interpreted as being in the range 0..1 by dividing each value by 4,294,967,295. The value in each slot
says how much the bone's transform affects the corresponding vertex.
</para>
<para>
The reference layer pointer is used to optimize space usage for large skeletons. Since the weights system above needs
one layer of weights for each bone, it ends up using a lot of storage space. This is especially true since skeletons
are typically local; the number of vertices influenced by each bone is typically small, and does not increase with
the number of bones or the number of vertices. Having to <quote>pay</quote> for them anyway adds a lot of overhead,
which is something to be avoided. The method used is to add another layer of indirection to the bone system. By
specifying the name of a <symbol>VN_G_LAYER_VERTEX_UINT32</symbol> layer in the reference field of a bone, this secondary
system is triggered. The layer should contain bone IDs, and the effect is that the weight values for the bone carrying
the reference are applied to the bones being referenced, rather than directly to the vertices. In this case, the
weight value carried in the bone definition no longer applies to the bone itself, but to any number of bones, as defined
by the reference layer.
</para>
<para>
The parent link defines hierarchies of bones, i.e. <emphasis>skeletons</emphasis>. It can be set to a non-existing bone to
indicate that no parent exists, and the bone will then be at root level.
</para>
<para>
The position and rotation properties of a bone can also be animated by linking them to <link linkend='n-curve'>curve node curves</link>.
This is done by specifying the name of the desired curves directly in the bone definition. When the named curve is
animated using the <link linkend='n-object'>object node</link> command, the bone referencing that curve will update.
</para>
<para>
Regarding the overall bone structure, the following simple <quote>algorithm</quote> might be helpful to illustrate how
they work. To draw a bone structure:
<itemizedlist>
<listitem><para>Take all the bone positions, and mark them out in 3D space.</para></listitem>
<listitem><para>Draw a line from every point to its parent, if it has one.</para></listitem>
</itemizedlist>
</para>
<para>Now you have something that looks like a bone structure, with the important (and typical) property that
if you rotate any bone, all bones <quote>downstream</quote> of it will rotate, too.</para>
<sidebar>
<title>API Links</title>
<para>Bones are manipulated using the <xref linkend='verse_send_g_bone_create'/> and <xref linkend='verse_send_g_bone_destroy'/> functions.</para>
</sidebar>
</sect2>
<sect2>
<title>Examples</title>
<para>
Because the geometry node is fairly complex, yet used for a very central and important purpose, it is helpful to illustrate
how it is used with the help of some simple examples. Such examples almost have to be very simple, since listing in full
the geometry for any <quote>realistic</quote> scene would swamp this document and still be unreadable.
</para>
<example>
<title>Cube Geometry</title>
<para>
One of the simplest 3D objects that is still interesting is the cube. A minimal cube consists of eight vertices and six
polygons (if using quadrilaterals, which is always recommended with Verse). To be well-defined in Verse, a cube also needs
its crease information set in a way that makes all edges and corners sharp. So, to summarize:
<itemizedlist>
<listitem><para>Eight vertices</para></listitem>
<listitem><para>Six quadrilaterals</para></listitem>
<listitem><para>Sharp creasing</para></listitem>
</itemizedlist>
That's all there is to building a cube. Let's attack these one at a time:
</para>
<para>
The vertices are stored in the standard <quote>vertex</quote> layer, with ID zero. They can be listed in any order,
but using the first eight slots is natural and the most space-efficient way to do it. Here is a table showing one possible
solution:
<informaltable>
<tgroup cols='9'>
<thead>
<row>
<entry align='center'>Layer</entry>
<entry align='center'>0</entry>
<entry align='center'>1</entry>
<entry align='center'>2</entry>
<entry align='center'>3</entry>
<entry align='center'>4</entry>
<entry align='center'>5</entry>
<entry align='center'>6</entry>
<entry align='center'>7</entry>
</row>
</thead>
<tbody>
<row>
<entry>0 (<quote>vertex</quote>)</entry>
<entry>(-1,1,-1)</entry>
<entry>(1,1,-1)</entry>
<entry>(1,1,1)</entry>
<entry>(-1,1,1)</entry>
<entry>(-1,-1,1)</entry>
<entry>(1,-1,1)</entry>
<entry>(1,-1,-1)</entry>
<entry>(-1,-1,-1)</entry>
</row>
</tbody>
</tgroup>
</informaltable>
Here, the four first vertices outline the top quadrilateral, in clock-wise order when seen from the outside. The last four
do the same for the bottom quadrilateral. Note how each cell (<quote>slot</quote> in the layer) contains three values,
this is because the layer has type <symbol>VN_G_LAYER_XYZ</symbol>.
</para>
<para>
Next, we need to define the polygons. This is done in the layer with ID=1, called <symbol>polygon</symbol>. Here is
how it could look, in tabular form:
<informaltable>
<tgroup cols='7'>
<thead>
<row>
<entry align='center'>Layer</entry>
<entry align='center'>0</entry>
<entry align='center'>1</entry>
<entry align='center'>2</entry>
<entry align='center'>3</entry>
<entry align='center'>4</entry>
<entry align='center'>5</entry>
</row>
</thead>
<tbody>
<row>
<entry>1 (<quote>polygon</quote>)</entry>
<entry>0,1,2,3</entry>
<entry>4,5,6,7</entry>
<entry>3,2,5,4</entry>
<entry>2,1,6,5</entry>
<entry>1,0,7,6</entry>
<entry>0,3,4,7</entry>
</row>
</tbody>
</tgroup>
</informaltable>
Each slot contains four integer values, since the type of the polygon layer is <symbol>G_POLYGON_CORNER_UINT32</symbol>.
The first two polygons are the top and bottom surfaces, respectively. They are followed by the front, right, back
and left surfaces of the cube (when viewed along the negative Z-axis, with positive Y being upwards). Each quadrilateral
is defined in clock-wise order, with the top left vertex first (when applicable).
</para>
<para>
Note how the vertex and polygon layers have different sizes. Although they are part of the same physical layer ID space
inside the node, they really do form two separate <quote>stacks</quote> of layers. All vertex layers will have the same
size as the base (ID=0) vertex layer, while all polygon layers will have the same size as the base (ID=1) polygon layer.
</para>
<para>
To help visualize the above, here is a figure showing a simple cube, with vertices labeled according to the order used above:
<figure id="g-ex-cube" float='1' floatstyle='right' pgwide='0'>
<title>A Cube</title>
<mediaobject>
<imageobject>
<imagedata fileref="media/geometry/cube.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
The polygons are not marked in this figure, to reduce the clutter. The cube is viewed as described above, and the
XYZ axes use red, green and blue colors, respectively.
</para>
<para>
The final point we need to take care of is the creasing. To make sure the cube is not interpreted as a smooth
shape, we need to explicitly set the creasing to <quote>sharp</quote> for all vertices and edges. Crease information
can be stored in vertex and polygon layers, when finer control is needed, but there is also a way to set the default
to use for corners and edges, respectively. In this case, we need all the crease values to be the same, so we can use
the defaults and set them to <literal>0xffffffff</literal> which means <quote>maximum sharpness everywhere</quote>.
</para>
</example>
<!--
<example>
<title>Creased Geometry</title>
<para>
Nothing to see here.
</para>
</example>
-->
</sect2>
</sect1>
<sect1 id="n-material">
<title>The Material Node</title>
<para>
The material node is used to define surface properties of an object. It does this by defining a set of primitives,
known as <emphasis>fragments</emphasis>. Fragments are operators that process triplets of values, very suitable
for representing color but also re-usable for other properties of a surface. For colors, the standard interpretation
of a value is that 0 is black and 1 is white, but values can be outside this range (at both ends) without being
clipped or considered invalid.
</para>
<para>
To define e.g. color (the typical use for a material node), begin by creating an
output fragment, setting its type to <quote>color</quote>, and then create any further fragments as desired, linking
them to the root and each other to form the final material tree. The tree is then evaluated for every point of each
surface that uses that material, and the result used to control the final shading.
</para>
<sect2>
<title>Fragments</title>
<para>
<xref linkend="m-frags-enum"/> enumerates the defined fragment types, and also gives the numerical value associated
with each one. This number is used to identify a fragment type in the network protocol.
<table id="m-frags-enum">
<title>Material Node Fragment Type Enumeration</title>
<tgroup cols="3" align="center">
<thead><row><entry>Name</entry><entry>Enum Value</entry><entry>Purpose</entry></row></thead>
<tbody>
<row><entry><link linkend="m-f-color"><symbol>VN_M_FT_COLOR</symbol></link></entry>
<entry><literal>0</literal></entry>
<entry align="left">Emits a constant color.</entry></row>
<row><entry><link linkend="m-f-light"><symbol>VN_M_FT_LIGHT</symbol></link></entry>
<entry><literal>1</literal></entry>
<entry align="left">Represents light falling on a surface.</entry></row>
<row><entry><link linkend="m-f-reflection"><symbol>VN_M_FT_REFLECTION</symbol></link></entry>
<entry><literal>2</literal></entry>
<entry align="left">Represents reflected light.</entry>