home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-20 | 162.3 KB | 5,088 lines |
-
- 16
-
- Genesis Programming Specification
-
- Author: Steven Woodman
- Date: 10/7/95
- Revision: 5
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- (C) Silicon Dream Ltd. 1995
-
- TABLE OF CONTENTS
-
- GEOMETRY SPECIFICATION 5
- INTRODUCTION 5
- PROVIDING A NEW GEOMETRY ENGINE 6
- WRITING NEW TOOLS 6
- USING GEOMETRY FOR APPLICATIONS 7
- HOW THE GEOMETRY API WORKS 7
- VERTICIES 7
- PATCHES 8
- HOW DO YOU SPECIFY WHICH SIDE IS WHICH 8
- PENETRATING PATCHES 8
- NORMALS 9
- OBJECTS 9
- LIGHTS 10
- AMBIENT LIGHT 10
- COORDINATE SYSTEMS 10
- HOW DO WE DEFINE THE POSITION OF A COORDINATE SYSTEM11
- MATRICIES 11
- COORDINATE SYSTEM `HANDEDNESS' 11
- SURFACE TYPES 12
- TEXTURES 12
- TILED TEXTURES 13
- RECURSIVE TEXTURES 13
- BUMP MAPPING 13
- TEXTURE ORIENTATION AND SIZE 13
- NON-LINEAR TEXTURE PROJECTIONS 13
- SPECULAR HIGHLIGHTS 14
- TRANSPARENT SURFACES 14
- USING THE API 14
- GEOMETRY API REFERENCE 15
- USE OF C++ MATHS CLASSES 15
- GLOBAL FUNCTIONS 16
- COORDINATE SYSTEM FUNCTIONS 21
- OBJECT CONSTRUCTION FUNCTIONS 25
- LIGHTING FUNCTIONS 34
- LOADING AND SAVING 36
- STRUCTURES AND TYPES 38
- TOOL INTERFACE 46
- INTRODUCTION 46
- WRITING CUSTOM TOOLS 47
- THE TOOL OBJECT 47
- THE TOOL'S CONFIGURATION DIALOG BOX 47
- HOW TO TELL THE EDITOR ABOUT YOUR TOOL 48
- OVERRIDING TOOL FUNCTIONS 48
- CALLING SEQUENCE 48
- MODIFYING AND UNDOING 49
- DRAWING INTO THE VIEW 49
- DRAWING RETURN CODES 49
- REDRAW_ALL 49
- REDRAW_NONE 50
- REDRAW_OBJECT_WIRE 50
- REDRAW_TOOL 50
- REDRAW_NOTOOL 50
- REDRAW_REFRESH 50
- GETTING 2D SCREEN COORDINATES 50
- DRAGGING WITH THE MOUSE 51
- XOR'ING IN MULTIPLE VIEWS 51
- DRAWSOFAR PARAMETERS 52
- GENERAL GUIDELINES 52
- HELP ON USING TOOLS 52
- DISPLAYING TEXT STRINGS 52
- COORDINATE SYSTEM TYPES 52
- A NOTE FOR C USERS 53
- OVERRIDABLES 54
- SUPPORT 58
- QUICK START TO WRITING TOOLS 69
- MATHS LIBRARY 71
- FOR C USERS 71
- FOR C++ USERS 71
- VECTORS 72
- LONG VECTORS 73
- POLAR VECTORS 73
- MATRICIES 74
- DEBUG LIBRARY 75
- INSTANCES OF DEBUG LIBRARY 76
- WRITING A GEOMETRY ENGINE 77
- ERRORS 77
- HANDLES 77
- UNSUPPORTED FEATURES 78
- HELPER LIBRARY 78
- API'S 78
- GEOMETRY SPECIFICATION
-
- Introduction
-
- This document describes the Geometry API. It assumes an
- understanding of programming in C++ and a basic knowledge
- of programming in Windows. Knowledge of mathmatics is not
- a prerequisite although an understanding of vectors and
- matricies is helpful.
-
- Figure 1 shows the various component parts of the Genesis
- package and how they relate to one another.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Figure 1. Components of Genesis
-
- Geometry is the part of Genesis that actually stores the
- data structures representing the 3D models and performs
- all the difficult 3D rendering. The editor makes various
- calls to the Geometry API as the user performs various
- actions on the program. For instance when the user
- presses the `Pos' button on the control bar the editor
- makes a call to the SetCamera routine in order to
- position the camera ready for rendering. When the user
- selects the `Render' menu item, a call to Render is made.
- A user will never need to know these details, however
- there are three scenerios in which a programmer might
- want to understand how the API works.
-
- · Providing a new Geometry engine
- · Writing new tools for the editor
- · Using Geometry for applications
-
- Whichever scnerio you are interested in the maths and
- debug libraries supplied in this package will prove
- invalueable programming aids (See the `Maths Library' and
- `Debug Library' sections).
-
-
-
- Providing a new Geometry engine
-
- The default Geometry engine is a single DLL which
- provides software for 3D graphics processing. It doesn't
- support accelerated hardware because at the time of
- writing we couldn't possibly anticipate what manner of 3D
- acceleration hardware might become available in the
- future. When third parties release their new 3D
- processing systems, wether hardware or software based,
- Genesis can support them simply by writing a DLL to
- interface the Geometry API to the new hardware/software.
- Imagine for example that the XYZ computer company came
- out with a board and a software interface that gave PC's
- the ability to render at over a million polygons a
- second, then with a few days work Genesis with all its
- powerfull editing tools could be rendering much faster
- and completely transparently from the users viewpoint.
-
- To create a new Geometry engine you will create a DLL
- implementing the Geometry API but which maps those
- functions onto the software functions provided by the
- third party 3D comapny. A set of routines is supplied in
- this package to make this job easier (See the `Geometry
- Helper Library' section).
-
- Writing new tools
-
- Genesis is very powerfull in the respect that if a
- function is needed which isn't available, with a little
- programming knowledge you can create your own extensions
- thereby tailoring Genesis to your own particular set of
- problems. For instance, an architect might spend most of
- his time creating doors, all of which are different but
- all share basic characterisitics. By writing a door
- creation tool, he can position the cursor where he wants
- the door, press a button in the tool box representing his
- custom tool, enter a few basic parameters into a dialog
- box, and hey presto, a door appears. In this way users
- can build their own libraries of tools all of which are
- seemlessly integrated into the program. In this way
- Genesis can be considered as little more than a shell
- designed to support a vast variety of `plug in' tools to
- cover every concievable problem in 3D design.
-
- To create a new tool you will create a DLL implementing a
- C++ class derived from a class that we supply (See the
- `Writing Tools' section). Dont worry if you are not
- familiar with C++ as we provide a C++ template source
- file. All you need to do is to fill in the relevent
- functions using C. You will use the Geometry API plus
- functions in the base class to implement the
- functionality of the tool. Minimal knowledge of
- programming in Windows is required.
-
- Some of the more general tools we thought might be
- usefull are listed below. Basically anything which
- manipulates 3D models can be implemented as a tool.
- However there are in fact an unlimited number considering
- the huge range of applications Genesis might be applied
- to:
-
- 1. Primitive creation types (Creates primitive objects)
- · Patches
- · Spheres/Semi spheres
- · Cylinders
- · Boxes
- · Cones
- · Torus's
- · Ellipsoids/General curved area creators
- 2. Tradional types (Often found on more conventional
- modellers)
- · Lathe (Spins a 2D outline into a 3D shape)
- · Extrude (Expands a 2D outline to give it 3D depth)
- · Copy (Makes a copy of an object)
- · Text input window (Calls other tools when you type
- in commands like `sphere rad=10;')
- 3. Savers/Loaders (for various file formats)
- · 3DS
- · DXF
- · WAD (Doom game file format)
- 4. CSG tools (Enables new objects to be created by
- combining existing ones)
- · Union operator (joins two objects as one object;
- a=b|c)
- · Intersection operator (creates one object from the
- overlapping volume of two others; a=b&c)
- · Subtraction operator (subtracts one object from
- another; a=b-c)
- · Exclusive OR operator (creates an object as the
- volume of two other objects excluding any intersection;
- a=b^c)
- 5. Imaginitive ideas
- · Fractal landscape generator
- · `Physical law' animation tools
-
- Using Geometry for applications
-
- The Geometry engine can be used via its API to construct
- new applications totally separate from the Genesis
- editor. For instance; Flight simulators, medical imaging
- applications, oil field data visualisation, 3D games to
- mention but a few. The advantages of using the Geometry
- API are twofold. Firstly all the difficult 3D stuff is
- already taken care of as well as a lot of other usefull
- bits such as routines to manipulate 3D vectors and
- matricies etc. (See `Maths Library' section). Secondly,
- any new hardware appearing for which a geometry engine is
- written (see above) will automatically work with the new
- application. So your flight simulator might not look too
- quick on a 386 PC but when XYZ's new 3D processor board
- hits the market suddenly without any additional
- programming effort your 386 looks like a million dollar
- professional simulator.
-
- To write a new application the Geometry DLL is used as a
- stand alone DLL, just like any other, which is called
- from your application according to the Geometry API.
-
- How the Geometry API works
-
- The Geometry design is a heirarchical one. Objects such
- as verticies, patches and normals belong to objects.
- Objects belong to coordinate systems as do lights.
- Coordinate systems belong to other coordinates system.
- Coordinate system along with all their associated objects
- can be rendered. The following sections decribe the
- terminology further.
-
-
-
-
-
-
-
-
-
-
-
-
- Figure 2. Construction of a cube
-
- Verticies
-
- A vertex is a point in 3D space described by an x, y and
- a z value. A cube has 6 verticies or corners, 12 edges,
- and 8 faces.
-
- Patches
-
- A patch is a polygon or face defined by 3 or more
- verticies, such as the 8 faces of the cube. You build up
- 3D models by connecting patches together exactly like a
- patchwork quilt. A patch has a surface type indicator
- defining its colour, texture and reflection
- characteristics. Patches are always flat but can be made
- to appear curved by associating normals with each of its
- verticies (see below). Because they are always flat care
- should be taken when creating patches of more than 4
- verticies that all the verticies lie on a plane otherwise
- Geometry will politely inform you of your error.
-
- Patches are one sided entities meaning they are intended
- to be viewed only from one side. An attempt to view it
- from the other side will in fact make it invisible. This
- might sound strange but is actually quite logical. For
- instance as you look around your cube you are always
- seeing the individual patches from the same side, to view
- them from the other side you will need to go inside the
- cube. If you did this you would actually see straight
- through to the outside because the patches would be
- invisible. What you need to do is design the inside of
- the cube to prevent you seeing out, ie. you need 8 more
- patches inside facing the other way. The reason for this
- is that it makes rendering quite a bit faster. In cases
- where you dont want to go inside the cube you only need 8
- single sided patches which render much quicker than 8
- double sided ones. This is a technique used by almost all
- real time rendering systems.
-
- How do you specify which side is which
-
- Geometry adopts the convention that all patches must have
- their verticies ordered clockwise when viewed from the
- correct side. It is the ordering of the verticies which
- defines which side is the solid looking side. When
- creating patches you must think about this, if you order
- them wrongly your object will be visible from the inside,
- and probably completely invisible from outside.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Figure 3. Penetrating patches
-
- Penetrating patches
-
- Care should be taken when constructing objects that one
- patch should not penetrate another as not all Geometry
- engines support penetrating surfaces, and in fact the
- default Geometry engine doesn't. If you want an object to
- look like it has been pierced with another the patches
- should be designed to give this effect without actually
- penetrating. The editor's CSG union tool will allow users
- to do this.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Figure 4. Normals
-
- Normals
-
- A normal is a direction specified in 3D by an x, y and z
- value, rather like a vertex. Normals are used to make
- objects appear curved. By associating a normal with each
- corner of our cube, we are telling the renderer that when
- it is working out the light shading on those points, to
- assume that the gradient of the surface at that point is
- such the normal's direction sticks out at 90 degrees to
- it. In fact this isn't so, as we might have 3 or more
- patches converging at a vertex (as in the cube example),
- but thanks to the normal the shading is generated as if
- it were a single face at that point. If we tell Geometry
- that an object we are constructing is to appear curved
- the `autosmooth' feature can generate the normal
- information automatically for us. There are some instance
- however when we would like to create them explicitly.
-
-
-
-
-
-
-
-
-
-
-
-
- Figure 5. Missing or wrongly ordered patches
-
- Objects
-
- An object is a 3D model constructed out of patches. Since
- patches are single sided it should be fully enclosed by
- patches so that we cannot see the inside of any patch
- from any angle. As mentioned above you would in fact not
- see it at all giving the appearance of a hole in your
- object. Another way to think about it is that each edge
- of every patch should have another patch connected to it.
- Geometry will not complain if you attempt to render an
- incomplete object but the results can look confusing seen
- from some angles.
-
- The editor's `Enclosed' tool will highlight any
- unconnected edges.
-
-
-
- Lights
-
- As well as a 3D position, lights can have characteristics
- such as intensity, colour and direction although the
- default Geometry engine actually only takes notice of the
- position and intensity.
-
- Ambient Light
-
- Real life lighting very rarely leaves you completly in
- the dark. This is because there is always light coming
- from somewhere, eg. sunlight, moonlight, a far off screet
- lamp etc. In 3D modeller environments we find it
- difficult to account for all these things, so to ensure
- that at least a little bit of light falls even on
- surfaces where no light sources can reach, we use ambient
- light. The ambient light setting is simply an intensity
- value added to those generated by the light sources when
- rendering a scene.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Figure 6. A coordinate system heirarchy
-
- Coordinate systems
-
- Every 3D coordinate you specify for lights, verticies,
- normals and therefore patches and objects is relative to
- an origin, ie. point 0, 0, 0. The position of the origin
- relative to whatever other stuff might get rendered is
- defined by the coordinate system. A coordinate system and
- all its associated objects and lights etc. can be moved
- quickly and easily relative to everything else simply by
- moving the coordinate system. The coordinate system moves
- and everything in it moves. As an example, imagine a huge
- landscape. This would be defined in the top level
- coordinate system by loads of patches. In this landscape
- there is a river, and on the river a large boat
- containing lots of people. We want to animate this boat
- moving down the river. As the boat moves twisting and
- turning as it goes, so do all the people.
- When creating the animation we have to define the
- position of the boat at each frame, but we shouldn't also
- have to define the position of every individual person.
- We do this by creating a coordinate system as a child of
- the landscape's coordinate system. and make the boat and
- everying in it belong it. We then only have to move the
- coordinate system.
-
- Coordinate systems are also usefull even if we're not
- making animations as it provides us with a new origin and
- axis to work with when designing objects at awkward
- angles to the x, y and z axis's in the parent coordinate
- system.
-
-
-
- How do we define the position of a coordinate system
-
- This brings us to the most difficult mathmatical concept
- used in Geometry. The straight answer is; a 4x4 matrix.
- Some of you will know what I mean, some will require a
- further explanation.
-
-
-
-
-
-
-
-
-
-
- Figure 7. Matricies
-
- Matricies
-
- A matrix is a set of numbers laid out in a rectangle.
- Matricies can have any number of columns by any number of
- rows. The matricies we're concerned with in Geometry are
- all 4x4. When defining the position of a new coordinate
- system its not just a matter of specifying the 3D
- coordinates of a new origin because we also have to
- define the `orientation' of the new axis. The
- `orientation' means the angle of the new x, y and z axis
- relative to the parent coordinate system. The x axis
- isn't neccessarily parallel to the parents x axis it
- could be rotated a bit in the y axis and bit in the z
- axis and even enlarged or shrunk relative to the parent.
- Matricies we're designed to represent this type of
- information. Thankfully the maths library supplies a C++
- class and C functions that make working with matricies
- easy.
-
-
-
-
-
- Figure 8. Coordinate system `handedness'
-
- Coordinate system `handedness'
-
- Two types of coordinate system can be defined; left and
- right handed. It is neccessary to tell Geometry which
- type you have defined otherwise the clockwise ordering of
- verticies in a patch is meaningless. To find out which
- type you want, position your right hand so that you index
- finger and second finger are at right angles to each
- other and your thumb is pointing up. In a right handed
- coordinate system if the x axis has the direction of the
- index finger and the y the direction of the second finger
- then the z axis will have the direction of the thumb. The
- same applies to a left handed coordinate system if you
- use your left hand.
-
- Coordinate systems and all their associated objects can
- be moved within the coordinate system heirarchy. For
- instance, coordinate system A has a child; B, and B has a
- child; C. C can then be moved so that it becomes a child
- of A, meaning it is now a sibling of B. This can only be
- done only if the coordinate systems are of the same type
- otherwise the ordering of the verticies in its patches
- effectively get reversed. If you want A to be left handed
- and B to be righthanded all you need do is construct a
- matrix which reverses one of the axis, either x, y or z.
- Functions in the maths library make this easy.
-
- The HCSYS_TOP coordinate system is left handed. Unless
- you specifically construct a matrix which reverses one of
- the axis's of a top level coordinate system, it too will
- be left handed.
-
- When constructing your data you must bear in mind the
- coordinate system it belongs too. If for example you
- designed a model of the earth for a right handed
- coordinate system but displayed it in a left handed
- system then America would end up on the right and Europe
- and Asia on the left. No amount of rotating or moving the
- object would correct this problem. If something like this
- happens to you then look closely at which type of
- coordinate system you should be using for you data.
-
- Surface Types
-
- All patches have a surface type. A surface type not only
- describes the colour of the surface but its texture and
- how how highlights appear on the surface. The surface
- type does not say wether a patch is curved. This is as
- attribute of the patch itself.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Figure 9. Tiled textures
-
- Textures
-
- Texturing is a way of making your object look more
- detailed and realistic by projecting an image onto it.
- For instance, if you have a wall you can use a brick
- texture or a wood grain. The way to image a texture is to
- think of an invisible image positioned somewhere in your
- scene. Although you cannot see the image directly, the
- plane of the image is projected infinitely through the
- scene in both directions and the image `rubs off' on any
- patch which uses the surface type of this texture. Think
- of it a bit like a film projector that shines on anything
- placed in fron of it. The only difference is the film
- projector image gets bigger the further in front the
- object or screen is moved. Also with a film projector
- everything in front gets projected onto, not just
- selected patches.
-
-
- Tiled textures
-
- If you have a huge wall you want to texture and you have
- a small image of part of a brick wall to use as the
- texture you have a problem. To make the bitmap fit the
- wall you have to scale it up. This is quite easily done
- but now you have a huge wall made of a few huge bricks!
- What you need to do is make the texture `tiled'. Genesis
- can place multiple copies of the image alongside each
- other and above and below, like tiling an infinitely
- large bathroon wall, so that every point in space will be
- within `range' of the texture.
-
- If you want to use tiled textures you should ensure that
- the image you use is `tileable', in other words, if you
- place multiple copies alongside each other will you see
- the joins. If you can your wall will look like you've
- simly pasted up posters of bricks rather than used the
- real thing.
-
- If you choose not to tile your texture and you have a
- patch using the surface type which is not in range of the
- texture, then this patch is coloured using the basic
- surface colour of the surface type.
-
-
- Recursive textures
-
- A recursive texture is where each pixel value in your
- image refers not to a colour in the palette of the
- image, but rather to another Genesis surface type. This
- means you could define a surface type which appears to
- have brick on top and through the holes in the brick you
- can see wooden slats. You can even define pixel values to
- represent real holes in your object that show through to
- objects behind. The default Genesis Geometry engine does
- not support recursive textures.
-
-
- Bump mapping
-
- With bump mapping the pixel values in the image refer to
- the height of a bump which is to appear at that point on
- any patch its projected onto. Obviously no real physical
- bump appears on the object, but the shading at the point
- is modified to make the surface appear irregular at that
- point. The effect is extremely convincing as long as you
- dont get too close to the object. The default Geometry
- engine does not support bump mapping.
-
-
- Texture orientation and size
-
- Having discussed how textures work, we still haven't
- addressed the question of how we specify the orientation
- of the texture. Its quite simple really, as before we use
- a 4x4 matrix to define the orientation relative to the
- origin of a coordinate system. If you use an identity
- matrix (this is really a null matrix, one that does
- nothing) then your texture will be aligned with the x and
- y axis of the coordinate system and will project through
- the z. The size will be such that if your image is 100
- pixels wide by 80 high then it will extend from the
- origin to x=100, and y=80. Any other matrix can be used
- to position, rotate, and scale the image away from the
- origin.
-
-
- Non-linear texture projections
-
- Texture matricies can also be used to define non-linear
- projections. For instance, suppose you want to project
- bricks onto a sphere. With a normal linear projection as
- described above, your bricks will distort as they go
- around the sides of the sphere, like putting a football
- in front of a film projector. The way around this is to
- use a spherical mapping. In other words create a matrix
- to map points on a sphere onto a flat image. Cylindrical,
- conic and even toriodal projections might come in handy
- for other types of objects.
-
-
- Specular highlights
-
- Specular reflections are what you see when you take a
- shiny surface such as a metal tray, and angle it towards
- a light. You will often see brightly lit areas where the
- light bounces off the object towards your eye. The exact
- shape, size and brightness of these highlights depends on
- what the surface is made of. Since the default Geometry
- engine (or any using Gouraud as opposed to Phong shading)
- performs its lighting calculations at each vertex only,
- the more verticies you have the more accurately the
- lighting will mimic the surface type. Even if you have a
- flat square surface, to get the most visually accurate
- highlights the surface should be made of lots of small
- flat patches rather than one large one.
-
- In technical terms the specular reflection
- characteristics relates the amount of light reflected to
- the angle of incidence (the angle made by the light
- striking a point on the surface and the normal of that
- point). It is not neccessary to understand this.
-
-
- Transparent surfaces
-
- As well as all the above a surface can have associated
- with it a transmissive value, in other words its degree
- of transparency. A value of 1.0 would make the surface
- completely invisibile whereas 0 would be completely
- solid. The default Geometry engine does not support
- transmissive surfaces.
-
-
- Using the API
-
- Custom tool writers have an easy life as the editor does
- most things for you. Most of the time you will be using
- only a handfull of calls specifically to do with create
- verticies and patches etc. However a full understanding
- of how the API works is useful for when you want to
- expand your tool writing to cover more advanced topics.
- See the separate section `Writing custom tools'.
-
- Application writers using the API will need a full
- understanding of the API, as will those developing new
- Geometry engines.
-
- The first call to the Geometry DLL must be Initialise,
- and it can only be called once. The last call must be
- Terminate. No furthers calls can be made after a
- Terminate. After Initialise the next likely call that a
- standalone application is likely to make will probably be
- AddCoorSystem, since every object must belong to a
- coordinate system. If we're writing a tool this would
- have been done for us by the editor. As explained
- coordinate systems are built up in heirarchies. A top
- level coordinate system has HCSYS_TOP (a constant defined
- in `geometry.h') as its parent. Other coordinate systems
- defined underneath these are known as its children.
-
- After creating some patches you can render an image by
- placing the camera into one of these coordinate systems
- using the SetCamera call and then call Render. Again,
- custom tools writers wont need to worry about this. When
- a coordinate system is rendered everything in it, its
- child coordinate systems and everything in them, and its
- parent coordinate systems and everything in them are
- rendered. The only thing which isn't rendered are other
- top level coordinate systems. So each top level
- coordinate system can be considered a completely separate
- scene, much like separate documents in a word processor.
- The one that gets rendered is the one we SetCamera into.
-
- The image gets rendered into a windows Device Independent
- Bitamp (DIB) which is created on the Render call. The
- application can maintain as many DIBs or rendered images
- as it likes. Notice how the editor does this. It has at
- least one for each top level coordinate system. When the
- window's window needs to be painted (on the WM_PAINT
- message) with the bitmap, we can call another Geometry
- function, UpdateImage, to transfer the image to the
- screen.
-
- Geometry API Reference
-
- To use the Geometry API either from your own application
- or from a custom tool, you must include the `geometry.h'
- C++ include file and link to `geometry.lib'. All Geometry
- functions return a GeomErr value. Usually this will be
- GERR_OK (value 0) if the function succeeded otherwise
- will either represent an internal processing error such
- as `out of memory', or information such as `vertex not
- visible'. The calling code should check these return
- codes and display any serious internal errors to the user
- in a message box. The GetErrorText function can be used
- to get a complete text description of the error and
- whereabouts internally it occurred. Internal processing
- errors more often than not indicate a bug in the calling
- code, such as trying to create a patch out of just two
- verticies. When your code is debugged they should go
- away. If serious errors persist when they shouldn't do we
- would be gratefull if you could fill in a bug report form
- and send it to us, in order for us to correct bugs in
- subsequent releases. We will also endevour to send you an
- update as soon as the bug is fixed.
-
- Many functions accept handles to objects. It is the
- responsibility of the tool/application writers to ensure
- that these handles are valid, because although there is a
- `handle not valid' error, you cannot rely on the Geometry
- engine being able to check its validity.
-
-
- Use of C++ maths classes
-
- Often a Geometry function will require a C++ class
- defined in the maths library as a parameter, a Vec for
- instance would be passed to AddVertex. A pure C interface
- will soon be made available where instead you will pass a
- pointer to a maths `Vector' structure.
-
-
-
- Global functions
-
-
- GeomErr Initialise (void);
- Comments
-
- Called to initilise Geometry. Must be called first.
-
- Return codes
-
- GERR_OUT_OF_MEMORY
-
-
-
-
- GeomErr Terminate (void);
-
- Comments
-
- Called to terminate Geometry and release all its
- allocated resource. Must be called last.
-
- Return codes
-
-
-
-
- GeomErr DefSurfType (SurfType *pst, HanSurf *phsur);
-
- pst Pointer to a SurfType structure.
-
- phsur Returns a handle to a surface type.
-
- Comments
-
- Creates a surface type definition.
-
- Return codes
-
- GERR_OUT_OF_MEMORY
- GERR_TOO_MANY_SURFACE_TYPES
- GERR_BITMAP_FILE_NOT_FOUND
- GERR_NOT_A_BMP_FILE
-
-
-
-
- GeomErr DelSurfType (HanSurf hsur);
-
- hsur Handle to surface type to delete.
-
- Comments
-
- Deletes a surface type as long as no patches are using
- it.
-
- Return codes
-
- GERR_INVALID_HANDLE
- GERR_IN_USE
-
-
-
-
- GeomErr QrySurfType (HanSurf hsur,
- SurfType *pst,
- BITMAPINFOHEADER *pbmih,
- ulong *pulNumPats);
-
- hsur Handle to surface type to query.
-
- pst SurfType structure to receive the
- information about the surface.
-
- pbmih Pointer to windows BITMAPINFOHEADER
- structure which will receive details of
- the texture bitmap if appropriate.
-
- pulNumPats Number of patches using this surface.
-
- Comments
-
- Queries information about a given surface type.
-
- Return codes
-
- GERR_INVALID_HANDLE
-
-
-
-
- GeomErr ModSurfType (HanSurf hsur,
- SurfType *pst);
-
- hsur Handle to surface type to modify.
-
- pst SurfType structure used to set surface
- characteristics.
-
- Comments
-
- Modifys a surface type.
-
- Return codes
-
- GERR_INVALID_HANDLE
-
-
-
-
- GeomErr SetCamera (HanCoorSys hcsys,
- Vec &vecPos,
- Vec &vecDir,
- Vec &vecUp);
-
- hcsys Coordinate system to set the camera
- in.
-
- vecPos The position of the camera within
- this coordinate system.
-
- vecDir The direction in which the camera is
- facing. It takes the form of an absolute
- 3D position within the coordinate system.
-
- vecUp The direction which will be `up' in the
- rendered image. It takes the form of an
- absolute 3D position within the coordinate
- system.
-
- usResX The x resolution of the associated image.
-
- usResY The y resolution of the associated image.
-
- Comments
-
- Sets the camera at a position within the coordinate
- system. The camera can only be in one coordinate system
- object at a time. Setting it in another coordinate system
- will remove it from this one. If you need to use
- Get3DLine and Get3DPoint to get 2D screen coordinates of
- 3D points, you must SetCamera first into the appropriate
- coordinate system. You must also supply the size of the
- image associated with the coordinate system otherwise the
- coordinates returned by these functions will be invalid.
- These values can be ignored if you do not intend to use
- Get3DPoint or Get3DLine.
-
- Return codes
-
-
-
-
- GeomErr Render (BITMAPINFO *huge *ppbmi,
- ushort usResX,
- ushort usResY);
-
- ppbmi Pointer to a pointer to a windows
- DIB.
-
- usResX Requested x resolution of the bitmap. This
- value must be a multiple of 4 pixels.
-
- usResY Requested y resolution of the bitmap.
-
- Comments
-
- Before rendering the *ppbmi value should be set to NULL.
- This will cause Geometry to create a DIB of the requested
- size and return a pointer to it in *ppbmi. On subsequent
- renders if we pass in the same value of *ppbmi Geometry
- will reusue the bitmap. If the requested size changes or
- circumstances within Geometry change, for instance,
- implementation specific options allow the default
- Geometry engine to switch between 8 and 24 bit output,
- then the old bitmap is freed and a new bitmap created.
- Each time we pass a value of zero, we force a new bitmap
- to be created. To transfer the image to a device context
- such as the screen, call the UpdateImage function.
-
- The render bitmaps created by this call are removed by
- Geometry when Terminate is called, however since these
- bitmaps can be very large it is advisable to remove them
- if no longer required by calling DeleteRenBitmap.
-
- The default Geometry engine is very sensitive about the
- `handedness' of the coordinate systems being rendered.
- When creating a coordinate system it has no way of
- telling if the coordinate system you've created is really
- of the type you've told it. Since Geometry's renderer
- relies on this information to optimise its performance it
- is likely to cause a trap if say, you created a left hand
- coordinate system but told Geometry it is right handed.
- If you experience traps when rendering check your
- coordinate systems very carefully.
-
- Return codes
-
- GERR_IMAGE_SIZE_NOT_MULT_4
- GERR_BITMAP_TOO_SMALL
- GERR_TOO_MANY_BITMAPS
-
-
-
-
- GeomErr DeleteRenBitmap (BITMAPINFO huge *pbmi);
-
- pbmi A pointer the the BITMAPINFO structure
- created by the Render call.
-
- Comments
-
- Tells Geometry to remove a bitmap created by the Render
- call.
-
- Return codes
-
-
-
-
- GeomErr UpdateImage (ulong ulHDC,
- BITMAPINFO huge *pbmi,
- ushort usX,
- ushort usY);
-
- ulHDC A ulong value holding the HDC to paint the
- rendered image to.
-
- pbmi Pointer to the rendered DIB (created by
- calling Render).
-
- usX Horizontal position in the DC of where the
- image will appear.
-
- usY Vertical position in the DC of where the
- image will appear.
-
- Comments
-
- Transfers a rendered DIB to a device context. This call
- could result in realising the colour palette.
-
- Return codes
-
-
-
-
- GeomErr GetErrorText (GeomErr gerr,
- char *szBuff,
- ushort usBuffSize);
-
- gerr The GeomErr value returned from a Geometry
- call.
-
- szBuff Pointer to a character buffer to hold
- the error string.
-
- usBuffSize Set to indicate the size of szBuff.
-
- Comments
-
- Can be called to get Geometry to return an error string
- describing the error which occurred. The string will
- contain the name of the module and the line number on
- which the error occurred.
-
- Return codes
-
- GERR_BUFFER_TOO_SMALL
-
-
-
- Coordinate system functions
-
-
- GeomErr AddCoorSys (HanCoorSys hcsysParent,
- Mat &matToParent,
- Mat &matFromParent,
- ushort usType,
- HanCoorSys *phcsys);
-
- hcsysParent Handle to parent coordinate system
-
- matToParent Matrix describing the transformation from
- child to parent. In other words this
- matrix transforms a point in the child
- coordinate system to its corresponding
- position relative to the parent coordinate
- system.
-
- matFromParent The inverse or opposite matrix to
- matToParent. NB. The maths library can
- easily generate the inverse of a matrix by
- preeceeding it with a minus sign (eg. -
- mat).
-
- usType This value indicates wether the
- coordinate system being defined is right
- handed or left handed. It should be either
- CT_RIGHTHAND or CT_LEFTHAND.
-
- phcsys Returns a handle to a new coordinate
- system.
-
- Comments
-
- Creates a coordinate system as a child of the parent. Use
- HCSYS_TOP to create a top level coordinate system. If the
- matricies do not specifically reverse one of the
- coordinate system axis's then this coordinate system will
- be the same `handedness' as its parent. It is important
- that the usType parameter correctly identifies the type
- of the coordinate system.
-
- The matricies can define scaling and shearing as well as
- basic orientation. However a matrix is not acceptable if
- it alters the basic topology of the geometry. For
- instance, a mirror type matrix will alter
- the `type' of the coordinate system (only use this if you
- also specify the correct `type' parameter). A matrix that
- warps space into say, a cone or cylindrical shape is
- completely unacceptable. A matrix consisting entirely of
- zeros, would be the Genesis equivalent of a black hole.
- In space physical laws break down inside black holes.
- Genesis will also break down if you use a matrix like
- this!
-
- Return codes
-
- GERR_OUT_OF_MEMORY
-
-
-
-
- GeomErr DelCoorSys (HanCoorSys hcsys);
-
- hcsys Coordinate system to delete.
-
- Comments
-
- Deletes a coordinate system and any objects belonging to
- that system including child coordinate systems and their
- objects.
-
- Return codes
-
-
-
-
- GeomErr QryCoorSys (HanCoorSys hcsys, CoorSysInfo *pcsi);
-
- hcsys Coordinate system to query.
-
- pcsi Pointer to a CoorSysInfo structure to
- receive the information.
-
- Comments
-
- Returns information about a coordinate system and all its
- associated objects enabling us to navigate our way around
- the coordinate system heirarchy.
-
- If you query HCSYS_TOP, the only relevent field is
- usType, which will be lefthand.
-
- If you query any top level coordinate systems (ie. direct
- children of HCSYS_TOP) you cannot rely on the matrix
- fields of the CoorSysInfo structure being what you
- originally set them to. The reason for this apparent
- oddity is that under the covers these matricies define
- the position of the scene relative to the camera, so as
- the camera 'moves', so these matricies change.
-
- Return codes
-
-
-
-
- GeomErr ModCoorSys (HanCoorSys hcsys,
- Mat &matToParent,
- Mat &matFromParent,
- ushort usTransType);
-
- hcsys Coordinate system to query.
-
- matToParent Matrix to define the new position of the
- coordinate system relative to its parent.
- It can be used either to replace the old
- matrix or to modify it.
-
- matFromParent Inverse of matToParent.
-
- usTransType Indication of how the new matrix is to
- modify the existing one. Can be one of the
- following values;
-
- MCS_TRANS_LAST The new matrix is applied as;
- old_matrix*new_matrix
-
- MCS_TRANS_FRIST The new matrix is applied as;
- new_matrix*old_matrix
-
- MCS_TRANS_REPLACE The new matrix simply replaces
- the old
-
- Comments
-
- Modifies the position of a coordinate system relative to
- its parent.
-
- Return codes
-
- GERR_INVALID_OPP_IN_TOP
-
-
-
-
- GeomErr Get3DLine (HanCoorSys hcsys,
- Vec &vecA,
- Vec &vecB,
- float *pfStartX,
- float *pfStartY,
- float *pfEndX,
- float *pfEndY);
-
- hcsys Handle of coordinate system points
- belong to.
-
- vecA Position in coordinate system of first
- point.
-
- vecB Position in coordinate system of second
- point.
-
- pfStartX Returns the screen X coordinate of start
- of line.
-
- pfStartY Returns the screen Y coordinate of start
- of line.
-
- pfEndX Returns the screen X coordinate of end of
- line.
-
- pfEndY Returns the screen Y coordinate of end of
- line.
-
- Comments
-
- Returns the 2D screen coordinates of a line segment
- defined by two points; vecA and vecB, within the
- coordinate system hcsys. This routine can be used to
- generate lines corresponding to points in a rendered
- image which can then be superimposed on the rendered
- image. This way it makes it look as if Geometry's
- renderer can support 3D lines as well as patches. Of
- course this is not quite true as the lines do not go
- through the hidden surface/line process.
-
- Unlike the 2D screen coordinates returned on calls like
- QryVertex, this routine doesn't require a Render to have
- taken place, however it does require that the camera is
- set in an appropriate coordinate system for the point to
- be visible, otherwise GERR_NOT_VISIBLE is returned.
-
- Return codes
-
- GERR_NOT_VISIBLE
-
-
-
-
- GeomErr Get3DPoint (HanCoorSys hcsys,
- Vec &vec,
- float *pfX,
- float *pfY);
-
- hcsys Handle of coordinate system points
- belong to.
-
- vec Position of point in coordinate system.
-
- pfX Returns the screen X coordinate of the
- point.
-
- pfY Returns the screen Y coordinate of the
- point.
-
- Comments
-
- Returns the 2D screen coordinates of a point; vec, within
- the coordinate system hcsys.
-
- Unlike the 2D screen coordinates returned on calls like
- QryVertex, this routine doesn't require a Render to have
- taken place, however it does require that the camera is
- set in an appropriate coordinate system for the point to
- be visible, otherwise GERR_NOT_VISIBLE is returned.
-
- Return codes
-
- GERR_NOT_VISIBLE
-
-
-
- Object construction functions
-
-
- GeomErr AddObject (HanCoorSys hcsys,
- float fNewVertTol,
- HanObject *phobj);
-
- hcsys Handle to coordinate system to add
- object to.
-
- fNewVertTol Verticies in this object cannot be
- closer than this value in all of x, y and z.
-
- phobj Returns a handle to the new object.
-
- Comments
-
- Adds a new object to a coordinate system.
-
- When new verticies are added to this object a check is
- made to see if it is closer than fNewVertTol in x, y and
- z. If it is the vertex is re-used. Notice that
- fNewVertTol is not the distance from the existing
- verticies, this is given by the formula;
- MaxDistFromVert=sqrt((NewVertTol^2)*3).
-
- Return codes
-
-
-
-
- GeomErr DelObject (HanObject hobj);
-
- hobj Handle to the object being deleted.
-
- Comments
-
- Deletes an object along with all its patches, verticies
- and normals from a coordinate system.
-
- Return codes
-
-
-
-
- GeomErr QryObject (HanObject hobj, ObjectInfo *poi);
-
- hobj Handle to the object to query.
-
- poi Points to an ObjectInfo structure to
- receive the information.
-
-
- Comments
-
- Returns information on an object.
-
- Return codes
-
-
-
-
- GeomErr PrtObject (HanObject hobj);
-
- hobj Handle to the object to print.
-
- Comments
-
- Used purely as a debugging aid for when writting Geometry
- engines. This routine can be called to print out a text
- description of an objects data structures. It can be
- invoked from the editor using a special key combination.
- Unless compiled with the _DEBUG macro definition this
- routine should do nothing.
-
- Return codes
-
-
-
-
- GeomErr AddVertex (HanObject hobj,
- Vec &vec,
- HanVertex *phver);
-
- hobj Handle to object to add vertex to.
-
- vec 3D position of the vertex within the
- coordinate system.
-
- phver Returns a handle to the vertex.
-
- Comments
-
- Creates a new vertex belonging to the object.
-
- Return codes
-
-
-
-
- GeomErr DelVertex (HanObject hobj, HanVertex hver);
-
- hobj Handle to object we want to delete the
- vertex from.
-
- hver Handle to the vertex to be deleted.
-
- Comments
-
- Deletes a vertex from an object. The vertex is only
- deleted if no patches are using it.
-
- Return Codes
-
- GERR_IN_USE
-
-
-
- GeomErr QryVertex (HanObject hobj,
- HanVertex hver,
- VertInfo *pvi);
-
- hobj Handle to object containg vertex to query.
-
- hver Handle to the vertex to query.
-
- pvi Pointer to a VertInfo structure to receive
- the information.
-
- Comments
-
- Returns information about a vertex. The fScrnX and fScrnY
- elements of the VertInfo structure contain the screen x
- and y coordinates of this vertex the last time a render
- was performed. If the vertex was not visible for whatever
- reason, eg. it was out of view, or the last render was
- applied to a different coordinate system, then
- GERR_NOT_VISIBLE is returned.
-
- The default Geometry engine will indicate that this
- vertex was visible if it was within the view and used by
- a patch which was facing the viewpoint even if the vertex
- was obscurred by a closer object.
-
- Return codes
-
- GERR_NOT_VISIBLE
-
-
-
-
- GeomErr ModVertex (HanObject hobj,
- HanVertex hver,
- Vec &vec);
-
- hobj Handle to object containing vertex to
- modify.
-
- hver Handle to vertex to modify.
-
- vec New position.
-
- Comments
-
- Modifies the position of a vertex. The next time a render
- is performed the vertex will appear in its new position.
- If the new position affects a patch with 4 or more sides,
- such that it no longer lies on a plane, then
- GERR_NOT_ON_PLANE is returned.
-
- Return codes
-
- GERR_NOT_ON_PLANE
-
-
-
-
- GeomErr AddNormal (HanObject hobj
- Vec &vec,
- HanNormal *phnor);
-
- hobj Handle to the object to add the normal to.
-
- vec 3D direction vector of the normal. It
- specifies a 3D `direction' rather than an
- absolute point in 3D space.
-
- phnor Returns a handle to the new normal.
-
- Comments
-
- Adds a normal to an object.
-
- Return codes
-
-
-
-
- GeomErr DelNormal (HanObject hobj, HanNormal hnor);
-
- hobj Handle to the object containing the normal
- to delete.
-
- hnor Handle to the normal to delete.
-
- Comments
-
- Deletes a normal from an object as long as no patches are
- using it.
-
- Return Codes
-
- GERR_IN_USE
-
-
-
-
- GeomErr QryNormal (HanObject hobj,
- HanNormal hnor,
- HanVertex hver,
- NormInfo *pni);
-
- hobj Handle to the object containing the normal
- to query.
-
- hnor Handle to normal to query.
-
- hver Handle to a vertex using the normal
- in order to generate the screen positions
- for the last render.
-
- pni Pointer to a NormInfo structure to receive
- the information.
-
- Comments
-
- Returns information about a normal. Since a single normal
- can be used by verticies from many patches we need to
- supply the handle of a vertex in order to generate the 2D
- screen coordinates of the normal when used by that
- vertex. The normal makes a line extending from the vertex
- to a distance of 1 coordinate system unit away in the 3D
- direction given when the normal was created. If this line
- or any part of it was visible at the last render, its 2D
- screen coordinates are returned, otherwise the return
- code is GERR_NOT_VISIBLE.
-
- Return Codes
-
- GERR_NOT_VISIBLE
-
-
-
-
- GeomErr ModNormal (HanObject hobj,
- HanNormal hnor,
- Vec &vec);
-
- hobj Handle to the object containing the
- normal.
-
- hnor Handle to normal to modify.
-
- vec New direction vector.
-
- Comments
-
- Modifies the direction of a normal vector and therefore
- the surface gradient at all verticies using the normal.
- At the next render the shading at all those verticies
- using the normal will have changed to reflect the new
- surface gradients.
-
- Return codes
-
-
-
-
- GeomErr QryEdge (HanObject hobj,
- HanEdge hedg,
- EdgeInfo *pei);
-
- hobj Handle to the object cotining the edge.
-
- hedg Handle to the edge to be queried.
-
- pei Pointer to an EdgeInfo structure to
- receive the information.
-
- Comments
-
- Returns information about an edge. Although we do not
- explicitly create the edges, we create verticies and
- patches and Geometry takes care of the edges, it is
- sometimes useful to have access to the edges. Suppose we
- want to draw a wire frame of the object (exactly as the
- editor does). We could iteratively query each patch in
- the object, query the screen positions of each of its
- verticies in turn and draw them. However each edge of
- each patch is also used by another patch meaning each
- edge (and therefore the entire object) will get drawn
- twice. Querying the edges directly avoids this.
-
- Return codes
-
-
-
-
- GeomErr DefPatch (HanObject hobj,
- ushort usNumEdges,
- ushort usFlags,
- float fSmoothAng,
- HanVertex *ahver,
- HanNormal *ahnor,
- HanSurf hsur,
- ushort *pusNumPats,
- HanPatch *ahpat);
-
- hobj Handle to object to add patch to.
-
- usNumEdges The number of edges, and therefore
- verticies and normals in the patch. This
- can be any number from 3 upwards. If the
- Geometry engine does not support patches
- of more than say 3 or 4 edges then the
- patch will be automatically split up into
- more than one patch resulting in more than
- one handle being returned.
-
- usFlags Flags controlling the creation of the
- patch. It can be any of the following
- values combined with C's OR operator
- (`|');
-
- DP_AUTOSMOOTH Signifies that the patch should
- appear curved even although we have
- not defined any normals. The normals
- should be created automatically by
- Geometry by averaging out the plane
- normals of all patches converging on
- a vertex.
-
- DP_SMOOTH_BY_SURFSignifies that autosmoothing is
- applied only to patches ajoining this
- one if they have the same surface
- type.
-
- DP_SMOOTH_BY_ANGLE Signifies that autosmoothing is
- applied only to patches ajoining this
- one if they angle made at the join is
- less than that given by the
- fSmoothAng paramter.
-
- DP_DONT_VALIDATE Signifies that this patch should not
- be validated. If you code is fully
- debugged and tested it can use this
- flag to say, `I am confident that
- this patch definition is OK'. Using
- this flag speeds up the creation
- process, otherwise the following
- checks are performed;
-
- · No two points can be in exactly the same spot
- · All points do not lie along a straight line
- · All points lie on a plane (or within a small
- tolerence of)
-
- DP_CONVEX Signifies that the polygon is convex
- (has no internal angles greater than
- 180 degrees). This flag should not be
- used if we're not certain. As with
- DP_DONT_VALIDATE it can speed up the
- creation process, (depending on the
- Geometry engine).
-
- fSmoothAng Specifies the angle to use for
- autosmoothing. Only takes effect if
- DP_SMOOTH_BY_ANGLE is used.
-
- ahver Array of handles to verticies. The number
- of verticies is given by the usNumEdges
- parameter. The verticies must be specified
- in a clockwise order when viewing the
- patch from the correct side. No attempt
- should be made to define a patch using
- verticies belonging to another object.
-
- ahnor Array of handles to normals. The number of
- normals is given by the usNumEdges
- parameter. Each normal relates to the
- corresponding vertex in ahver, eg.
- ahnor[0] applies to aver[0] etc. This
- parameter is ignored if the DP_AUTOSMOOTH
- flag is given. No attempt should be made
- to define a patch using normals belonging
- to another object.
-
- hsur Handle to the surface type to be used for
- the patch.
-
- pusNumPats A pointer to a ushort used to return the
- number of patches actually created (Large
- concave outlines will almost definitely be
- split up into more than one patch). Before
- calling the ushort should be set to the
- size of the ahpat buffer.
-
- ahpat Buffer to hold the handle(s) of the
- patch(es) created.
-
- Comments
-
- Creates a patch out of 3 or more predfined verticies.
- Any number of verticies can be used to define the outline
- of the patch as long as they lie on a plane, do not form
- a straight line or cross over at any point. The
- autosmooth feature takes the worry out of having to
- define normals for curved surfaces.
-
- The outline may be split into more than one patch
- depending on how many verticies the Geometry engine can
- use in a single patch and wether or not it can support
- concave patch outlines. The default Geometry engine
- supports patches of no more than four verticies and they
- must be convex. An attempt to create a patch with more
- than four verticies, or with a concave outline will
- result in more than one patch being created.
-
- Return codes
-
- GERR_COINCIDENT_POINTS
- GERR_THIN_SEGMENT
- GERR_NOT_ON_PLANE
- GERR_OUT_OF_MEMORY
- GERR_BUFFER_TOO_SMALL
- GERR_NOT_ENOUGH_POINTS
-
-
-
-
- GeomErr DelPatch (HanObject hobj, HanPatch hpat);
-
- hobj Handle to the object containing the patch
- to delete.
-
- hpat Handle to the patch to delete.
-
- Comments
-
- Deletes a patch from an object.
-
- Return codes
-
-
-
-
- GeomErr QryPatch (HanObject hobj,
- HanPatch hpat,
- PatchInfo *ppi);
-
- hobj Handle to the object containing the patch
- to query.
-
- hpat Handle to the patch to query.
-
- ppi Pointer to a PatchInfo structure to hold
- the information. The ahver and ahnor
- elements should point to buffers to
- receive the handles of the verticies and
- normals and the usNumEdges element should
- indicate how many handles there is room
- for in the buffers. NB. No Geometry engine
- implementation should have more than
- MAX_PATCH_EDGES edges in any patch
- (defined in geometry.h), so it is a good
- idea to set usNumEdges to this.
-
- Comments
-
- Returns information about a patch.
-
- Return codes
-
- GERR_BUFFER_TOO_SMALL
-
-
-
-
- GeomErr QryVertPatch (ulong *pulRef, HanPatch *phpat);
-
- pulRef Pointer to a ulong holding a reference to
- a patch. This value is returned by the
- ulRef element of the VertInfo structure on
- a call to QryVertex.
-
- phpat Returns a handle to the next patch
- using this vertex.
-
- Comments
-
- To query which patches use a particular vertex, first
- query the vertex, and then pass the ulRef value to
- QryVertPatch. This will return a handle to the first
- patch using that vertex. Subsequent calls to QryVertex
- will return other patches until a NULL_HANDLE is
- returned.
-
- Return codes
-
-
-
- Lighting functions
-
-
- GeomErr AddLight (HanCoorSys hcsys,
- LightDef *pld,
- HanLight *phli);
-
- hcsys Handle to coordinate system to add
- light to.
-
- pld Points to a LightDef structure containing
- details of the light.
-
- phli Returns a handle to a new light.
-
- Comments
-
- Creates a new light belonging to the coordinate system.
-
- Return codes
-
-
-
-
- GeomErr DelLight (HanLight hli);
-
- hli Handle to the light to be deleted.
-
- Comments
-
- Deletes a light from the coordinate system.
-
- Return Codes
-
-
-
-
- GeomErr QryLight (HanLight hli, LightDef *pld);
-
- hli Handle to light to query.
-
- pld Pointer to a LightDef structure to receive
- the information.
-
- Comments
-
- Returns information about a light.
-
- Return codes
-
-
-
-
- GeomErr ModLight (HanLight hli, LightDef *pld);
-
- hli Handle to light to modify.
-
- pld Pointer to LightDef structure containing
- the new parameters.
-
- Comments
-
- Modifies the characteristics of a light, including
- possibly its position.
-
- Return codes
-
-
-
-
- GeomErr SetAmbient (float fInt);
-
- fInt Ambient light intensity.
-
- Comments
-
- Sets the intensity of the ambient light in a scene. The
- ambient value applies to all coordinates systems.
-
- Return codes
-
- GERR_INVALID_LIGHT_INT
-
-
-
-
-
-
- Loading and Saving
-
-
- GeomErr SaveScene (HFILE hfile,
- HanCoorSys hcsys,
- ulong *pulNumCSys,
- HanCoorSys *ahcsys,
- ulong *pulNumObjs,
- HanObject *ahobj)
-
- hfile Handle of a file to save to.
-
- hcsys Coordinate system to save.
-
- pulNumCSys Indicates the size of the ahcsys buffer in
- terms of how many handles it can hold. On
- return this value is modified to the total
- number of coordinate systems saved, and
- therefore the number of handles in the
- ahcsys array.
-
- ahcsys An array which on return contains the
- handles of all the coordinate systems
- saved in the order in which they were
- saved in the file. If you are not
- interested in the handles, this parameter
- can be NULL if we set *pulNumCSys to zero.
-
- pulNumObjs Indicates the size of the ahobj buffer in
- terms of how many handles it can hold. On
- return this value is modified to the total
- number of objects saved, and therefore the
- number of handles in the ahobj array.
-
- ahobj An array which on return contains the
- handles of all the objects saved in the
- order in which they were saved in the
- file. If you are not interested in the
- handles, this parameter can be NULL if we
- set *pulNumObjs to zero.
-
- Comments
-
- Saves a coordinate system to the file given by hfile. All
- objects and lights belonging to this coordinate system
- will be saved including any children and all their
- objects. The last four parameters will return the
- handles of all coordinate systems and objects saved. This
- is very usefull for applications like the editor. The
- editor associates a name with each coordinate system and
- object. These names are unknown to Geometry and so will
- not get saved. However the editor can save the names
- associated with each handle after the main Geometry
- information in the file. When the file gets loaded again
- by LoadScene we get told the new handles which we then
- simply have to associate with the names in the file.
-
- Return codes
-
-
-
-
- GeomErr LoadScene (HFILE hfile,
- HanCoorSys hcsys,
- Char *szTexPath,
- ulong *pulNumCSys,
- HanCoorSys *ahcsys,
- ulong *pulNumObjs,
- HanObject *ahobj)
-
- hfile Handle of a file to load from.
-
- hcsys Coordinate system to load under.
-
- szTexPath A pointer to a path specification for
- where to search for texture bitmaps if
- they are not found in the current working
- directory. This would typically be set to
- the directory where the model file is, or
- else a special texture directory. It must
- have terminating back slash eg;
- "c:\textures\" or else be a null string.
- The pointer cannot be NULL.
-
- pulNumCSys Indicates the size of the ahcsys buffer in
- terms of how many handles it can hold. On
- return this value is modified to the total
- number of coordinate systems loaded, and
- therefore the number of handles in the
- ahcsys array.
-
- ahcsys An array which on return contains the
- handles of all the coordinate systems
- loaded in the order in which they existed
- in the file. If you are not interested in
- the handles, this parameter can be NULL if
- we set *pulNumCSys to zero.
-
- pulNumObjs Indicates the size of the ahobj buffer in
- terms of how many handles it can hold. On
- return this value is modified to the total
- number of objects loaded, and therefore
- the number of handles in the ahobj array.
-
- ahobj An array which on return contains the
- handles of all the objects loaded in the
- order in which they existed in the file.
- If you are not interested in the handles,
- this parameter can be NULL if we set
- *pulNumObjs to zero.
-
- Comments
-
- Loads a coordinate system from the file given by hfile.
- All objects and lights belongning to this coordinate
- system will be loaded including any children and all
- their objects. The top level coordinate system in the
- file will become a child of hcsys. To load an entirely
- new scene hcsys should be set to HCSYS_TOP. For a fuller
- description of the last four parameters see SaveScene.
-
- Return codes
-
- GERR_INVALID_GEN_FILE
-
-
-
-
-
- Structures and types
-
-
- typedef struct Colourtag // col
- {
- byte byRed;
- byte byGrn;
- byte byBlu;
- } Colour;
-
- byRed Red component
-
- byGrn Green component
-
- byBlu Blue component
-
- Comments
-
- Specifies a true RGB colour value.
-
-
-
-
- typedef struct VertInfotag // vi
- {
- Vec vec;
- ulong ulNumPatches;
- ulong ulRef;
- float fScrnX;
- float fScrnY;
- HanVertex hverNext;
- } VertInfo;
-
- vec 3D position of vertex
-
- ulNumPatches Number of patches using this vertex
-
- ulRef Reference to the first patch. To find all
- the patches using this vertex pass this
- value to QryVertPatch
-
- fScrnX The screen X coordinate of this vertex
- after the last Render call
-
- fScrnY The screen Y coordinate of this vertex
- after the last Render call
-
- hverNext Handle to the next vertex in this object
-
- Comments
-
- Contains information about a queried vertex.
-
-
-
-
- typedef struct NormInfotag // ni
- {
- Vec vec;
- HanNormal hnorNext;
- } NormInfo;
-
- vec 3D direction vector of normal
-
- hnorNext Handle to next normal in this object
-
- Comments
-
- Contains information about a queried normal.
-
-
-
-
- typedef struct PatchInfotag // pi
- {
- ushort usNumEdges;
- ushort usFlags;
- HanVertex *ahver;
- HanNormal *ahnor;
- HanSurf hsur;
- Vec vecNorm;
- HanPatch hpatNext;
- } PatchInfo;
-
- usNumEdges Describes the size of the buffers pointed
- to by ahver and ahnor
-
- usFlags Set of bitwise OR'd flags describing the
- patch;
-
- PI_VISIBLE Patch was visible at last render. The
- default geometry engine sets this on
- if the patch was facing us, but was
- maybe obscured by a closer object
-
- PI_FLAT If on object is flat, otherwise it is
- curved
-
- ahver Pointer to a buffer in which the handles
- of the verticies will be returned
-
- ahnor Pointer to a buffer in which the handles
- of the normals will be returned
-
- hsur Handle to the surface used by the patch
-
- vecNorm Normal of the plane of the patch
-
- hpatNext Handle to the next patch in the object
-
- Comments
-
- Contains information about a quieried patch. The ahver
- and ahnor pointers should be set to point to the buffers
- to receive the handles before the query call and
- usNumEdges variable be set to the size of the ahver and
- ahnor buffers.
-
-
-
-
- typedef struct EdgeInfotag // ei
- {
- HanVertex hverA;
- HanVertex hverB;
- HanPatch hpatAB;
- HanPatch hpatBA;
- HanEdge hedgNext;
- } EdgeInfo;
-
- hverA Handle to the vertex at one endpoint
-
- hverB Handle to the vertex at the other endpoint
-
- hpatAB Handle to the patch which uses the edge
- from vertex A to vertex B. NULL_HANDLE if
- not used
-
- hpatBA Handle to the patch which uses the edge
- from vertex B to vertex A. NULL_HANDLE if
- not used
-
- hedgNext Handle to the next edge in this object
-
- Comments
-
- Contains information about a queried edge. Each edge
- should be used twice if the object is fully enclosed by
- patches. If the object isn't fully enclosed one of the
- patch handles will be set to NULL_HANDLE. Since edges are
- created and deleted automatically by the geometry engine
- you will not receive an edge used by no patches as any
- such edges would have been deleted.
-
-
-
-
- typedef struct ObjectInfotag // oi
- {
- ulong ulNumVerts;
- ulong ulNumNorms;
- ulong ulNumPatches;
- ulong ulNumEdges;
- float fNewVertTol;
- ulong ulMemUsed;
- ushort usCoorType;
- HanCoorSys hcsys;
- HanVertex hverFirst;
- HanNormal hnorFirst;
- HanPatch hpatFirst;
- HanEdge hedgFirst;
- HanObject hobjNext;
- } ObjectInfo;
-
- ulNumVerts Number of verticies defined in the object
-
- ulNumNorms Number of normals defined in the object
-
- ulNumPatches Number of patches defined in the object
-
- ulNumEdges Number of edges defined in the object
-
- float Indication of how close new verticies can
- be to neighbouring verticies without
- getting re-used
-
- ulMemUsed Total memory used by object and all its
- verticies, patches etc. (in bytes)
-
- usCoorType Type of coordinate system object belongs
- to;
-
- CT_LEFTHAND Coordinate system is left handed
-
- CT_RIGHTHAND Coordinate system is right handed
-
- hcsys Handle of the coordinate system this
- object belongs to
-
- hverFirst Handle to the first vertex in this object
-
- hnorFirst Handle to the first normal in this object
-
- hpatFirst Handle to the first patch in this object
-
- hedgFirst Handle to the first edge in this object
-
- hobjNext Handle to the next object in the
- coordiante system
-
- Comments
-
- Contains information about a queried object.
-
-
-
-
- typedef struct CoorSysInfotag // csi
- {
- ushort usType;
- Mat matToParent;
- Mat matFromParent;
- HanCoorSys hcsysParent;
- HanCoorSys hcsysNext;
- HanCoorSys hcsysFirstChild;
- HanLight hliFirst;
- HanObject hobjFirst;
- } CoorSysInfo;
-
- usType Type of coordinate system
-
- CT_LEFTHAND Coordinate system is left handed
-
- CT_RIGHTHAND Coordinate system is right handed
-
- matToParent Matrix describing the orientation of this
- coordinate system relative to the parent.
- The matrix will convert a point in our
- coordinate system into that of the parent.
-
- matFromParent The inverse of matToParent. This matrix
- will convert a point in the parent
- coordinate system into ours.
-
- hcsysParent Handle to parent coordinate system
-
- hcsysNext Handle to next sibling coordinate system,
- ie. the next coordinate system which also
- has hcsysParent as its parent
-
- hcsysFirstChild Handle to the first of our child
- coordinate system, ie. the first
- coordinate system which has us as the
- parent (query this coordinate system to
- find the next one)
-
- hliFirst Handle to the first light in this
- coordinate system (query this light to
- find the next one)
-
- hobjFirst Handle to the first object in this
- coordinate system (query this object to
- find the next one)
-
- Comments
-
- Contains information about a queried coordinate system.
-
-
-
-
- typedef struct LightDeftag // ld
- {
- Vec vecPos;
- Vec vecDir;
- ushort usFlags;
- float fInt;
- float fAng;
- Colour col;
- HanLight hliNext;
- } LightDef;
-
- vecPos 3D position of light
-
- vecDir 3D position towards which the light is
- directed
-
- usFlags Flags describing the light;
-
- LI_DIRECTIONAL Light has a directional beam
-
- fInt Intensity of the light from 0 to 1
-
- fAng Angle of the lights beam (if directional)
-
- col Colour of the light
-
- hliNext Handle of the next light in this
- coordinate system
-
- Comments
-
- Contains information about a light. Can be used to set
- the light or query the light. NB. The default Geometry
- engine does not support directional or coloured lights.
-
-
-
-
- typedef struct SurfTypetag // st
- {
- Colour col;
- ushort usFlags;
- ushort usSpecRefChar;
- float fShineCoef;
- float fTransCoef;
- HanCoorSys hcsysTex;
- Mat matTex;
- HanSurf hsurSurf0;
- HanSurf hsurSurf1;
- HanSurf hsurSurf2;
- HanSurf hsurSurf3;
- float fBumpHeight;
- char szFNTex[128];
- } SurfType;
-
- col Basic colour of the surface
-
- usFlags A set of bitwise OR'd flags defining the
- type of surface
-
- DS_TEXTURE Surface is textured
- DS_RECURSIVE_TEXTURE The texture is a recursive
- texture. The default Geometry engine
- does not support recursive textures.
- DS_TILE_TEXTURE The texture will be tiled. If the
- texture is not tiled the basic
- surface colour `col' will show
- through where the texture does not
- reach, or where hsurSurf0-4 is set to
- NULL_HANDLE for recursive textures.
- DS_BUMPED The texture will be bump mapped. It
- is not valid to have this on as well
- as DS_RECURSIVE_TEXTURE. The default
- Geometry engine does not support bump
- mapped textures.
-
- usSpecRefChar This value describes only how the specular
- highlights will appear on the surface. It
- does not mean that an SRC_GOLD surface
- will have a gold colour but given enough
- patches the positioning and size of the
- specular highlights will mimic a surface
- made of gold
-
- The following types are permitted;
-
- SRC_DULL (Surface has no specular
- highlights)
- SRC_CONSTANT (50% reflection
- regardless of incidence
- angle)
- SRC_LINEAR (Amount of reflected light
- increases in proportion to
- incidence angle)
- SRC_SILVER (Produces large diffuse
- highlights)
- SRC_GOLD (Produces dull ring shaped
- highlights)
- SRC_GLASS (Produces highlights only on
- the horizon edges of
- objects)
- SRC_BRASS (The default Geometry engine
- does not implement
- SRC_COPPER any further ,but maps them
- to the nearest of the
- SRC_ALUMINIUM above...)
- SRC_IRON
- SRC_PLASTIC
- SRC_WATER
- SRC_CHINA
- SRC_LEATHER
- SRC_SILK
-
- For completeness sake the following types
- are defined but mean the same as SRC_DULL
- as they are not shiny surfaces;
-
- SRC_ROCK (same as SRC_DULL...)
- SRC_RUBBER
- SRC_WOOD
- SRC_FABRIC
-
- fShineCoef Shinyness coefficient. This values ranges
- from 1 to 10. Large values mean highly
- polished, and therefore very reflective
- surfaces. These generate very small but
- bright highlights with sharply defined
- edges (eg. a snooker ball). Small values
- produces large, dull, diffuse highlights
- (eg. a peice of paper)
-
- fTransCoef Transmissive coefficient. A value ranging
- from 0 to 1 to describe how transparent
- the surface is. A value of 1 would make
- the surface invisible. The default
- Geometry engine does not support
- transmissive surfaces
-
- hcsysTex The handle of the coordinate system the
- texture is defined relative to. See below
- for further details. NB. Because a texture
- is defined in one coordinate system,
- doesn't mean it cant be used by patches in
- another. Textures pervade all of 3D space,
- however because top level coordinate
- systems aren't related to each other by
- matricies like parent-child-sibling
- relationships, it does means that the
- orientation of a texture in one top level
- coordinate system or scene won't have any
- meaning in other and may come out looking
- confusing. However, the ModSurfType call
- can be used to modify the coordinate
- system a texture is defined in
-
- matTex The orientation of the texture bitmap
- within the coordinate system. When a
- texture is defined the bitmap is projected
- through 3D space and `rubs off' on any
- patch using this surface type. If you
- supply the identity matrix here then the
- orientation of the bitmap is such that the
- bottom left is at the origin of the
- coordinate system, and the bottom edge
- proceeds along the x axis for however many
- pixels wide the bitmap is, eg. If we have
- a 100 pixel wide bitmap the bottom left
- will be at 0, 0, 0 and the bottom right at
- 100, 0, 0 in the coordinate system.
- Similarly the top of the bitmap proceeds
- up the y axis of the coordinate system.
- The bitmap is projected through the z axis
- to +/- infinity. By changing this matrix
- you can alter the plane of the bitmap or
- scale it to any size
-
- hsurfSurf0-3 A recursive bitmap is one where the colour
- values in the bitmap refer not to colours
- in the bitmaps palette, but to other
- surfaces types which can in turn be
- textured, or even recursive textures. The
- surface handles for the colour values 0 to
- 3 can be set here. A value of NULL_HANDLE
- means the surface's colour (defined by
- `col') shows through, whereas a value of
- HSUR_SEE_THROUGH means that the object has
- a hole in it at at those points showing
- objects that may be behind. The default
- Geometry engine does not support recursive
- textures
-
- fBumpHeight If the DS_BUMPED flag is set, the colour
- values in the bitmap refer to height
- values for a bumpy surface. The effective
- height of the maximum colour value is set
- using this parameter. The default Geometry
- engine does not support bump mapping
-
- szFNTex The full name (including path and
- extension) of a windows bitmap file to use
- as a texture
-
- Comments
-
- Defines a surface type. This structure can be used to
- both set, query and modify a surface type.
-
-
-
- Tool Interface
-
- Introduction
-
- Although custom tools are implemented as a C++ class, an
- understanding of the C++ language is not essential as we
- have supplied a template source file; toolexmp.cpp,
- defining the class. All you need to do is to fill in the
- functions which can be written in normal C language. The
- source to the patch tool is also supplied as an example
- (see patch.cpp). Only a basic understanding of
- programming the windows operating system is required as
- the only windows calls you are likely to make are the GDI
- drawing calls such as, MoveTo and LineTo. Dialog box
- calls will also be required if your tool needs a
- configuration dialog box. An understanding of the
- Geometry API is required.
-
- The screen shot below is useful to refer to when reading
- this section.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- You will notice that some of the Geometry API functions
- are also available through the tool interface and have
- been slightly modified. This does not mean that you can't
- use the original Geometry version.s There are two reasons
- we have done this; Some functions, DefPatch for example
- are built on top of Geometry's DefPatch and provide
- additional functionality, for instance if an error occurs
- during the DefPatch call (say `out of memory') the error
- will be reported to the user in a message box and
- everything created by the tool up to that point will be
- erased. This is the sort of thing many tools would have
- to implement, so to save time and effort the tool base
- class DefPatch does it for you (if you want it to).
-
- The other reason for duplicating some functions is that
- the editor gives names to things like objects and
- coordinates systems. Since Geometry only has the concept
- of handles and not names, if your tool needs to create an
- object called `MyBox' it needs to call the editor version
- of AddObject for the name to appear in the list box on
- the control bar. If you use the Geometry version it will
- still be visible and will be rendered, but without a name
- it wont be selectable at a single mouse click from the
- listbox and any tools that require the name of an object
- to modify will not be able to process the object.
-
-
- Writing custom tools
-
- Each tool is implemented in a windows DLL by writing a
- C++ class derived from the base tool class; `Tool'. The
- base class is implemented in tool.dll. Your derived class
- should include tool.h and should be linked to tool.lib.
-
- Your DLL should include a resource file defining a 16
- pixel wide by 15 pixel high bitmap with a resource ID of
- one. This bitmap contains an image which will
- automatically be placed on a button in the toolbox to
- enable your tool to be invoked. If you are using
- Microsoft App Studio this can be done by entering; <id>=1
- in the id field of the properties dialog for the bitmap.
-
- The tool object
-
- The DLL should provide a routine to create and delete an
- object belonging to your tool class which will be called
- by the editor. The IMPLEMENT_OBJECT macro will do this
- for you. The following line must be added to your main
- source file;
-
- IMPLEMENT_OBJECT(<your_class_name>)
-
- You must also add the following to the exports section of
- your .def file;
-
- _CREATETOOL
- _DELETETOOL
-
- The editor will create one of your tool objects for each
- scene that exists. Note, this is not the same as the
- view. You can have several views into a single scene. It
- works in the same in same way that a word processor can
- have several documents loaded at once, and you might have
- several windows showing different parts of the same
- document. The reason for this is that it makes tool
- writing considerably simpler as a tool can be
- constructing in different scenes at once without the tool
- code having to manage a complete set of varaibles
- relating to each scene. Therefore a tool defines just one
- set of member variables that it needs to do its job.
-
- The tool's configuration dialog box
-
- If your tool defines a configuration dialog box, you
- generally want the dialog to apply to all tools belonging
- to your object. For instance when editing in scene A, you
- configure your tool in a certain way. You then switch to
- scene B, since you see only one tool of your type in the
- toolbox, you assumes it is configured the way you just
- set it. Now, if your configuration data is stored as
- member variables within your object there will be a
- separate configuration for each tool, ie one for each
- scene. So generally it is best to make your configuration
- variables static members or global.
-
- How to tell the editor about your tool
-
- The name of your DLL should be added to the Gened.ini
- file in the main windows directory, under the section
- [Tools] as follows;
-
- [Tools]
- 0=patch
- 1=sphere
- 2=box
- :
- n=<name of your DLL>
-
- The value of n must be the next unused consequective
- number.
-
- Overriding tool functions
-
- Whenever the `Set' or `Do' buttons on the control bar is
- pressed, or the `Undo' menu item is selected an
- appropriate function is called in the currently selected
- tool. The tool base class provide default functions which
- actually do nothing. To detect these events you can
- override these functions in your derived class. The
- following table shows the events which trigger tool
- functions;
-
- Event Called when
- OnSelect The tool has been selected from the
- toolbox
- OnUnSelec An attempt has been made to select
- t another tool
- OnButtonD The mouse is in the view and the left
- own button is pressed
- OnMouseMo The left button is pressed and the
- ve mouse moves
- OnButtonU The left mouse button is released
- p
- OnSet The `Set' button on the control bar
- is pressed
- OnDo The `Do' button on the control bar is
- pressed
- OnViewCha The active view into the scene has
- nge changed
- OnUndo The `Undo' menu item is selected and
- this was the last active tool
- OnConfigu The user requests to configure the
- re tool
-
- Calling sequence
-
- The very first call to all tools is Initialise. Overide
- it if you need to initialise any variables. The next
- likely call to your tool will be when it is selected from
- the toolbox, the OnSelect routine will be invoked. Then
- as the user user clicks and moves the mouse in the view
- you will receive OnButtonDown, OnMouseMove and OnButtonUp
- events. Then when the user presses the `Set' button,
- having positioned the 3D cursor, the OnSet call is
- invoked. This can be invoked as many times as your tool
- requires. If your tool requires an indefinite number of
- Set presses, then the `Do' button can be used to do
- whatever is required to complete the tools action. For
- instance, the patch tool uses Set to position each
- vertex. Since you can define an indefinite number of
- verticies, the Do button is used to create the patch. The
- interpretation of the buttons is entirely up to you.
-
- All events are directed to the currently selected tool
- only, apart from, obviously OnSelect, and OnUndo.
-
- Modifying and undoing
-
- For your custom tool to be seamlessly integrated with the
- editor, it must be capable of undoing any action it has
- performed on the object. If and when a tool modifies any
- aspect of a scene, wether its creating or deleting part
- of an object, moving a light or even changing the colour
- of a patch it must call the `ModifiedScene' function.
- This has two effects. First of all it marks the scene as
- having changed and will give the user a warning if he
- tries to close the editor down without having saved the
- scene first. Secondly it marks this tool for calling
- should the user select the `Undo' menu item. This tool
- can now be called to undo its action even after it has
- been de-selected, at least until another tool calls the
- ModifiedScene routine.
-
- Drawing into the view
-
- During the construction of a primitive the tool will
- probably need to draw into the views showing the object
- being constructed, to give the user some feedback about
- what is going on. There are two ways of doing this. The
- tool can implement the DrawSoFar routine so that whenever
- the view gets updated it gets a chance to draw into the
- DC representing the view window. The patch tool draws a
- dotted line between the cursor positions at each point
- Set was pressed using this technique. The patch isn't
- actually created on Geometry until the Do button is
- pressed. Alternatively, more complex tools might
- construct the object on Geometry in several steps (eg.
- during Set presses, or on mouse move events) in which
- case the editor can redraw it for you. The sphere tool
- does this. A combination of these techniques can also be
- used.
-
- When the screen view needs repainting, say if part of it
- is uncovered by a window on top, the editor redraws the
- rendered image along with its wire frame and then calls
- the selected tool's DrawSoFar routine passing it the
- device context handle of the view window. The DrawSoFar
- routine will be called for each view into the object
- which needs updating. If we attempt to draw into the view
- on any call other than a DrawSoFar, then we have to
- consider the fact that there might be several views into
- this object all of which will need updating. For this
- reason drawing should be reserved exclusively for the
- DrawSoFar routine.
-
- The view will probably need updating after a Set/Do press
- or an Undo selection. Although we cannot draw on these
- event we can return a value which will cause the view to
- be repainted, and therefore DrawSoFar to be called.
-
- Drawing return codes
-
- For each view into the scene the editor maintains two
- bitmaps. The first is the full colour rendered bitmap
- generated by Geometry's Render call. The second is a
- monochrome overlay containing the image of the x, y, and
- z axis, the objects wire frame, and optionally a set of
- grid points. When the object changes all this needs to be
- updated; the image must be re-rendered and the overlay
- regenerated. When a tool is in a constructing state, we
- might want to draw the object quickly. For instance the
- sphere or box tool might require the radius or corner to
- be dragged by the mouse and released when you release the
- button. Given that there could be several views into the
- object there is not time to re-render and regenerate the
- overlay for every view as the mouse moves. The whole
- thing would be too slow. The following return codes from
- event functions can tell the editor how to redraw
- quickly.
-
- REDRAW_ALL
-
- This is typically used only once when the tool has
- finished its business and tells the editor to re-render
- the main bitmaps and regenerate all overlays for each
- view. The screen image for each view is then refreshed
- from both of these. This takes the most amount of time
- and so it is highly unlikely you will ever want to use
- this from a mouse move event.
-
- The current tools DrawSoFar routine will also be.
-
- REDRAW_NONE
-
- Pretty much self explanitory. This return code will not
- affect the on screen image in any way.
-
- REDRAW_OBJECT_WIRE
-
- This causes the editor to draw the wire frame of the last
- object created by the tool base class's AddObject
- function directly onto the screen using the GDI XOR mode.
- The XOR mode has the effect that if you draw something
- into a DC twice, it actually removes it leaving you with
- the original image. Using this return code does not cause
- the screen image to get refreshed from the rendered and
- overlay bitmaps, so it is very fast. The box creation
- tool might use this return code to update the wire frame
- of the box on the mouse move event when dragging a corner
- to get the correct box size (see the `Dragging with the
- mouse' section).
-
- Again the current tools DrawSoFar routine is called.
-
- REDRAW_TOOL
-
- The REDRAW_ALL and REDRAW_OBJECT_WIRE return codes result
- in the editor redrawing the object as it exists within
- Geometry (ie. as seen through Geometry's query
- functions). If the object within Geometry hasn't changed,
- returning these codes will be wastefull as the on screen
- image wont change. Instead the REDRAW_TOOL return code
- results in just the tools DrawSoFar routine being called.
- The patch tool uses this after setting a vertex.
-
- REDRAW_NOTOOL
-
- This causes the editor to simply refresh the screen from
- its internal bitmaps, thereby effectively removing any
- image drawn as a result of a DRAW_OBJECT_WIRE code, or
- anything drawn by a tool's DrawSoFar routine. If a tool
- has used either of these to draw an object during a
- construction phase but undo was selected before the
- operation completed, then this return code can be used to
- erase the `construction image' on the screen. If we
- actually constructed parts of an object on Geometry then
- we must remember to remove them as well otherwise the
- next time a render is performed the object will reappear!
-
- The DrawSoFar routine is not called as a result.
-
-
- REDRAW_REFRESH
-
- This is the same as a REDRAW_NOTOOL except that the
- tool's DrawSoFar routine is called as well.
-
- Getting 2D screen coordinates
-
- The actual drawing is done using the windows GDI. The 2D
- window coordinates you need to perform the drawing
- operations can be got using Geometry calls such as
- Get3DPoint and Get3DLine. The Geometry API spec states
- that before you can use these calls you must set the
- camera in the appropriate coordinate system. Obviously
- without specifying a camera view the 3D coordinate you
- work with will not have a 2D counterpart. Before
- DrawSoFar is called the editor sets the camera at the
- viewpoint in the coordinate system of the view being
- redrawn so the tool doesn't have to worry about this. On
- event calls like OnSet and OnMouseMove the camera is set
- in the currently active view, ie. the one that has the
- focus.
-
-
-
- Dragging with the mouse
-
- The sphere tool creates a small sphere when Set is
- pressed, if the `quickdraw' configuration option is
- switched off. It then traps the OnMouseMove event and
- scales the sphere to the correct radius. By returning
- REDRAW_OBJECT_WIRE it gets the editor to draw the wire
- frame of the sphere.
-
- If it is more appropriate to perform drawing ourself then
- simply use GDI's ROP2 setting of XORPEN to draw and erase
- your image in the DrawSoFar routine. You may of course
- prefer to save the background before drawing on it, but
- in general we have found that XOR drawing is faster. The
- only thing to remember is that if you change any of the
- DC's attributes such as selected pen, drawing mode etc.
- you must set them back to the originals before DrawSoFar
- returns. NB. This is a general requirement of programming
- in Windows.
-
- XOR'ing in multiple views
-
- If you wish to implement dragging on the mouse move event
- as described above there is just one other thing to bear
- in mind. Consider the following sequence of events.
- Assume that this is part of a cube construction tool. We
- `Set' the cursor at one corner then move the cursor to
- the opposite corner (during which the box is being
- dynamically sized in the view[s]), and press `Do'.
- Further assume we have two views into this scene.
-
- 1. OnSet event - Set the 3D coordinates of the first
- corner to those of the cursor. Set the 3D coordinates of
- the far corner to the same as the first and return
- REDRAW_TOOL to start the XOR drawing (initially a point
- sized cube as both corners are in the same place)
- 2. OnDrawSoFar call - Called for the first view as a
- result of returning REDRAW_TOOL from OnSet. Being the
- first DrawSoFar for this view there is no previous
- construction image to remove, so simply draw the image in
- XOR mode (ie. a cube) using Get3DPoint to convert your 3D
- corners into 2D window coordinates and draw them using
- the GDI. Store the 2D coordinates of your construction
- image so you can erase it later
- 3. OnDrawSoFar call - Called for the second view. Do
- exactly the same as for the previous DrawSoFar but for
- the second view
- 4. OnMouseMove event - Set the 3D coordinates of the
- opposite corner to the cursor position, and return
- REDRAW_TOOL
- 5. OnDrawSoFar call - Called for the first view as a
- result of returning REDRAW_TOOL from the OnMouseMove
- event. Redraw the old construction image in XOR mode to
- erase the image and redraw the image in XOR mode using
- the opposite corner in its new position
- 6. OnDrawSoFar call - Called for the second view. Do
- exactly the same as for the previous DrawSoFar but for
- the second view
- 7. Do steps 4, 5 and 6 - For however many mouse move
- events we get
- 8. OnDo event - Construct the cube using Geometry and
- return REDRAW_ALL to get it rendered properly
-
- You will notice that because we have two views we get two
- DrawSoFar calls every time we return REDRAW_TOOL from an
- event. This means that we must store two sets of
- coordinates in order to removethe previous XOR image. For
- this purpose DrawSoFar gets called with a parameter to
- instance data relating to each particular view.
-
- DrawSoFar parameters
-
- The first parameter contains the DC handle of the view.
- You need this when using GDI drawing commands.
-
- The second parameter is a pointer to a 60 byte area of
- memory stored as part of each view known as the view
- instance data. You can use this memory to store whatever
- you like, eg. coordinates of the construction image. If
- you need more memory than this you can allocate your own
- and store a pointer to the memory in the view instance
- data. The SetViewData call in the tool base class can be
- used to intialise the instance data at any time (say,
- from the OnSet event).
-
- The final parameter is a boolean value which says why
- this routine has been called. Not only will you receive a
- DrawSoFar call as the result of returning REDRAW_TOOL
- from an event but you will also receive one if part of
- the view was invalidated by a window on top of the view
- being removed. In normal windows programming this will
- generate a WM_PAINT message. If this happens and your
- tool is in the process of constructing an XOR image it
- must not erase the previous image because the view is
- invalid in that region. As a general rule, if this
- bInvalid parameter is TRUE simply draw the XOR image as
- if it were the first OnDrawSoFar for this view.
-
- General guidelines
-
- Help on using tools
-
- As a general rule any tool should provide instructions to
- the user on how to operate the tool. The recommended
- approach is at each stage inform the user what to do next
- by writing a message in the status bar at the bottom of
- the main window using the WriteMessage function. See the
- Sphere or Patch tools as an example.
-
- Displaying text strings
-
- Whenever your tool displays any text it is a good idea to
- load the text from a string table resource. This way if
- your tool ever gets used in other countries, language
- translation is a simple matter of going through the
- string table and recompiling to get a new DLL, rather
- than having to search through the source code for literal
- strings. The tool base class functions such as
- WriteMessage and MessageBox aid this by allowing you to
- present string resource ids as well as character
- pointers.
-
-
- Coordinate system types
-
- Any tool which creates patches has to consider the fact
- it could be invoked in either a lefthand or a righthand
- coordinate system. The significance is in the ordering of
- the verticies. Remember verticies should always be seen
- to progress clockwise around the patch. If your tool
- works fine in one system but not in the other then you
- probably need to reverse the ordering in the system which
- doesn't work.
-
-
-
- A note for C Users
-
- For those not familiar with C++, you can use the
- toolexmp.cpp file as a base to work from. The functions
- defined in the `Overridables' section are functions you
- can implement yourself if you're interested in trapping
- those particular events. Empty functions are defined but
- commented out in toolexmp.cpp. If you want to trap mouse
- moves events simply uncomment it and add your code using
- normal C. Remember C++ is a superset of the C language.
-
- The functions defined in the section titled `Support' are
- supplied for you to call should the need arise. One thing
- you will realise about C++ is that a function is
- specified not just by its name but also by its paramters,
- meaning you can have two or more functions with the same
- name as long as they have differents paramters (NB. The
- MessageBox support function is an example).
-
- Some variables are also defined in the `Support' section.
- In C++ terminology these are protected variables defined
- in the base class. Non C++ programmers can just think of
- them as global variables containing information which may
- or may not be of use to your tool. You must not attempt
- to alter these vaiables.
-
-
-
- Overridables
-
-
- virtual ~Tool();
-
- Comments
-
- Destructor for your tool object. This function must be
- overidden even if it does nothing. As with any normal C++
- class, if you create a constructor for your object which
- allocates resources, the destructor must release these
- resources. C users can leave this function empty.
-
-
-
-
- virtual void Initialise();
-
- Comments
-
- Called once when the DLL is loaded. This call can be used
- to initialise variables.
-
-
-
-
- virtual Redraw OnSelect(Vec &vec);
-
- vec Current psition of the 3D cursor.
-
- Comments
-
- Called when the user selects the tool from the toolbox.
-
-
-
-
- virtual Redraw OnUnSelect(bool *pbOkToChange)
-
- pbOkToChange Set this to TRUE if it is OK for the
- editor to change the current tool.
-
- Comments
-
- Called when the user tries to select another tool from
- the toolbox. If the tool is in the middle of a
- complicated operation it can either set *pbOkToChange to
- FALSE or it can either abort its operation or complete it
- without further action from the user. What happens here
- is up to the tool writer. Remember the tool can always
- undo what its just done if the user isn't happy.
-
-
-
-
- virtual void OnConfigure();
-
- Comments
-
- Called when the tool is selected and the user then
- selects the Configure item from the Tool menu. Typically
- this call is overrided to construct a dialog box enabling
- the user to enter configuration information for the tool.
-
-
-
-
- virtual Redraw OnButtonDown(Vec &vec);
-
- vec Current psition of the 3D cursor.
-
- Comments
-
- Called when the tool is selected and the user presses the
- left mouse button when the mouse is in a view allowing
- the 3D cursor to be moved. The vec parameter gives the
- coordinates of the 3D cursor. The editor assumes the tool
- is in a constructing state only after the first Set
- press, so if you overide this function, construction
- should not start until Set has been pressed. The Redraw
- return code can be used to tell the editor how to
- efficiently redraw the view.
-
-
-
-
- virtual Redraw OnMouseMove(Vec &vec);
-
- vec Current psition of the 3D cursor.
-
- Comments
-
- Called when the 3D cursor moves within a view. NB.
- Windows programmers should realise that this is not quite
- the same as a WM_MOUSEMOVE message as the left button has
- to be depressed while the mouse is over a view.
-
-
-
-
- virtual Redraw OnButtonUp(Vec &vec);
-
- vec Current psition of the 3D cursor.
-
- Comments
-
- Called when the tool is selected and the user releases
- the left mouse button when the mouse is in a view.
-
-
-
-
- virtual Redraw OnSet(Vec &vec);
-
- vec Current psition of the 3D cursor.
-
- Comments
-
- Called when the 'Set' button is clicked after a tool has
- been selected.
-
-
-
-
- virtual Redraw OnUndo();
-
- Comments
-
- Called when user wishes to undo effect of tool. This can
- be called even if the tool is not selected. If the
- currently selected tool is not in a constructing state
- and the user selects `Undo' from the `Edit' menu, then
- the last tool to modify the object data is called.
-
-
-
-
- virtual Redraw OnDo(Vec &vec);
-
- vec Current psition of the 3D cursor.
-
- Comments
-
- Called when the user presses the `Do' button on the
- control bar. Typically this is used to end use of the
- selected tool.
-
-
-
-
- virtual void OnViewChange(HanCoorSys hcsys, Vec &vec);
-
- hcsys The coordinate system of the new
- active view.
-
- vec Current psition of the 3D cursor.
-
- Comments
-
- Called when the user clicks the mouse in a new view
- making it active. Since there is a separate object of
- each tool type for each scene the tool will not be
- notified of a view change into a different scene. In fact
- the new active scene could have a different tool type
- currently selected.
-
- This event is also called if a tool calls the base class
- version of AddCoorSys with the bAddView parameter set to
- TRUE. In this case the OnViewChange event is called
- before the AddCoorSys call returns.
-
- virtual void DrawSoFar(HDC hdc,
- HanCoorSys hcsys,
- void *pvViewData,
- bool bInvalid);
-
- hdc A handle to the device context of the view
- being redrawn.
-
- hcsys Coordinate system handle of the view
- being redrawn.
-
- pvViewData Pointer to instance data for the
- view.
-
- bInvalid The region being redrawn was invalidated,
- probably by a window on top being removed.
-
- Comments
-
- Called when the view is being redrawn to give the tool a
- chance to draw the `object so far' into the view.
-
-
-
- Support
-
-
- Protected member variables
-
- hinst Instance handle of the tool DLL.
-
- hwnd Handle to the main frame window.
-
- ahverPrim Array of handles to verticies created
- (ulNumVerts contains how many). See
- StartPrim for details.
-
- hverPrim Last handle created by an AddVertex call.
-
- ulNumVerts Number of vertex handles in
- ahverPrim.
-
- ahnorPrim Array of handles to normals created
- (ulNumNorms contains how many). See
- StartPrim for details.
-
- hnorPrim Last handle created by an AddNormal call.
-
- ulNumNorms Number of normal handles in
- ahnorPrim.
-
- ahpatPrim Array of handles to patches created
- (ulNumPats contains how many).
-
- ulNumPats Number of patch handles in ahpatPrim.
-
- hcsysTopLevel Handle of top level coordinate system in
- this scene.
-
-
-
-
- void WriteMessage(int iResId);
- void WriteMessage(const char *szMsg);
-
- iResId The resource id of the string within
- the DLLs resource file.
-
- szMsg Pointer to a null terminated string.
-
- Comments
-
- Called to write a message in status bar at the bottom of
- the main window.
-
-
-
-
- int MessageBox(int iTitleId, int iMsgId,
- UINT uiStyle =MB_ICONEXCLAMATION);
- int MessageBox(int iTitleId, char *szMsg,
- UINT uiStyle =MB_ICONEXCLAMATION);
- int MessageBox(int iTitleId, GeomErr gerr);
-
- iTitleId The resource id of a string to use for the
- message box title.
-
- iMsgId The resource id of the main message
- string.
-
- szMsg A pointer to the message string.
-
- gerr A Geometry error value. The routine will
- query an appropriate error string from
- Geometry, and will use the
- MB_ICONEXCLAMATION style.
-
- uiStyle One of windows MB_ values to indicate the
- type of message box. This defaults to
- MB_ICONEXCLAMATION if omitted.
-
- Comments
-
- Puts a message box on the screen. There are three
- variations on this function. If a tool gets an internal
- processing error return code from Geometry it should use
- the third form to notify the user, and then abort
- whatever action it was performing.
-
- The return code is the same as for the windows MessgeBox
- function.
-
-
-
-
- bool StartPrim (HanObject hobj,
- ulong ulMaxVerts,
- ulong ulMaxNorms,
- ulong ulMaxPats,
- bool bReportErrs,
- bool bUndoOnErr);
-
- hobj Handle to the object we want to add to.
-
- ulMaxVerts Maximum number of verticies we will
- be adding.
-
- ulMaxNorms Maximum number of normals we will be
- adding.
-
- ulMaxPats Maximum number of patches we will be
- adding.
-
- bReportErrs If this is set to TRUE any Geometry errors
- that occur during AddVertex, AddNormal, or
- DefPatch (eg. `out of memory' or
- `verticies not on a plane') will be
- reported to the user in an message box.
-
- bUndoOnErr If this is set to TRUE and a Geometry
- error occurs then every patch, vertex and
- normal added to the object since the
- StartPrim call will be removed.
-
- Comments
-
- This routine can be used along with the, AddVertex,
- AddNormal and DefPatch routines to add elements to an
- object. They are usually more convenient than Geometry's
- version of these functions because the handles to the
- elements are automatically stored in arrays allocated by
- this routine. For instance a tool will usually want to
- access say the handle for the 8th vertex that it created.
- If we use the base class version of the AddVertex
- function we can access this handle using the ahverPrim
- protected member variable of the tool base class, ie.
- ahverPrim[7] for the 8th vertex. Similaraly ahnorPrim[7]
- will access the 8th normal created and ahpatPrim[7] will
- give you the 8th patch. What is more, if we need to undo,
- the RemovePrim function will remove all the elements
- created so far.
-
- Once the tool has finished constructing and we have no
- further interest in the handles, we must call the EndPrim
- function to release the handle arrays. If during any
- `Add' function a serious error is returned by Geometry a
- description of the error can be automatically reported to
- the user and the RemovePrim function called to remove all
- elements created. The return code is then passed back to
- the tool. In this case you must not call EndPrim.
-
- If the tool has any reason to call RemovePrim itself it
- should not call EndPrim as the RemovePrim routine does
- this for you.
-
- If you call say AddVertex to create more verticies than
- you originally specified on the StartPrim call the
- function will not fail, but the handle will not be stored
- either, therefore if you call RemovePrim you might find
- it doesn't remove all of your object.
-
- StartPrim can be called with an object already containing
- vertices, patches and normals.
-
- This routine returns TRUE if it succeeded.
-
-
-
-
- void EndPrim ();
-
- Comments
-
- Called after a StartPrim and when the tool has no further
- need for handles to the elements its created. This
- routine removes the buffers allocated by StartPrim.
-
-
-
-
- void RemovePrim ();
-
- Comments
-
- Removes all primitive elements (verts, normals and
- patches) added to the object the tool is working on.
- Should be called only if a StartPrim has been called.
-
- GeomErr AddVertex (Vec &vec);
-
- vec Position of vertex.
-
- Comments
-
- Adds a vertex to the object specified by a call to
- StartPrim and records its handle in the ahverPrim array.
- The hver variable can be used as a more convenient way of
- accessing the last handle created by an AddVertex call.
-
- If Geometry reports an error this is passed to the user
- in a message box.
-
- This call can only be used after a call to StartPrim. See
- StartPrim comment and Geometry's AddVertex function for a
- full description.
-
-
-
-
- GeomErr AddNormal (Vec &vec);
-
-
- vec Direction of normal.
-
- Comments
-
- Adds a normal to the object specified by a call to
- StartPrim and records its handle in the ahnorPrim array.
- The hnor variable can be used as a more convenient way of
- accessing the last handle created by an AddNormal call.
-
- If Geometry reports an error this is passed to the user
- in a message box.
-
- This call can only be used after a call to StartPrim. See
- StartPrim comment and Geometry's AddNormal function for a
- full description.
-
-
-
-
- GeomErr DefPatch (ushort usNumEdges,
- ushort usFlags,
- float fSmoothAng,
- HanVertex *ahver,
- HanNormal *ahnor,
- HanSurf hsur);
-
- usNumEdges The number of edges, and therefore
- verticies and normals in the patch. This
- can be any number from 3 upwards.
-
- usFlags Flags controlling the creation of the
- patch.
-
- fSmoothAng Specifies the angle to use for
- autosmoothing. Only takes effect if
- DP_SMOOTH_BY_ANGLE flag is used.
-
- ahver Array of handles to verticies. The number
- of verticies is given by the usNumEdges
- paramter.
-
- ahnor Array of handles to normals. The number of
- verticies is given by the usNumEdges
- paramter.
-
- hsur Handle to the surface type to be used for
- the patch. If you use NULL_HANDLE here
- then the currently selected surface type
- will be used. If no surface type has been
- selected then any available type will be
- used. If no surface types exists then one
- will be created.
-
- Comments
-
- Adds a patch to the object specified by a call to
- StartPrim and records its handle in the ahpatPrim array.
- Unlike AddVertex and AddNormal you cannot access the last
- handle created using a protected base class variable as a
- call to AddPatch can result in several patches being
- created.
-
- If Geometry reports an error this is passed to the user
- in a message box.
-
- This call can only be used after a call to StartPrim. See
- StartPrim comment and Geometry's DefPatch function for a
- full description.
-
-
-
-
- HanObject AddObject(HanCoorSys hcsys,
- char *szName,
- ushort usBuffSize,
- float fNewVertTol,
- HanObject hobj)
-
- hcsys Handle to coordinate system to add object
- too.
-
- szName The name of the object to appear in the
- object list box. The actual name used is
- returned in this buffer as the name
- supplied might already be in use. If this
- is the case a number is added to the end
- of the name.
-
- usBuffSize Size of the szName buffer. To ensure that
- the modified name will fit you can set
- this to MAX_NAME_BUFF_LEN but ensure that
- the supplied string uses no more than
- MAX_NAME_LEN of the buffer. If the actual
- name used is of no interest this can be
- set to zero, so the buffer will not be
- modified. This allows use of a literal
- string, eg. AddObjec(hcsys, "box", 0...)
-
- fNewVertTol The tolerence setting for creating new
- verticies rather than reusing old ones.
-
- hobj If the object already exists within
- Geometry and you simply want to give it a
- name, the existing object handle can be
- supplied here.
-
- Comments
-
- This function does not have to be used in conjunction
- with StartPrim and EndPrim. It simply calls Geometry's
- AddObject function to start an empty object in the given
- coordinate system. However by supplying a name, the
- object gets added to the object list on the control panel
- thereby allowing the entire object to be selected by
- highlighting its name.
-
-
-
-
- HanCoorSys AddCoorSys(HanCoorSys hcsysParent,
- char *szName,
- ushort usBuffSize,
- HanCoorSys hcsys,
- Mat &matToParent,
- Mat &matFromParent,
- ushort usType,
- bool bAddView);
-
- hcsysParent Handle to the parent coordinate system.
-
- szName The name of the coor sys to appear in the
- list box. The actual name used is returned
- in this buffer as the name supplied might
- already be in use. If this is the case a
- number is added to the end of the name.
-
- usBuffSize Size of the szName buffer. To ensure that
- the modified name will fit you can set
- this to MAX_NAME_BUFF_LEN but ensure that
- the supplied string uses no more than
- MAX_NAME_LEN of the buffer. If the actual
- name used is of no interest this can be
- set to zero, so the buffer will not be
- modified. This allows use of a literal
- string, eg. AddCoorSys(hcsys, "new", 0...)
-
- hcsys If the coor sys already exists within
- Geometry and you simply want to give it a
- name, the existing handle can be supplied
- here.
-
- matToParent Matrix describing the transformation from
- child to parent. In other words this
- matrix transforms a point in the child
- coordinate system to its corresponding
- position relative to the parent coordinate
- system.
-
- matFromParent The inverse or opposite matrix to
- matToParent. NB. The maths library can
- easily generate the inverse of a matrix by
- preeceeding it with a minus sign (eg. -
- mat).
-
- usType This value indicates wether the
- coordinate system being defined is right
- handed or left handed. It should be either
- CT_RIGHTHAND or CT_LEFTHAND.
-
- bAddView If this is set to TRUE a new view window
- will appear.
-
- Comments
-
- Creates a new coordinate system as a child hcsysParent.
- Its name will appear in the coor sys list box. There are
- many advantages of using a named coordinate system rather
- than creating an unamed one using the Geometry API, for
- instance, a named coordinate system can be used in the
- surface type dialog to specify an orientation for a
- texture.
-
-
-
-
- bool DelObject(const char *szName);
-
- szName The name of the object to delete.
-
- Comments
-
- Deletes a named object from Geometry and removes its name
- from the listbox. The function returns TRUE if
- successfull.
-
-
-
-
- bool DelCoorSys(const char *szName);
-
- szName The name of the coordinate system to
- delete.
-
- Comments
-
- Deletes a named coordinate system from Geometry and
- removes its name from the listbox. The function returns
- TRUE if successfull.
-
-
-
-
- ushort GetSelectedObjects(char *szNames, ushort
- usBuffSize);
-
- szNames List of object names.
-
- usBuffSize Size of the szNames buffer.
-
- Comments
-
- Returns the list of object names that are highlighted in
- the object listbox. Each name is terminated with a null,
- and the entire list is terminated with a double null.
-
-
-
-
- HanObject GetObjectHandle(const char *szName);
-
- szName The name of the object whose handle is to
- be returned.
-
- Comments
-
- Returns the handle of the named object. A NULL_HANDLE is
- returned if the name was not recognised.
-
-
-
-
- HanObject GetCoorSysHandle(const char *szName);
-
- szName The name of the coor sys whose handle is
- to be returned.
-
- Comments
-
- Returns the handle of the named coordinate system. A
- NULL_HANDLE is returned if the name was not recognised.
-
-
-
-
- void GetObjectName(HanObject hobj, char *szName,
- ushort usBuffSize);
-
- hobj The handle of the object whose name we
- want returned.
-
- szName The name of the object.
-
- usBuffSize Length of the szName buffer.
-
- Comments
-
- Returns the name of a given object. A zero length string
- is returned if the handle was not recognised.
-
-
-
-
- void GetCoorSysName(HanCoorSys hcsys, char *szName,
- ushort usBuffSize);
-
- hcsys The handle of the coor sys whose name we
- want returned.
-
- szName The name of the coor sys.
-
- usBuffSize Length of the szName buffer.
-
- Comments
-
- Returns the name of a given coor sys. A zero length
- string is returned if the handle was not recognised.
-
-
-
-
- void ForceRedraw(Redraw rd,
- HanCoorSys hcsys=NULL_HANDLE);
-
- rd The redraw code to use.
-
- hcsys The handle of the coordinate system whose
- view is to be redrawn. If more than one
- view window exists for this coor sys they
- are all redrawn. If a NULL_HANDLE is
- passed, every view into the scene (ie. all
- coordinate systems) is redrawn.
-
- Comments
-
- Forces a redraw of one or more views. This function is
- usefull if a tool constructs a dialog box which has
- buttons that can be invoked independently of any events
- from the editor. For instance the coor sys editing tool
- has a dialog whose buttons could invoke a redraw. All
- resulting DrawSoFar calls will be made before this call
- returns.
-
-
-
-
- void DrawMarker(HDC hdc, int iX, int iY, ushort usType);
-
- hdc Handle to device context to draw into.
-
- iX Device context X coordinate for marker.
-
- iY Device context Y Coordinate for marker.
-
- usType Type of marker to draw. Can be one of
- the following values;
-
- MT_BOX A small square marker
- MT_PLUS A `+' shaped marker
- MT_CROSS An `X' type cross marker
- MT_DIAMOND A small diamond shaped
- marker
-
- Comments
-
- Draws a marker into the device context at the specified
- position using the current attribute (pen, colour, mode
- etc) settings of the DC.
-
-
-
-
- void DrawArrow(HDC hdc, int iX, int iY, ushort usFlags);
-
- hdc Device context to draw into.
-
- iX Device context x coordinate of the arrow
- head.
-
- iY Device context y coordinate of the arrow
- head.
-
- usFlags Type of marker to draw. Can be one of the
- following values;
-
- DA_FILLED The arrow head is filled in
- DA_FIXEDSIZE The arrow head is fixed in
- size as opposed to
- proportional to the length
- of the arrow body
-
- Comments
-
- Draws an arrow from the current position in the device
- context to iX, iY.
-
-
-
-
- bool ActivateCSysWin(HanCoorSys hcsys);
-
- hcsys Handle of coordinate system whose view is
- to be activated.
-
- Comments
-
- Activates the view window associated with a coordinate
- system. This means bringing it on top of the other
- windows and highlighting its title bar. An OnViewChange
- event will be received before this call returns.
-
-
-
-
- HanSurf GetCurrentSurf();
-
- Comments
-
- Returns the handle of the currently selected surface
- type.
-
-
-
-
- void ModifiedScene();
-
- Comments
-
- This routine must be called after any tool modifies the
- scene in any way. Not only does it mark the tool as the
- one which should perform an undo if the user requests it,
- but also it marks the document as modified such that a
- warning will be issued if an attempt is made to close the
- editor without saving it first.
-
-
-
-
- void SetViewData(void *pvData, ushort usSize);
-
- pvData Pointer to the view data.
-
- usSize Size of the view data.
-
- Comments
-
- Sets the view data for every view in trhe scene to the
- contents of pvData.
-
-
-
-
- void BackgroundYield(const char *szWrite=NULL);
-
- szWrite An optional string which is written to the
- status bar at the bottom of the screen.
-
- Comments
-
- If a tool has a lot of processing to perform which could
- take several seconds, even minutes, then somewhere in its
- processing loop it should call this function. This
- prevents the entire system being `locked up' during the
- processing. The optional string can be used to print a
- message to status bar to say for instance; "25% done".
- Notice how the CSG tools use this.
-
-
-
-
- Quick start to writing tools
-
- The following source file is provided as a templete to
- work from when creating new tools. Remember you must
- define a 16x15 pixel bitmap with an id of one in your
- resource file, and you must export _CREATETOOL and
- _DELETETOOL in the .def file (the functions are
- implemented by the IMPLEMENT_OBJECT macro).
-
- From then on simply uncomment any events you are
- interested in trapping. The whole of the Geometry, tool
- interface, maths and debug API's are available to you as
- well as the windows API.
-
- Finally put an entry in the Gened.ini file so the editor
- knows of the existence of your tool.
-
- /*-------------------------------------------------------
- --------------------
- ExampleTool
- -----------
-
- Example tool class
-
- (C) Silicon Dream Ltd 1995
-
- -------------------------------------------------------
- --------------------
-
- Changes: Date:
- * Created file 08/02/95
- */
-
- #include <tool.h>
-
- #include "resource.h"
-
- // YOU DO: Change the class name below to describe your
- tool and anywhere else
- // this class name is used in this file
- class ExampleTool: public Tool
- {
- private:
- // YOU DO: Declare your private variables here.
- eg.
- // Vec vecCursorPos;
- // (Non C++ users: 'private' means those
- // variables which have global scope from
- // within the functions you define here)
-
- // YOU DO: Uncomment any functions to trap
- events you're interested in
- // void _cppdyn Initialise(); //
- Called once when DLL loaded
- // void _cppdyn OnConfigure(); //
- Called to configure tool
- // Redraw _cppdyn OnSelect(Vec &vec); //
- Called when tool is selected
- // Redraw _cppdyn OnUnSelect(bool
- *pbOkToChange); // Called when another tool is
- selected
- // Redraw _cppdyn OnButtonDown(Vec &vec);
- // Called when button pressed
- // Redraw _cppdyn OnMouseMove(Vec &vec);
- // Called when mouse moves with button down
- // Redraw _cppdyn OnButtonUp(Vec &vec);
- // Called when button is released
- // Redraw _cppdyn OnSet(Vec &vec); //
- Called when the 'Set' button is clicked
- // Redraw _cppdyn OnUndo(); //
- Called when user wishes to undo effect of tool
- // Redraw _cppdyn OnDo(Vec &vec); //
- Called to end use of tool
- // void _cppdyn OnViewChange(HanCoorSys hcsys,
- Vec &vec); // Called when active view changes
- // void _cppdyn DrawSoFar(HDC hdc, HanCoorSys
- hcsys, void *pvViewData, bool bInvalid); // Called to
- draw object so far into the view
-
- public:
- _cppdyn ~ExampleTool() {};
- };
-
- IMPLEMENT_OBJECT(ExampleTool)
-
- // YOU DO: Uncomment and fill in any functions for events
- you want to trap.
- // (Non C++ users: If you create any functions of
- your own which need
- // to access your private variables (see above),
- you must make the
- // funtion part of your class by declaring it along
- with the other
- // functions (see above), and prefixing the
- function name with
- // 'classname::' in the implementation)
-
- /*
- void _cppdyn ExampleTool::Initialise()
- {
- }
- */
- /*
- void _cppdyn ExampleTool::OnConfigure()
- {
- }
- */
- /*
- Redraw _cppdyn ExampleTool::OnSelect(Vec &vec)
- {
- return REDRAW_NONE;
- }
- */
- /*
- Redraw _cppdyn ExampleTool::OnUnSelect(bool
- *pbOkToChange)
- {
- *pbOkToChange=TRUE;
- return REDRAW_NONE;
- }
- */
- /*
- Redraw _cppdyn ExampleTool::OnButtonDown(Vec &vec)
- {
- return REDRAW_NONE;
- }
- */
- /*
- Redraw _cppdyn ExampleTool::OnMouseMove(Vec &vec)
- {
- return REDRAW_NONE;
- }
- */
- /*
- Redraw _cppdyn ExampleTool::OnButtonUp(Vec &vec)
- {
- return REDRAW_NONE;
- }
- */
- /*
- Redraw _cppdyn ExampleTool::OnSet(Vec &vec)
- {
- return REDRAW_NONE;
- }
- */
- /*
- Redraw _cppdyn ExampleTool::OnUndo()
- {
- return REDRAW_NONE;
- }
- */
- /*
- Redraw _cppdyn ExampleTool::OnDo(Vec &vec)
- {
- return REDRAW_NONE;
- }
- */
- /*
- void _cppdyn ExampleTool::OnViewChange(HanCoorSys hcsys,
- Vec &vec)
- {
- }
- */
- /*
- void _cppdyn ExampleTool::DrawSoFar(HDC hdc, HanCoorSys
- hcsys, void *pvViewData, bool bInvalid)
- {
- }
- */
-
-
-
- Maths Library
- The maths library is implemented in a single DLL
- containing usefull functions and classes for manipulating
- graphical related objects such as vectors and matricies.
- Currently Geometry accepts parameters to its functions as
- C++ classes so the C version of the library is not really
- usefull for programming tools or applications. However
- eventually a C version of the API will also be included.
-
- This section is split into two, the first part describing
- the C support, the second describing the C++ support.
-
- To use the DLL functions and classes you must include
- either the `maths.h' include file (not to be confused
- with C's math.h), for C users, or `cppmaths.h' for C++
- users. Both must then link to `maths.lib'.
-
- The C++ class interface is built on top of the C maths
- library and provides no additional functionality that is
- not available in the C library, however the C++ version
- allows programs to be written which manipulate vectors
- and matricies using algebraic formula and are therefore
- easier to read. For instance;
-
- VectorA=VectorB+VectorC;
-
- is easier to understand than;
-
- MthAddVec(&VectorA, &VectorB, &VectorC);
-
- For C Users
-
- Not yet written
-
- For C++ Users
-
- The C++ support is probably best described in terms of
- the class definitions and examples of the operations
- available on those classes, rather than a function by
- function breakdown.
-
- Four types of class are available;
-
- Vec Implements a three element floating point
- cartesian coordinate (x, y and z).
- Lvec Implements a four element floating point
- cartesian coordinate (x, y, z and w). NB. Only
- an Lvec can be multiplied by a matrix as a
- matrix has four rows.
- Polar Implements a three element floating point
- polar coordinate (theta, phi and rho).
- Mat Implements a 4x4 floating point matrix.
-
-
-
- Vectors
-
- A vector can be used to store the position of a point in
- 3D space or alternitively a direction relative to another
- point. The following operations are defined for vectors;
-
- Vec vec(x, y, z) Initialise a vector up to
- three values
- Vec vecA(vecB) Initialise a vector with another
- vector
- Vec vec(lvec) Initialise a vector with a
- long vector (loses last component)
- ((Vec) lvec) Convert a long vector to a
- vector (loses last component)
- Vec vec(pol) Initialise a vector with a polar
- vector (conversion performed)
- ((Vec) pol) Convert a polar vector to a
- vector (conversion performed)
- vecA+vecB Add two vectors
- vecA-vecB Subtract a vector from another
- vec*f Multiply a vector by a
- scalar
- vec*mat Multiply a vector by a matrix
- vec/f Divide a vector by a scalar
- vecA+=vecB Add two vectors (overwrite
- original)
- vecA-=vecB Subtract a vector from
- another (overwrite original)
- vec*=f Multiply a vector by a
- scalar (overwrite original)
- vec*=mat Multiply a vector by a matrix
- (overwrite original)
- vec/=f Divide a vector by a scalar
- (overwrite original)
- -vec Returns the vector inverted
- vecA==vecB Are two vectors equal?
- vecA!=vecB Are two vectors not equal?
- vec.Set(x, y, z) Set a vector's components
- vec.X() Get x component
- vec.Y() Get y component
- vec.Z() Get z component
- vec.Len() Get length of vector
- vecA.Dot(vecB) Get dot product of two vectors
- vecA.Cross(vecB) Get cross product of two
- vectors
- vec.AddrVec() Gets address of Vector member
- (WARNING: Use only to interface
- to non C++ code)
-
-
-
- Long Vectors
-
- Long vectors are designed primarily to allow
- multiplication by matricies. The following operations are
- defined for long vectors;
-
- LVec lvec(x, y, z, w) Initialise a long vector
- with up to four values
- LVec lvecA(lvecB) Initialise a long vector
- with another long vector
- LVec lvec(vec) Initialise a long vector with a
- vector (last component becomes
- 1.0)
- ((LVec) vec) Convert a long vector to a
- vector (last component becomes
- 1.0)
- lvec*mat Multiply a long vector with a
- matrix
- lvec*=mat Multiply a long vector with a
- matrix (overwrite original)
- lvecA==lvecB Are two long vectors equal?
- lvecA!=lvecB Are two long vectors not
- equal?
- lvec.Set(x, y, z, w) Set a long vector's
- components
- lvec.X() Get x component
- lvec.Y() Get y component
- lvec.Z() Get z component
- lvec.W() Get w component (homogeneous
- coordinate)
- lvec.AddrLVec() Gets address of LongVec member
- (WARNING: Use only to interface
- to non C++ code)
-
- Polar Vectors
-
- The following operations are defined for polar vectors;
-
- Polar pol(t, p, r) Initialise a polar with up
- to three values
- Polar polA(polB) Initialise a polar with
- another polar
- Polar pol(vec) Initialise a polar with a vector
- (conversion performed)
- ((Polar) vec) Convert a vector to a polar
- (conversion performed)
- polA==polB Are two polars equal?
- polA!=polB Are two polars not equal?
- pol.Set(t, p, r) Set a polar's components
- pol.Theta() Get theta component
- pol.Phi() Get phi component
- pol.Rho() Get rho component
- pol.AddrVec() Gets address of Vector member
- (WARNING: Use only to interface
- to non C++ code)
-
-
-
- Matricies
-
- The following operations are defined for matricies;
-
-
- Mat mat Initialise a matrix with the
- identity matrix
- Mat matA(matB) Initialise a matrix with another
- matrix
- Mat mat(XROT, a) Initialise a matrix with a
- rotation or scale value (or
- leave it unset)
- Mat mat(TRANSL, vec) Initialise a matrix with a
- translation value (or leave it unset)
- Mat mat(vecOrigin, vecZAxis, vecYDir) Initialise a
- matrix by defining a new origin,
- a direction for the z axis, and
- given these constraints, a
- direction towards which the y
- axis will point.
- matA*matB Multiply two matricies
- matA*=matB Multiply two matricies
- (overwrite original)
- matA==matB Are two matricies equal?
- matA!=matB Are two matricies not equal?
- -mat Compute inverse of matrix (ie.
- when multiplied by this gives
- identity)
- mat.Set(f1,..f16) Sets elements of a matrix
- mat.MoveParent(vec) Moves coor sys defined by matrix
- relative to its parent
- mat.MoveChild(vec) Moves coor sys defined by matrix
- relative to itself
- mat.ScaleParent(x, y, z) Scale coor sys defined
- by matrix relative to its parent
- mat.ScaleChild(x, y, z) Scale coor sys defined by
- matrix relative to its own origin
- mat.XRotParent(a) Rotates coor sys defined by
- matrix about parents x axis
- mat.XRotChild(a) Rotates coor sys defined by
- matrix about its own x axis
- mat.YRotParent(a) Rotates coor sys defined by
- matrix about parents y axis
- mat.YRotChild(a) Rotates coor sys defined by
- matrix about its own y axis
- mat.ZRotParent(a) Rotates coor sys defined by
- matrix about parents z axis
- mat.ZRotChild(a) Rotates coor sys defined by
- matrix about its own z axis
- mat.ReverseX() Reverses direction of x axis of
- coor sys defined by matrix
- mat.ReverseY() Reverses direction of y axis of
- coor sys defined by matrix
- mat.ReverseZ() Reverses direction of z axis of
- coor sys defined by matrix
- mat.AddrMat() Gets address of Matrix member
- (WARNING: Use only to interface
- to non C++ code)
-
-
-
- Debug Library
- The debug library is not really part of Genesis but is a
- very helpful debuging aid wether you're writing tools,
- geometry engines, applications, in fact any code what so
- ever. It can be used in windows or non-windows programs,
- DLLs, C, or C++. What is more it presents you with just
- one set of memory management functions.
-
- Wether you are writing a simple C program, windows code
- or whatever you use debug's Malloc and Free functions
- (note the capitals letters to distinguish from C's memory
- functions). If using C++ you can use New and Delete
- (again with capitals). When your application or DLL
- terminates, a call to DebListMem will output to a file
- showing any memory which has been left unfreed, the size
- of the memory, the module and line it was allocated in
- and wether it was allocated with Malloc or New.
-
- If you're programming under windows the Malloc and New
- functions are not limited to allocating 64K segments.
-
- If writing C code simply include `debug.h' and C++ users
- should include `cppdebug.h'. In both cases you should
- define the _DEBUG macro, this can be done with /D _DEBUG
- on the compile line. The program must then be linked to
- debug.lib.
-
- The DebOut function can be used exactly like printf but
- will output to a file. Each line appearing in the debug
- output file is timestamped to within the accuracy of the
- system clock. What is more since the output is buffered
- into a 64K buffer it has practically zero impact on the
- performance of your application and so can be used to
- time `speed critical' parts of your code. When the buffer
- becomes full and the file has to be flushed to disk a
- line appears in the file saying that a flush happened at
- this point in case there is a discrepancy in the time
- stamps.
-
- The debug filename is set by the string passed on the
- very first call to DebOut. This string should contain a
- valid filename. Directly after the filename you can put a
- `+' character to indicate that the data should also be
- directed to an additional output stream. Under windows
- the additonal output stream will be the debug window, in
- a regular C program it will be the screen. Because many
- DLL's could all be printing on the additional output
- stream simultaneously the output can look confusing and
- the timestamps wont neccessarily be continuous.
-
- Here is an example run;
-
-
- DebOut("C:\app.deb+"); // Open debug
- file
- DebOut("Debug file has been opened");
- DebOut("Variable fLength is %f", fLength); //
- Output floating point variable
- pvoid1=Malloc(20); // Allocates 20 bytes
- pvoid2=Malloc(30); // Allocates 30 bytes
- pobj=New Obj; // Allocate a C++
- object called Obj
- DebOut(FLUSH); // Forces the debug file to
- be flushed to disk
- DebOut("More debug");
- DebListMem(); // List all unfreed
- memory to debug file
- DebOut("Closing file now");
- DebOut(STOP); // Flushes and closes
- the debug file
- Free(pvoid1); // Free memory...
- Free(pvoid2);
- Delete(pobj);
-
- The following output will be generated;
-
- 0.000: Debug file has been opened
- 0.000: Variable fLength is 5.75
- 0.000: --------: (Flushed)
- 0.030: More debug
- 0.030: Allocated memory dump:
- 0.033: Size | File | Line | Alloc type
- 0.033: ---------+--------------+-------+-------------
- -
- 0.033: 20 | app.c | 128 | Malloc
- 0.033: 30 | app.c | 129 | Malloc
- 0.033: 106 | app.c | 130 | New
- 0.040: Closing file now
-
-
- If your code is compiled without the _DEBUG macro defined
- then the memory allocation will not store the debugging
- information required by DebMemList. What is more the
- DebOut routine will not be included as part of your
- application and so calls to it should be enclosed in
- #ifdef's to prevent linker errors, eg;
-
- #ifdef _DEBUG
- DebOut("A line of debug");
- #endif
-
- Instances of debug library
-
- If you are building a large application consisting of
- many DLLs, and statically linked libraries, then it is
- sometimes not clear how many instances of the debug
- library you have. Basically whenever you use the linker
- and pass it the debug library's name, then you get an
- instance of the library. The upshot of this is that you
- cannot open a debug file in your application and expect
- one of your DLLs to write to the same file. Any DLLs your
- application use we're linked seperately and therefore
- have their own copy of the debug library. Therefore they
- should open their own debug file on the first call to
- DebOut. Statically linked libraries however are not
- linked independently and are therefore considered part of
- the application or DLL using it.
-
- Writing a Geometry engine
-
- Writing a Geometry engine is the simple process of
- writing a DLL whose interface conforms to the Geometry
- API specification and which maps those functions onto its
- own or a third party rendering engine or a hardware based
- interface.
-
- Of course there may be many differences between the new
- renderer and Genesis's Geometry engine. For instance the
- renderer might not have the concept of a coordinate
- system. However as long as it has the ability to move
- objects independently of one another then a coordinate
- system can be implemented in the DLL which hides the
- inadequecies of the renderer. It might also be that the
- renderer uses integer rather than floating point
- coordinates. Again this is easy to remedy, you could
- adopt the convention that floating point numbers in the
- range 0 to 100 get scaled to integer numbers 0 to 100,000
- meaning that floating point numbers with an effective
- resolution of 0.001 are supported. As long as the
- coordinates are converted back on any query function then
- a Geometry application will not know the difference.
-
-
- Errors
-
- The geometry.h file includes all of the standard geometry
- errors. If a particular error code is listed in the
- Geometry API spec as being returned from a particular
- function, for instance, DefPatch returns
- GERR_NOT_ON_PLANE if its points do not lie on a plane,
- then any Geometry engine must return the same error
- should the condition occur. This is because some
- applications may check for this specific return code and
- if it returns a more general error, such as
- GERR_INT_PROCESSING_ERROR then the behaviour of the
- application might change. The mark of a good Geometry
- engine is one whose applications work identically to the
- default.
-
- If an error occurs in the new engine which a standard
- error does not describe adaquetely then you can use
- GERR_INT_PROCESSING_ERROR (internal processing error) or
- define your own code whose value must be
- GERR_UNKNOWN_ERROR (defined in geometry.h) or greater.
- Such errors can have their own descriptions implemented
- in the engine's GetErrorText function.
-
-
- Handles
-
- All handles are defined as 32 bit unsigned integers. The
- geometry engine can use this value to mean whatever is
- most convenient. For instance the default Geometry stores
- a pointer to the appropriate object in this value. It can
- also be used as an index into an array, however, the
- value 0 cannot be used as this is reserved for the
- NULL_HANDLE, so any such arrays must be based at one.
-
- Handles do not have to be validated according to the
- spec. To perform proper validation on all handles at
- every call could be time cosuming, so if it is not
- quickly and easily achieved, then do not worry about
- implementing it. The onus is on the application and tool
- writers to get the handles right.
-
-
- Unsupported features
-
- If a Geometry engine does not support a particular
- feature say, bumped mapped textures, it should still
- accept DefSurfType calls defining bump mapped textures
- without returning a bad error. When rendered, the texture
- should just appear as a normal image mapped texture. What
- is more if the surface is queried with QrySurfType it
- should return a SurfType structure with the bump mapped
- flag set, otherwise as a particular model is saved and
- loaded into editors with different engines then the model
- will change. If it is loaded then saved again by an
- editor whose engine does not support bump mapping, and
- then the resulting file is loaded into an engine that
- does, the texture will have lost its `bumpy' quality.
- Likewise engines not supporting `curved' patches must
- still store the normal information.
-
-
- Helper library
-
- A library is provided which contains functions common to
- any Geometry engine thereby preventing any duplication of
- work on behalf of the programmer. The library includes;
-
- · Validating patches (checks all points lie on a plane
- etc.)
- · Splitting patches into smaller (possibly concave)
- patches
- · Computing patch normals
- · Computing normals for `autosmooth' patches
- · Loading and saving scenes
- · Loading bitmaps for textures
- · Providing text descriptions of Geometry errors
-
- If the Geometry engine is compiled with the _DEBUG macro
- defined then we must link to the debug version of the
- helper library genhelpd.lib. Otherwise we should link to
- the release version genhelp.lib. Notice there is no
- include file for the helper library, everything you need
- is defined in geometry.h.
-
-
- API's
-
- Any Geometry engine has at its disposal the whole of the
- maths, debug and helper APIs. It should not attempt to
- use the tool interface as there is no concept of tools in
- the Geometry engine. Tools are purely an invention of the
- editor application and the editor application should by
- no means be the only one that can use the Geometry API.
-
-
- GeomErr RegisterError (GeomErr gerrIn,
- char *szFNIn, ushort usLineIn);
-
- gerrIn Geometry error to register.
-
- szFNIn Filename of the module in which the error
- occurred
-
- usLineIn The line number within the module at which
- the error occurred.
-
- Comments
-
- Registers a Geometry error. If an error occurs somewhere
- within the Geometry engine, wether it is the result of
- the application passing in bad parameters (eg.
- GERR_INVALID_HANDLE), or due to circumstances beyond the
- apps control (eg. GERR_OUT_OF_MEMORY) then the error must
- be passed back to the the app. It is quite likely that
- the app will then call the GetErrorText function to see
- what went wrong and possibly to report the error to the
- user. If the Geometry engine registers the error with
- this routine before returning the error code then it
- gives the GetErrorText routine in the helper library the
- ability to build a more helpfull error string indicating
- where exactly the error occured.
-
- The Gerr() macro defined in geometry.h calls the
- RegisterError function without worrying about how to work
- out the module name and line number.
-
- The following example code shows the recommended way of
- returning errors;
-
- if (pmem==NULL)
- return Gerr(GERR_OUT_OF_MEMORY);
-
- If the app then passes the returned error to GetErrorText
- which in turn invokes the helper library function
- GetHlpErrorText, then the following text will be
- returned;
-
- Out of memory. Error occurred at line 850 in module
- geometry.cpp.
-
- If we returned the error without invoking the macro;
-
- if (pmem==NULL)
- return GERR_OUT_OF_MEMORY;
-
- then the following text will be returned from
- GetErrorText;
-
- Out of memory.
-
- Implementation specific errors with values above
- GERR_UNKNOWN_ERROR can also be registered.
-
-
-
-
- GeomErr GetHlpErrorText (GeomErr gerr,
- char *szBuff, ushort
- usBuffSize);
-
- gerr The error whose text is to be returned.
-
- szBuff Buffer to contain message.
-
- usBuffSize Size of the supplied buffer.
-
- Comments
-
- This function can be called from the Geometry engine's
- GetErrorText function. It supplies standard text
- descriptions for all of Geometry's errors. If an
- implmentation specific error is used (one with a value
- above GERR_UNKNOWN_ERROR) then the buffer will contain
- the following;
-
- `An implementation specific error occurred.
- Error was reported at line 850 in module
- geometry.cpp. Implementation interprets error
- as:'
-
- and GERR_UNKNOWN_ERROR will be returned. The GetErrorText
- function can then append its own implementation defined
- description of the error if there is space in the buffer.
- strlen can be used to find the length of the returned
- string. If the GetHlpErrorText function runs out of
- buffer space then it copies as much of the error text as
- possible and puts three period characters, `...' in the
- end of the buffer and returns GERR_BUFFER_TOO_SMALL.
-
-
-
-
- GeomErr ValidPatch (Vec *avec,
- ushort usNumVecs, ushort usFlags);
-
- avec A list of points to be used for the
- verticies.
-
- usNumVecs Number of points in avec.
-
- usFlags Flags used to idicate the kind of validity
- checks to perform;
-
- VP_CHECK_THIN_SEGMENT Checks that no `thin'
- segments appear in the patch
- outline. A thin segment is where
- part of the outline doubles back
- on itself at a 180 degree angle,
- forming an infinitely thin line
- rather than an area.
-
- VP_CHECK_ON_PLANE Checks that all the points lie
- on a plane or within a tolerence
- of the plane surface. The
- tolerence used is proportional
- to the size of the patch and is
- approximately 1/50th the
- greatest distance across any two
- points on the patch outline.
- This really only applies to
- patches with more 4 or more
- verticies.
-
- Comments
-
- Two checks are performed regardless of the flag setting,
- first that at least three points have been supplied, and
- secondly that no consequective points are coincident, ie
- are in exactly the same place.
- One check which is isn't performed is wether any line
- segments in the patch's outline cross over thereby making
- the ordering clockwise in one part and anticlockwise in
- the other. We also do not check for concave outlines as
- to some renderers a concave patch might well be a valid
- patch. To those that don't support concave patches the
- split function can be called to chop it up into smaller
- convex patches.
-
- In general this routine should not be called from
- DefPatch if the DP_DONT_VALIDATE flag is used in the call
- to DefPatch. This is because this call can be time
- consuming if many patches are being created, and if the
- application programmer is confident that no invalidate
- patches will be passed then DP_DONT_VALIDATE can speed
- things up.
-
-
-
-
- GeomErr ExtractVecs (HanObject hobj, ushort usType,
- Handle *ahan, ushort usNum,
- Vec **pavec);
-
- hobj Handle to object containing verticies.
-
- usType Are we extracting verticies or normals?
- Value can be EV_NORMS or EV_VERTS.
-
- ahan Array of handles to verticies or normals.
-
- usNum Number of handles in ahan array.
-
- pavec The address of a pointer to Vec. The
- pointer to the allocated memory holding
- the vectors is returned here.
-
- Comments
-
- This routine extracts the vectors from a list of
- verticies or normals using QryVertex or QryNormal
- respectively. A buffer is allocated to contain the
- vectors. This buffer must be freed by the calling code
- using the Free call.
-
- This routine is usefull for extracting vertex positions
- in order to pass to routines such as ValidPatch, Split
- and CompNormal.
-
-
-
-
- GeomErr CompNormal (Vec *avec, ushort usNumVecs,
- ushort usFlags, Vec *pvecNorm);
-
- avec Set of points to use for patch.
-
- usNumVecs Number of points in avec.
-
- usFlags Flags to specify the significance of the
- normal;
-
- CN_DIRECTION_IMPORTANT The normal will point to the
- side from which the points proceed
- in a clockwise direction. Also if
- we set this flag we must try and
- set the CONVEX flag (if we know
- for sure that the outline is
- convex) and the coordinate system
- type flag (appropriate to the
- coordinate system the points
- belong to).
-
- CN_CONVEX If we know for certain that the
- outline is convex, then we should
- set this flag as it can reduce the
- amount of processing this routine
- has to do. If
- CN_DIRECTION_IMPORTANT is not set
- then this is not important.
-
- CT_LEFTHAND If we know that this patch belongs
- to a lefthand coor sys then we
- should set this flag as it can
- reduce the amount of processing
- this routine has to do. If
- CN_DIRECTION_IMPORTANT is not set
- then this is not important.
-
- CT_RIGHTHAND If we know that this patch belongs
- to a righthand coor sys then we
- should set this flag as it can
- reduce the amount of processing
- this routine has to do. If
- CN_DIRECTION_IMPORTANT is not set
- then this is not important.
-
- pvecNorm A unit length normal vector is returned
- here.
-
- Comments
-
- Computes the normal of a set of points. No check is made
- to see if the points lie on a plane (use ValidPatch for
- this). If the CN_DIRECTION_IMPORTANT is set then a lot
- more processing is needed to work out which side the
- normal should be facing. This processing can be reduced
- by specifying as many of the other parameters as
- possible. Concave patches always need the full processing
- if CN_DIRECTION_IMPORTANT is set.
-
- If the patch outline contains some points very close
- together then this routine is selective in deciding which
- three points to use to generate the normal. This ensures
- we get an accurate a value as possible as the accuracy of
- this normal is crucial to the operation of some of the
- editors tools.
-
-
-
-
- GeomErr Split (Vec *avecMain, ushort usNumMainVecs,
- ushort usMaxPerPatch, ushort usFlags,
- ushort *pusNumSets, void **apvSets,
- ushort *ausNumInSets);
-
- avecMain Set of points to split up.
-
- usNumMainVecs Number of points in avecMain.
-
- usMaxPerPatch The maximum number verticies per patch
- that this Geometry engine will allow.
-
- usFlags Flags controlling the operation;
-
- SP_SUPPORT_CONCAVE Indicates wetherr the Geometry
- engine supports concave patch
- outlines.
-
- SP_RETURN_INDEX Rather than returning an array of
- vector arrays in (*apvSets)
- instead we return an array of
- ushort arrays, where each ushort
- is an index into the original set
- of points passed in.
-
- pusNumSets The number of sets returned, ie. the
- number of smaller outlines the main
- outline was split into.
-
- apvSets A pointer to an array of size
- (*pusNumSets) containing pointers to
- either arrays of vectorsor arrays of
- ushorts (if SP_RETURN_INDEX was given).
- Each of these arrays describes a set of
- points. If SP_RETURN_INDEX was specified
- than a variable declared; ushort
- **aausIndex, should be passed to apvSets,
- otherwise the variable should be; Vec
- **aavec; All arrays are allocated by this
- routine.
-
- ausNumInSet An array of ushorts indicating the size of
- the individual set arrays. For example
- ausNumInSet[2] contains the size of the
- array pointed to by apvSet[2]. In other
- words set 2 consists of elements
- apvSet[2][0] to
- apvSet[2][ausNumIntSet[2]].
-
- Comments
-
- This routine splits up an outline defined by a set of
- points into a number of sets. The sets can be expressed
- themselves as points or as indexes into the original
- array avecMain. The sets are allocated by this routine,
- but it is the responsibility of the calling code to Free
- the memory when it has finished with it.
-
- The following code fragment will free up all memory;
-
- for (us=usNumSets; us--;)
- Free(aausIndex[us]); // Free all
- sets
- Free(aausIndex); // Free
- array of pointers to sets
- Free(ausNumInSet); // Free array of
- sizes of sets
-
- Although we can pass in any number for usMaxPerPatch, in
- practice the sets produced will not contain more than 4
- points each, although these can be concave if
- SP_SUPPORT_CONCAVE is set.
-
-
-
-
- GeomErr Autosmooth (HanObject hobj, HanVertex *ahver,
- ushort usNumVerts, Vec &vecNorm,
- ushort usFlags, HanSurf hsur,
- float fSmoothAng, HanNormal *ahnor,
- ASUndoBuff *pasub);
-
- hobj Handle to object to add `autosmoothed'
- patch too.
-
- ahver Array of vertex handles defining the
- patch.
-
- usNumVerts Number of handles in ahver. Also specifies
- the size of the ahnor buffer.
-
- vecNorm The normal of the patch to be
- `autosmoothed'. The normal should point to
- the empty side of the patch.
-
- usFlags Flags controlling the operation;
-
- DP_SMOOTH_BY_SURFThis patch is to be smoothed only
- with neighbouring patches which have
- the same surface type.
-
- DP_SMOOTH_BY_ANGLE This patch is to be smoothed
- only with neighbouring patches which
- form an angle less than fSmoothAng
- with this patch.
-
- hsur Surface type of the `autosmoothed' patch.
-
- fSmoothAng Specifies autosmooth angle threshold if
- DP_SMOOTH_BY_ANGLE is set.
-
- ahnor An array of handles to normals returned.
-
- pasub Pointer to an autosmooth undo buffer. If
- the geometry engine wishes to abort this
- operation it can pass this to the UndoAS
- routine to undo any changes made. If not
- it must pass it to the ComitAS.
-
- Comments
-
- Given an array of vertex handles defining a new patch,
- this routine can determine the set of normals to use to
- get this patch to appear smooth given the criteria
- defined in usFlags. It does this by looking at the
- surrounding patches and averaging out the surface normals
- of the patches to create the normals. If normals already
- exist at these points they are modified, otherwise new
- ones are created. The set of normals to use in defining
- the patch is passed back in the ahnor parameter. The
- returned pointer pasub should be passed either to UndoAS
- or to CommitAS if the patch creation succeeded.
-
-
-
-
- GeomErr CommitAS (ASUndoBuff *pasub);
-
- pasub Pointer to the autosmooth undo buffer.
-
- Comments
-
- Commits the changes made to the normals by the Autosmooth
- function. Either this or UndoAS must be called at some
- point after an Autosmooth call.
-
-
-
-
- GeomErr UndoAS (ASUndoBuff *pasub);
-
- pasub Pointer to the autosmooth undo buffer.
-
- Comments
-
- Undoes the changes made to the normals by the Autosmooth
- function. Either this or CommitAS must be called at some
- point after an Autosmooth call.
-
-
-
-
- GeomErr LoadBmp (char *szFN,
- BITMAPINFO huge **ppbmi);
-
- szFN The name of a .bmp file to open.
-
- ppbmi The address of a pointer to a bitmap which
- will be returned after the bitmap is
- loaded. The memory is allocated by this
- routine.
-
- Comments
-
- Loads the bitmap with the specified name. The correct
- amount of memory is automatically allocated and a pointer
- to it is returned in (*ppbmi). The calling code must free
- the memory using the Free call. If the bitmap does not
- exist then GERR_BITMAP_FILE_NOT_FOUND is returned. If the
- file has an incorrect format GERR_NOT_A_BMP_FILE is
- returned.
-
-
-
-
- GeomErr SaveSceneHlp (HFILE hfile, HanCoorSys hcsys,
- ulong *pulNumCSys,
- HanCoorSys *ahcsys,
- ulong *pulNumObjs,
- HanObject *ahobj);
- hfile Windows handle of the file to save too.
-
- hcsys Handle of the coordinate system to save.
-
- pulNumCSys Size of ahcsys (in number of handles). On
- return holds the total number of
- coordinate systems saved.
-
- ahcsys An array of handles to coordinate systems
- saved.
-
- pulNumObjs Size of ahobj (in number of handles). On
- return holds the total number of objects
- saved.
-
- ahobj An array of handles to objects saved.
-
- Comments
-
- This function takes exectly the same parameters as
- Geometry's SaveScene function, so the implementation of
- this routine is nothing more than calling this helper
- routine.
-
-
-
-
- GeomErr LoadSceneHlp (HFILE hfile, HanCoorSys csysParent,
- Char *szTexPath,
- ulong *pulNumCSys,
- HanCoorSys *ahcsys,
- ulong *pulNumObjs,
- HanObject *ahobj);
-
- hfile Windows handle of the file to load from.
-
- hcsysParent Handle of the coordinate system which will
- be the parent of the one being loaded.
-
- szTexPath A pointer to a path specification for
- where to search for texture bitmaps if
- they are not found in the current working
- directory. This would typically be set to
- the directory where the model file is, or
- else a special texture directory. It must
- have terminating back slash eg;
- "c:\textures\" or else be a null string.
- The pointer cannot be NULL.
-
- pulNumCSys Size of ahcsys (in number of handles). On
- return holds the total number of
- coordinate systems loaded.
-
- ahcsys An array of handles to coordinate systems
- loaded.
-
- pulNumObjs Size of ahobj (in number of handles). On
- return holds the total number of objects
- loaded.
-
- ahobj An array of handles to objects loaded.
-
- Comments
-
- This function takes exectly the same parameters as
- Geometry's LoadScene function, so the implementation of
- this routine is nothing more than calling this helper
- routine.
-