development of a system to create smooth 3d …mdv/courses/cm30082/projects... · development of a...

101
DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted by Michael Ball for the degree of BSc (Hons) Computer Science 2006

Upload: dangkiet

Post on 28-Mar-2018

217 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

DEVELOPMENT OF A SYSTEM TO

CREATE SMOOTH 3D COMPUTER

MODELS USING LEGO BUILDING

BLOCKS

Submitted by Michael Ballfor the degree of

BSc (Hons) Computer Science2006

Page 2: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3DCOMPUTER MODELS USING LEGO BUILDING BLOCKS

Submitted by Michael Ball

COPYRIGHT

Attention is drawn to the fact that copyright of this dissertation rests with itsauthor. The Intellectual Property Rights of the products produced as part of theproject belong to the University of Bath(see http://www.bath.ac.uk/ordinances/#intelprop).

This copy of the dissertation has been supplied on condition that anyone who con-sults it is understood to recognise that its copyright rests with its author and that noquotation from the dissertation and no information derived from it may be publishedwithout the prior written consent of the author.

Declaration

This dissertation is submitted to the University of Bath in accordance with therequirements of the degree of Bachelor of Science in the Department of ComputerScience. No portion of the work in this dissertation has been submitted in supportof an application for any other degree or qualification of this or any other universityor institution of learning. Except where specifically acknowledged, it is the work ofthe author.

Signed...........................(Michael Ball)

This dissertation may be made available for consultation within the University Li-brary and may be photocopied or lent to other libraries for the purposes of consul-tation.

Signed...........................(Michael Ball)

ii

Page 3: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Abstract

There are many applications available to people creating 3-dimensional objects how-ever most are not easy for beginners to use, and depending on their complexity cantake many months to fully understand. In their most simple form these applica-tions provide the user with basic objects such as a cube, sphere, pyramid, and conewhich the user manipulates to create their desired object. A different method is toprovide the user with a ‘real world’ approach to building objects, such as that ofusing LEGO1 style bricks. Most people will at sometime have come into contactwith LEGO, or other similar building blocks, and they can relate this knowledge toa computer application providing a simulation of LEGO construction. LEGO canonly provide a ‘blocky’ representation of the modelled object, but smoothing couldbe applied to this LEGO structure to create a better representation of the modelledobject and to remove the ‘blocky’ appearance. This project looks into methods ofsmoothing LEGO structures, it examines the processes required to prepare a LEGOstructure for smoothing as well as the different smoothing methods that could beapplied.

1LEGO is a trademark of the LEGO Group

iii

Page 4: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Acknowledgements

Thank you to the late James Jessiman who in 1995 developed the LDraw file for-mat making the simulation of LEGO possible, and for projects such as this to beconsidered, and to my Supervisor, Prof Phil Willis.

iv

Page 5: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Contents

1 Introduction 1

2 Literature Review 32.1 Identification of the Project Areas . . . . . . . . . . . . . . . . . . . 32.2 Computer Simulation of LEGO . . . . . . . . . . . . . . . . . . . . . 32.3 The LDraw File Format . . . . . . . . . . . . . . . . . . . . . . . . . 42.4 The DirectX File Format . . . . . . . . . . . . . . . . . . . . . . . . 42.5 Smoothing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.5.1 Stud Removal . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.5.2 Smoothing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2.6 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3 Analysis 83.1 Loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2 Internal Representation . . . . . . . . . . . . . . . . . . . . . . . . . 83.3 Rendering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.4 Conversion To Mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.5 Smoothing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.6 Output to the DirectX File Format . . . . . . . . . . . . . . . . . . . 9

4 Requirements Specification 104.1 Functional Requirements . . . . . . . . . . . . . . . . . . . . . . . . . 104.2 Non-Functional Requirements . . . . . . . . . . . . . . . . . . . . . . 11

5 Design and Implementation 125.1 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

5.1.1 Language Choice . . . . . . . . . . . . . . . . . . . . . . . . . 125.1.2 User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . 125.1.3 Internal Representation . . . . . . . . . . . . . . . . . . . . . 135.1.4 Program Flow Diagram . . . . . . . . . . . . . . . . . . . . . 14

5.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145.2.1 Parsing LDraw Files . . . . . . . . . . . . . . . . . . . . . . . 155.2.2 Applying the Transformation Matrices . . . . . . . . . . . . . 155.2.3 Rendering the LEGO Object . . . . . . . . . . . . . . . . . . 165.2.4 Converting the LEGO Object to a Mesh . . . . . . . . . . . . 175.2.5 Smoothing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185.2.6 DirectX File Output . . . . . . . . . . . . . . . . . . . . . . . 25

6 Testing 266.1 Testing of Requirements . . . . . . . . . . . . . . . . . . . . . . . . . 26

v

Page 6: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

6.1.1 Functional Requirements . . . . . . . . . . . . . . . . . . . . 266.1.2 Non-Functional Requirements . . . . . . . . . . . . . . . . . . 28

6.2 Testing the Smoothing Methods . . . . . . . . . . . . . . . . . . . . . 286.2.1 Definition Of Smooth . . . . . . . . . . . . . . . . . . . . . . 286.2.2 Laplacian Smoothing . . . . . . . . . . . . . . . . . . . . . . . 306.2.3 Taubin’s Surface Fairing . . . . . . . . . . . . . . . . . . . . . 306.2.4 Loop’s Masking . . . . . . . . . . . . . . . . . . . . . . . . . . 30

6.3 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

7 Critical Evaluation 347.1 File Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347.2 The Mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347.3 Smoothing Extensibility . . . . . . . . . . . . . . . . . . . . . . . . . 347.4 Smoothing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

8 Further Work 36

9 Conclusion 37

Bibliography 38

A File Formats 40A.1 LDraw File Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40A.2 DirectX File Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

B Part Structures 50

C Overlap Resolving Images 52

D Code Listing 54D.1 Common.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54D.2 datReader.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57D.3 Form1.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60D.4 ListRenderer.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63D.5 ModelDefs.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66D.6 OpenGLViewer.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69D.7 Renderer.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71D.8 Smoother.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72D.9 SurfaceFinder.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77D.10 Transformer.vb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

vi

Page 7: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

List of Figures

2.1 Subdivision of Quadrilateral . . . . . . . . . . . . . . . . . . . . . . . 52.2 Neighbourhood Structure (adapted from [15]) . . . . . . . . . . . . . 6

5.1 Interface Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135.2 Flow Diagram of System . . . . . . . . . . . . . . . . . . . . . . . . . 145.3 Traversal of Internal Representation During . . . . . . . . . . . . . . 165.4 First Smoothing Output . . . . . . . . . . . . . . . . . . . . . . . . . 205.5 Example of Subdivison . . . . . . . . . . . . . . . . . . . . . . . . . . 215.6 Smoothing with Subdivison . . . . . . . . . . . . . . . . . . . . . . . 215.7 Example of the Pinching Effect . . . . . . . . . . . . . . . . . . . . . 225.8 Isolated Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235.9 Smoothing Applied after Overlapping Quadrilaterals are Resolved . 25

6.1 Test Results for Requirement 4 . . . . . . . . . . . . . . . . . . . . . 276.2 LEGO Pyramid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296.3 Square Pyramid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296.4 Black Triangle Showing the Desired ‘Smooth’ Result . . . . . . . . . 296.5 Test 1: Laplacian Smoothing of the Pyramid LEGO Object . . . . . 306.6 Test 2: Taubin’s Surface Fairing of the Pyramid LEGO Object . . . 316.7 Test 3: Loop’s Masking of the Pyramid LEGO Object . . . . . . . . 316.8 Test 3: Loop’s Masking of the Pyramid LEGO Object - Top View . 326.9 Gaps Created in the Mesh During Smoothing . . . . . . . . . . . . . 32

7.1 Parts Rendered with the Wrong Vertex Ordering . . . . . . . . . . . 35

C.1 Overlap Resolving for External Vertices and Line Intersections . . . 52C.2 Overlap Resolving for External Vertices and Intersections . . . . . . 52C.3 Overlap Resolving for Internal Vertices . . . . . . . . . . . . . . . . . 53

vii

Page 8: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 1

Introduction

There exists many methods of constructing 3-Dimensional objects using computers.When very accurate and technical objects, models, or buildings are being designedCAD (Computer Aided Design) systems are used. They allow the user to inputvery accurate measurements, and provide them with a preview of the planned item.These systems are generally very complex to use, can provide too much detail, andtake months of training to learn. Modern computer games also require 3D objects,these differ from the very accurate models CAD systems create for they need to berelatively small in the amount of detail they hold so as to be renderable in real time.

This project focuses more on the area of low detailed objects which would mostoften be used in real time rendering applications, such as games. The most commonway to create these objects is to start with some basic objects, a cube, sphere, pyra-mid and cone, and to manipulate these objects by applying different transformationsand object comparisons so as to create the desired object. This method works well,but is not that intuitive to new users.

Developments in game creation programming languages have given amateur andhobbyist game writers the ability to create 3D games through simplified languagesor point and click style interfaces. However they do not provide a method of creatingobjects, so the user is left having to use the limited supplied selection of objects, orlearn how to use one of the object creation systems.

In this project a different approach to object construction is examined. Most peoplehave at sometime come into contact with LEGO or other similar building blocks,and the concept of connecting these bricks together to create objects is relativelysimple. A method of creating objects could therefore be through a LEGO stylesimulator. This brings about its own problems, while the construction would nowbe relativity simple, the constructed objects will show LEGO characteristics, mostobviously the exposed studs, but also the ‘blocky’ effect LEGO objects have. Thesecharacteristics would give the objects a very limited usefulness.

This project addresses ways of making these objects more useful, it looks at theremoval of the most obvious LEGO characteristic, the studs, it then goes on to ad-dress the ‘blocky’ look of the objects by examining different methods of smoothingthem. The project looks at how to take a LEGO object, defined in a certain struc-ture, and prepare them for being smoothed, it then goes on to address problems

1

Page 9: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

found during these processes.

This project does not look at the actual construction of the LEGO models, asmany LEGO simulator systems already exist, some of which are examined in theLiterature review. Aswell as existing systems, existing file formats for the storageof LEGO objects are also examined.

The dissertation is organised as follows; The literature review which examines dif-ferent LEGO simulators, LEGO file formats, and methods of removing the LEGOcharacteristics from the model. The analysis section examines the research findings,and specifies the direction the project should follow. The requirements are specifiedfrom the analysis and are found in the requirements section. Then follows a detailedexplanation of the implementation, describing findings, and problems experienced,along with methods carried out to fix these problems. The testing demonstrateswhether the project has met its requirements, and looks at the results of differentsmoothing methods. The project is evaluated in the critical evaluation and the di-rections the project could be extended towards are explained in the further worksection. The conclusion draws the project to a close and specifies if the project wasa success at showing LEGO blocks as a feasible method for 3D object construction.

2

Page 10: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 2

Literature Review

2.1 Identification of the Project Areas

Here we outline how the literature review is structured. The project is ultimatelyabout smoothing LEGO objects, and this will take numerous steps. The first ofthese to be examined are the methods of loading a LEGO object into the projectsapplication, and then once smoothed how to store it so it can be used by otherapplications. The easiest method of getting the object in to the application will beto support a file format in which LEGO objects are already stored. Research intoexisting LEGO simulators is needed to identify the most common, or most suitablefile format available. Once smoothed the object will again need to be stored. It ispresumable a LEGO file format will not be suitable, as a smoothed object will notcontain the same type of characteristics as a LEGO object. There are many 3D fileformats available, however a choice is made to use DirectX as it is well supportedand not application specific. After these areas have been examined the literaturereview moves onto examine different methods of smoothing the LEGO object.

2.2 Computer Simulation of LEGO

While this project is not focused on the actual method of simulating LEGO, it willbe necessary to connect with simulators already in existence. The simplest methodwill be to support the same file format as another simulator. We therefore haveto examine different LEGO simulators and select a file format which is either mostsupported, or best documented, preferably both will be true.

A sensible place to start looking for LEGO simulators is LEGO themselves andthey have produced LEGO Digital Designer [2] a system created using Qube soft-ware1. The simulator has a game feel to it, and supports brick snapping allowingthe bricks to be connected by the studs as with real LEGO. It uses LEGO’s ownfile format (.lxf) which was previously used by LEGO CAD for the developmentof LEGO Mindstorm robotics. The .lxf file is a package of three files; a thumbnailpreview of the object, an XML file specifying which bricks are used along with thecamera and object orientation when it was saved, and a .MODEL binary file. TheXML file only identifies which bricks are being used and their orientation, the actualbrick data describing its shape are stored in binary files within the LEGO Digital

1Q Technology’s generic game and interactive 3D creation package. [3]

3

Page 11: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Designers installation folders. With the data being stored in binary files it will bedifficult to use this file format within the project, especially as there appears to beno publicly available documentation on the file format.

There are many other LEGO simulators which do not need to be individually listedhere as this project is not concerned with the actually simulators, but with the fileformat they support. All of the other simulators that were found support a fileformat created by the LDraw Organisation. [6]. The organisations website providesa list of some of these simulators [7].

2.3 The LDraw File Format

The LDraw organisation was started in 1995 [6], and provide a completely unofficial,community run free CAD system, along with an extensive database of official partsproduced by the LEGO company. It is the LDraw representation of the officialparts (bricks) which are used in most of the LEGO simulation packages. LDrawworks on a community system whereby members submit parts, and then LDraw’sadministrators validate them to check they comply to the LDraw file format, and area valid real LEGO brick. The file format used to store these parts is fully documented(see A.1). Each brick normally consists of multiple parts, and is referenced in ahierarchial structure, whereby one part file may reference another which referencesanother and so on. The referenced parts are not always complete bricks but morelikely a simple structure, such as a box. These are generally created at unit scale,i.e. the maximum length of a side is 1 unit, and are transformed to the desired scalewhen used.

2.4 The DirectX File Format

While this project is focused on loading a LEGO object and then smoothing it, themain aim is to prove that a method of constructing useable 3D objects via a buildingblock system is feasible. For this to be the case the smoothed object will need tobe compatible with other applications. The LEGO file format will no longer be ofuse as it can not represent a smooth object, and while being compatible with manyLEGO simulators it does not stretch into other less specialised applications. A moreuniversally compatible file format supported by many applications, at least thoserunning under a version of Microsoft Windows, is DirectX (.x). The file format iswell documented (see A.2) and is architecturally and contextually free [11]. Allowingit to be an excellent candidate for the output of the smoothed object. DirectX ismore than just a file format, and covers a large area of multimedia from 3D models,to video, music, and real time animation. However for this project we are onlyconcerned with its use as a 3D object file format.

2.5 Smoothing

This can be split into two areas. The removal of the studs, and the smoothing ofthe LEGO object as a whole.

4

Page 12: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 2.1: Subdivision of QuadrilateralMethod of subdividing a quadrilateral into triangles. Firstly divides into two

triangles. These in turn are split into four triangles. Each of these can then besplit into four more triangles and so on for the desired number of subdivisions

2.5.1 Stud Removal

From the research into the LDraw file format (see A.1), stud removal has become areasonably trivial problem of disregarding part files containing the word ‘stud’.

2.5.2 Smoothing

A lot of research has been carried out in the past examining different smoothingmethods and approaches, each with their own merits. Most of these approacheshave then seen further research carried out on them with further approaches beingcreated. This project is not about examining smoothing techniques and then en-hancing them, but more about applying these techniques to the problem of ‘blocky’LEGO objects, and proving its possible to smooth them. From carrying out initialresearch into different smoothing techniques it appears smoothing is used for noisereduction or removal from 2D images, or 3D objects. For the purpose of this projectthe ‘blocky’ steps of a LEGO object are noise from the smooth shape which it isrepresenting.

The LEGO object loaded from the LDraw format will consist of a very simplis-tic quadrilateral mesh, and will only provided a limited number of data points forthe smoothing techniques which could cause problems. To increase the number ofdata points a method of subdivision will need to be applied to the mesh. Subdivisioncan be used to divide the mesh into quadrilaterals or triangles, the most commonlyused in meshes are triangles. The original quadrilateral can be split in half to createtwo triangles, this is a preliminary step. Each triangle can then be split into 4 newtriangles by cutting the edges of the original triangle in half and then connectingthem together as shown in Figure 2.1. This step can be carried out as many timesas required.

Once subdivided the mesh will be able to have smoothing effects applied to it. Oneof the simplest and most used methods of smoothing is Laplacian smoothing [13].Laplacian smoothing examines each vertex individually, and uses a vertex neighbour-hood to adjust the examined vertex. The neighbourhood consists of all the verticesthe examined vertex is connected to by edges, see Figure 2.2. The examined vertexis then moved to the mean average location of all vertices in the neighbourhood, asdescribed by the equation 2.1

5

Page 13: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 2.2: Neighbourhood Structure (adapted from [15])

v′i =∑

j∈i∗(vi)n

(2.1)

Where vi is the vertex being repositioned, i* its neighbourhood, and n the numberof vertices within its neighbourhood.

Due to Laplacian smoothing being so simplistic many people have created optimisa-tions and improvements to this method. Taubin’s smoothing scheme [15] attempts tofix a problem Laplacian, and many other methods suffer, which is that of shrinkage.Due to the underlying Laplacian method being an averaging process the model willultimately be shrunk to its origin. Halstead, Kass, and DeRose [1] attempt to solvethis problem by calculating how much the mesh will shrink during a smoothing step,and to enlarge it by that amount before applying the smoothing. This does fix theshrinking problem, however leads to exaggerated curvatures in the mesh. Taubin’sapproach uses Guassian smoothing, which replaces the Laplacian method, in thatwhile the neighbourhood of vertices is still used, each vertex in the neighbourhoodhas a weighting applied to it depending on how many neighbours are in its neigh-bourhood, and/or its distance from each neighbour. The Guassian smoothing stillsuffers from the shrinking problem. Taubin attempts to counteract this problem byapplying the smoothing process twice. The first time with a positive scaler appliedgenerating the smoother, but shrunk mesh. The second time with a negative scalerapplied, this enlarges the mesh again, but is still applying smoothing. The positivescaler is known as λ, and the negative as µ, and they are related such that 0<λ<1and µ+λ<0. The equation as defined by Taubin for the new position of each vertexin the mesh is:

v′i = vi + {λ, µ}∑

j∈i∗wij(vj − vi) (2.2)

Where vi is the vertex being repositioned, i* its neighbourhood, and wij the weight-ing applied to each of the vertices, vj in that neighbourhood.

Both these methods have looked at smoothing the mesh once the subdivisions havebeen calculated. Loop’s masking applies smoothing after each subdivision iteration

6

Page 14: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

[9]. The subdivision is carried out as already explained, but at the end of each iter-ation all the vertices are repositioned. The method is still based on the Laplacianmethod, but again with the use of weighting as with Taubin’s method, however thereis no attempt made to counteract the shrinking problem. Again a neighbourhood ofvertices is used, and the equation for positioning the vertices shown below, as takenfrom [10].

v′ =α(n)v +

∑j∈i∗ vi

α(n) + n(2.3)

whereα(n) =

n(1− β(n))β(n)

(2.4)

where

β(n) =54− (3 + 2 cos(2Π/n))2

32(2.5)

where vi is the vertex being repositioned, i* its neighbourhood, and n the numberof vertices in the neighbourhood. α and β are a weighting algorithm applied to themean average vertex found from the vertices in the neighbourhood.

There are other methods of smoothing which try to reduce the shrinking effectsuch as a method of smoothing the mesh towards the shape of a sphere, which isbased upon Gaussian functions [4]. One of the prerequisites of this technique is tohave an object which is already ‘sphere like’, the example given is a CT scan of ahuman head. With LEGO objects this prerequisite can not be guaranteed and thismethod would be unlikely to give satisfactory results.

2.6 Conclusion

From the research carried out it has become apparent as to how to connect withexisting LEGO simulators through the support of the LDraw file format. Using theformat has also provided a simple method of removing the stud characteristic fromthe objects. The removal of the ‘blocky’ shape is therefore the area this project willinvestigate in more detail. It will use the researched smoothing techniques as itsbasis. These methods have been designed to remove noise, and it is yet to be seenif the ‘blocky’ appearance of LEGO falls into this category, however this projecthopes to show that it does, and that either one of these methods or some adaptionof theses methods may be useable to smooth LEGO objects.

7

Page 15: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 3

Analysis

This project can be split into six different sections; loading, internal representation,rendering, conversion to mesh, smoothing, and finally output in the DirectX fileformat.

3.1 Loading

The system will need to be capable of loading LEGO objects created in existingsimulators as the system will not provide a method of generating objects itself. Fromthe research of exisiting simulators described in the literature review the LDraw fileformat is not only the most utilised format but also a well documented and plaintext format. The shapes are described in terms of quadrilaterals and triangles, eachof which can easily be joined to construct a mesh representation of the LEGO objectrequired for smoothing.

3.2 Internal Representation

The system will need to be capable of holding the loaded LEGO object in an internalstructure. This structure needs to be generic enough to support many different fea-tures. Firstly it needs to be quick to populate during the loading procedure. It mustsupport the hierarchal structure given by the LDraw file format, allowing for studparts to be easily removed. The stud parts are made up from many different parts,each made from other different parts. To fully remove a stud it must be identifiableat the top level, and then all parts linked from it can be removed or ignored whenrendering and converting to the mesh form. The internal representation must alsobe capable of supporting the mesh representation of the object, this is so only oneinternal representation, rendering procedure are required.

3.3 Rendering

Once loaded the system will need to render the LEGO object. This will be doneusing OpenGL. OpenGL supports both quadrilateral and triangle shapes, these aredefined by their vertices as they are in the LDraw file format. Some care willneed to be taken as OpenGL supports back face culling and uses vertex ordering todetermine the front and back of the defined shapes. For OpenGL the front of a shapeis viewable when the vertices are ordered counter-clockwise, the LDraw file format

8

Page 16: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

originally did not support vertex ordering, but since the rise in 3D renders and theconcept of vertex ordering, meta-commands have been added to the file format tospecify whether the parts are defined in clockwise or counter-clockwise ordering. Forshapes defined as clockwise they will need to be re-ordered before rendering can takeplace. The LDraw format also supports inverting referenced parts and this conceptalso needs to be catered for in the rendering, and internal structure. The rendereris also required to render the mesh structure, this should not require a differentapproach if the internal structure can support both forms, and hide the differencefrom the renderer.

3.4 Conversion To Mesh

Before smoothing can be applied the LEGO object needs to be described in terms ofa mesh rather than individual shapes. The smoothing methods require a neighbour-hood of vertices for each vertex that is being adjusted and this structure can onlybe created once the object is defined as a single mesh. The easiest method will beto still use the quadrilateral and triangle shapes to define the mesh. (The methodsresearched only require the use of a triangular mesh, but different approaches mayrequire the use of quadrilateral meshes). The vertices where these shapes meet willneed to be the same object1 within the internal structure so when an adjustment ismade to each vertex it will adjust all shapes connecting at that vertex.

3.5 Smoothing

The system will need to apply certain smoothing algorithms to the mesh structurecreated from the LEGO object. This project is investigating different smoothingapproaches in its attempt to find a suitable method to removed the ‘blocky’ appear-ance of the object. To begin the three methods of smoothing researched will beapplied and their results examined, once these originals tests have been carried out,any problems which affect all the methods will be examined and solutions produced.Once these are dealt with and if none of the smoothing methods produce the desiredeffect then they will be examined and improvements discussed, if not implemented.The smoothing part of the system will need to be easily extendable so changed ornew smoothing methods can be added for testing and evaluation.

3.6 Output to the DirectX File Format

The system will need to output the smoothed object so other applications can makeuse of them. A very commonly supported file format in most 3D applications, andgaming languages, at least on Microsoft Windows, is the Microsoft DirectX fileformat. It is capable of storing triangles which makes it very suitable for storingthe mesh representation of the smoothed LEGO object as this will be defined by anarray of triangles.

1By ‘the same object’ it is meant the actual structure or object used to store the vertex shouldbe the same, and not just a copy that contains the same values

9

Page 17: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 4

Requirements Specification

Here the formal requirements of the project are drawn up, they are split into twosections functional and non-functional. As stated by Sommerville [14] functionalrequirements are statements of services the system should provided, along with howit should behave to particular situations and inputs. Non-functional requirementsare constraints on the services of functions offered by the system, such as timingconstraints.

4.1 Functional Requirements

1. The system must load LEGO objects stored in the LDraw file format.

2. The system must store the loaded model in an internal structure that is adapt-able enough to hold the LEGO data, and mesh structure.

3. The system must be able to convert from the LEGO format into a meshstructure.

4. The system must be capable of rendering the unchanged LEGO object, andthe smoothed mesh structure.

5. The system must allow the user to rotate and zoom the view so as to be ableto fully examine the rendered objects. Wireframe, and other similar optionswould be helpful.

6. The system must remove the stud characteristics from the LEGO object.

7. The system must demonstrate the effects of different smoothing methods.

8. The system must be able to apply different smoothing techniques to the orig-inal model without having to reload the model each time.

9. The system must be easily extendable to allow different smoothing methodsto be added.

10. The system must be able to save the smoothed mesh structure in the DirectXfile format so as to be useable by other applications.

10

Page 18: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

4.2 Non-Functional Requirements

11. The system should be able to load models within an acceptable duration.

12. The system should provide an easy method of selecting the different smoothingoperations.

11

Page 19: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 5

Design and Implementation

5.1 Design

This section outlines the high level design of the system, describing the followingitems; why the language used to develop the system was chosen, details about theuser interface, the internal representation which shall be used for the LEGO andmesh structures, and finally a flow diagram describing the structure of the system.

5.1.1 Language Choice

The system will be written in VB.NET. This language has been chosen for thefollowing reasons; firstly the author has industry level knowledge and experienceof this language allowing the development of the system to be relatively quick asthere will be no time required in learning the langauge. This system requires a largeamount of ground work in the form of file parser, renderer and mesh creation beforethe project part can be implemented, and with the relative short time scale quickdevelopment is a necessity. Other reasons supporting the choice of language is thatit supports objects which will be useful for the internal representation (see 5.1.3),and through a wrapper OpenGL is easily available. VB.NET can only run what isknown as managed code, the OpenGL dynamic linked library is not managed codeand the wrapper is used to simply make the functionality in OpenGL.DLL availableto VB.NET. The wrapper used is called CSGL (C# Graphics Library) [8], C# andVB.NET are essentially the same language compiling to the same byte code, andthis wrapper can be used by both. Other languages such as C++ would probablybe capable of faster computing for the smoothing algorithms and is able to connectdirectly to the OpenGL.dll, along with providing objects and so could be seen as abetter candidate, but the speed of development as already mentioned is crucial andso the choice of using VB.NET is made.

5.1.2 User Interface

The system only requires a basic user interface. It needs to allow the user to rotateand zoom in on the rendered LEGO Object, this will be done through mouse inputs.It needs to allow the user to select the LDraw file to load, this will be done byeither dragging the file onto the render window, or selecting the file in a standardWindows file selection box. The interface should provide the user with the abilityto select certain options such as the smoothing method, and rendering options (e.g.wireframe , no studs, smoothed object). This project is focused on the smoothing

12

Page 20: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 5.1: Interface Design

of the LEGO object rather than the usability of the system and so the this limiteduser interface will be sufficient. The options will be represented as either radiobuttons or check boxes depending which is appropriate. Unallowed combinationsshould be disabled preventing the user from selecting them. Figure 5.1 shows howthe interface is simplistic, and as this project is concerned with observing the effectof smoothing methods on the LEGO object, that the interface is dominated by therendering display window. The application will consist of just this one interface.The ‘Load Model’ button will bring up a standard Microsoft Windows file selectiondialog from which the LEGO object can be selected. The top options change howthe LEGO object will be displayed, while the bottom ones make changes to the wayit will be smoothed.

5.1.3 Internal Representation

The internal representation of the object needs to be versatile so as to hold theLEGO object in both the LEGO parts, and mesh format. The structure will bedesigned to hold a LEGO object, this will contain an array of part objects similarto the command types defined by the LDraw file format. The part type, whichreferences another LEGO part in the LDraw file format will be represented by apart object that holds a reference to another LEGO object, because each part canbe seen as a smaller LEGO object which when combined create the complete LEGOobject this method will work well, and allows the hierarchical structure defined inthe LDraw format to be kept in the internal representation. The part type alongwith that of the line, triangle, quadrilateral, and special line parts will all be objectsinherited from a base class. These will store information relevant to that particularpart such as colour, normals, vertices, transformation matrix. The actual structureof each object is shown in Appendix B. When storing the mesh representation it

13

Page 21: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

will consist of just one LEGO object, and that will hold an array of just triangle orquadrilateral parts. As both the object and mesh structures are held in this internalstructure the renderer only needs to be capable of handling this one representation.

5.1.4 Program Flow Diagram

Figure 5.2 presents the reader with a high level plan of the system to help guidethem through the implementation section described below.

Figure 5.2: Flow Diagram of System

5.2 Implementation

This section describes the processes carried out in the creation of the system. Thesmoothing section describes some of the findings found from the smoothing meth-ods described in the Literature Review (see 2.5.2). It then goes onto discuss genericproblems found by all the smoothing methods, and how these problems could beresolved. The fixes are then attempted, and the results from them are discussed.This section does not provide detailed results from the smoothing methods, onlyenough information to give reasoning for attempting the fixes. The testing section(see Chapter 6) gives a more thorough discussion about the obtained results fromdifferent smoothing methods.

This section is ordered according to the logical flow through the system, and closelyfollows the path described by the program flow diagram (see Figure 5.2), passingeach of the sections output to the next sections input.

14

Page 22: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

5.2.1 Parsing LDraw Files

The parser takes an LDraw formatted file and generates an object which holdsan array of different parts (e.g. line, triangle, etc). The LDraw file format hascommands specified one to a line, and the parser reads each line examines thecommand type and carries out the correct task. For the basic commands; line,triangle, quadrilateral, and special line, a new object of that type (see AppendixB) is created and the vertex and colour fields populated. If the file is specified ashave the vertices clockwise ordered, the opposite to that required by OpenGL, thenthe vertices are swapped as they are entered into the internal structure so as to besuitable for rendering. For the more complex command; part reference, the systemcreates a new part object, and populates the transformation matrix, and name field.It sets the stud field to true if the name contains the word ‘stud’. If the previouscommand was ‘0 BFC INVERTNEXT’ (the invert next part meta-command) theinverted field is set to true. The parser then recursively calls itself with the partfile specified, and the returned object, being a LEGO object, is then stored in thepart field. All loaded parts are also stored in a hashtable identified by their partname, and when the part command is seen the system first checks if there is a partwith that name which has previously been loaded. If so then the other fields arepopulated as before, but rather than recursively calling the parser the object fromthe hashtable is copied into the part field. This is a deep copy, copying the partplus all sub parts within it. Once the bottom of the main object file is reached theparser returns the complete LEGO object.

5.2.2 Applying the Transformation Matrices

This section takes the LEGO object produced during loading, propagates the inver-sions, colours, and transformation matrices down through the structre, and returnsthis updated object.

To simplify the loading process the transformation matrices are not applied to partobjects during this procedure. The transformation matrix applies to all the partswithin the referenced part, this can be triangles, lines, and quadrilaterals, and alsoanother referenced part, along with its own transformation matrix. As the systemtraverses the internal structure it adds the seen transformation matrices to a stack,when it finds a shape defined it applies all the transformations on that stack tothe shapes vertices. When triangle and quadrilateral shapes are transformed theirsurface normals are calculated and stored in the objects normal field, these normalsare used later during the rendering process to produce the specular lighting effects.

As mentioned in the file parsing section an inverted flag can be set on the partobject, if this is the case then during the traversal of the structure the inversionsare carried forward through the parts, re-ordering the vertices if required.

Along with these the real colour RGB values are also calculated. LDraw coloursare specified through integer codes (see A.1), some of which are not an actual colourbut a reference to the ‘current’ colour. The ‘current’ colour is initially gray, and thenbecomes the last actual colour seen. As an example a LEGO brick is made up ofmany referenced parts, some of these being its studs. The triangles and quadrilater-als describing the stud part are defined with the colour code 16, the ‘current’ colour.

15

Page 23: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

The brick is given a colour at the top level, and the ‘current’ colour is set to it, whenthe stud part is reached during the traversal it is given the ‘current’ colour, whichis the desired colour of the brick. In the internal representation it is the real colourfields which holds this calculated colour. Figure 5.3 shows this traversal process.

Figure 5.3: Traversal of Internal Representation During

5.2.3 Rendering the LEGO Object

This section takes the updated LEGO object created by the previous section, andrenders the object to screen.

16

Page 24: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

The rendering process as mentioned previously (see 5.1.1) is carried out using OpenGL.OpenGL allows lines, triangles, and quadrilaterals to be defined by their vertices,details of which are specified in the LDraw file format, and have been reproducedin the internal representation of the LEGO object. It was therefore an easy processto create these in OpenGL. The vertex ordering had also been handled both duringloading and the transformation sections allowing the vertices to be used in the orderstored in the internal representation.

The rendering is carried out in a different thread to the rest of the applicationand consists of a loop instructing OpenGL to render the model on each cycle. Orig-inally OpenGL was being supplied with all the object data on every cycle and thetraversal of the LEGO object on each cycle made for a low frames per second (FPS)rate. To attempt to increase the FPS the internal structure was traversed once tocreate two stacks, one of instructions the other of values. The instructions consist oftriangle, quadrilateral, line, and colour, the values being either vertices, or the RGBcolour, and each command knowing how many values it required. Now each cycleof the rendering loop only has to run through the instruction stack rather than re-cursing through the LEGO object structure, and FPS rates did increase. At a laterstage the author was made aware of an improvement to this method of rendering.OpenGL natively supports the instruction list method, and this list is created in thesame way as the rendering is carried out but by specifying the rendering is to thelist. Now on each cycle of the rendering loop OpenGL is instructed to render thelist, and the details of the shapes do not have to be constantly specified. The systemwas adapted so that the stacks were still created from the LEGO object, and theOpenGL instruction list was built from a single render of these stacks, the controlloop was then updated to instruct OpenGL to render its internal list.

Requirement 5 specifies that the user must be able to rotate and zoom in on therendered object. This is done by applying a global rotation or adjusting the positionof the camera respectively, these are handled by OpenGL, and do not change any ofthe values within the LEGO object held in the internal structure.

The renderer can be supplied with certain display options, these include; wire framemode and the hiding of studs. The wire frame mode informs the OpenGL rendererto apply back and front face culling, (compared to the default of just back faceculling), when this option is specified the OpenGL renderer displays just the outlineof shapes, i.e. the wire frame. When the option to hide the studs is selected the listrepresentations are recreated from the main internal representation of the LEGOobject. However this time when the structure is being traversed if it comes across areference to a stud part (identified by the stud flag being set to true) it is skippedover, meaning the shapes which define the stud are not added to the lists, and hencenot displayed.

5.2.4 Converting the LEGO Object to a Mesh

This section takes the hierarchical object produced by the transformation section,and flattens it to just one object with triangles and quadrilaterals. The quadrilat-erals are converted into two triangles producing a triangle only mesh. The sharedvertices of each triangle are then merged, and this flattened mesh representation ofthe object returned.

17

Page 25: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Requirement 8 specifies the system should be capable of undoing the smoothingand reverting to the original LEGO object. The subdivision is the first step awayfrom the original LEGO object, so a copy is made before the flattening is applied,and this copy can be swapped in when the user wishes to return to viewing thenon-smoothed object.

The conversion is carried out by creating a new LEGO object which only holdsthe shapes, not the references to parts that contain shapes. This is done by travers-ing the original structure and adding any reference to a triangle or quadrilateralto the new object. The new object now holds the flattened version of the LEGOobject. The desired mesh is one containing only triangles and so as mentioned anyquadrilaterals are divided in half creating two new triangles. These triangles areadded to the LEGO object, and the original quadrilateral is removed.

Now we have a triangular mesh however each triangle has its vertices defined asdifferent objects. This means two triangles which share the same vertex locationhave independent objects specifying it. If this was not fixed so both triangles de-fined the vertex with a shared object then the creation of the neighbourhoods usedduring smoothing would be difficult. Also every vertex object would have to beupdated when smoothing is performed whereas if the triangles share the vertex ob-ject, the vertex only needs adjusting once for all the triangles with that vertex to bealtered. This method is known as merging the vertices and is performed by loopingthrough every vertex of every shape in the flattened LEGO object. For each vertexa list is checked, if that list contains a vertex with the same values then the vertexobject is redirected to point to this one, if no vertices match it on the list, then it isadded. Once completed all vertices defining the triangles in the mesh are containedin the list, and it is this list of vertices which is used during the smoothing methods,as changes to these change the triangles in the flattened LEGO object structure.

5.2.5 Smoothing

This section takes the flattened mesh structure and applies smoothing methods. The‘smoothed’ mesh is then returned as a LEGO object which can be rendered usingthe same method as the orginial LEGO object.

It is stated in requirement 9 that the system must be written in such a way thatsmoothing methods can easily be added to the system. The system could be moresimple to extend by using a plug-in based module system, where each smoothingmethod is a new module. However due to time constraints a slightly less extend-able method has been adopted. The file Smoother.VB consists of multiple controlsubroutines. These control the subdivision and smoothing iterations, and applyingof the smoothing at the correct time, e.g. Loops masking is applied during eachsubdivision iteration whereas the others are applied after the subdivision has takenplace. These control subroutines call the relevant methods, such as the subdivider,and more importantly the correct smoothing algorithm. To allow the user to selectthe type of smoothing they wish to carry out the interface also has to be updatedto add the smoothing method as an option. This is by far not the simplest form ofextensibility, however by creating a control loop calling the smoothing techniques,and adding the smoothing method to the user interface, the new method can be

18

Page 26: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

added to the system without having to make changes to the existing code.

As described in the literature review there are three smoothing techniques that willbe implemented first to show if the idea is plausible, and also to find any problemswhich are generic to them all and which can hopefully be eliminated.

Vertex Neighbourhood

The three smoothing techniques require a vertex neighbourhood. The neighbour-hood identifies, for each vertex within it, which other vertices it connects to. Thisinformation is used by each smoothing method to create the repositioned vertices,and ultimately the smoothed object. The literature review covers the details of thesesmoothing methods and how they utilise the neighbourhoods (see 2.5.2).

This section explains how the neighbourhood object is actually constructed by thesystem. The neighbourhood structure is represented by a hash table where the keyvalues are all the vertices from the mesh, and the data values are arrays of verticeswhich the key vertex connects to. This structure allows the individual vertices toquickly obtain their part of the neighbourhood when required during the smooth-ing processes. The structure is populated by iterating through each shape withinthe LEGO object representation of the mesh, and by each of these shapes iteratingthrough its vertices checking if they are already one of the keys in the neighbourhoodstructure. If so then the other vertices in the shape which connect to this vertexare added to the array in the hast table that is identified by this vertex. If a vertexis not already one of the keys in the hash table then an array is created containingthe vertices it connects to in its shape and this array is added to the hash tableusing the vertex as the key. Listing 5.1 is a pseudo example for constructing theneighbourhood structure from a triangular mesh.

19

Page 27: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Listing 5.1: Construction of Neighbourhoods.¨ ¥12 for each t as triangle in LEGO_Object3 for each v as vertex in t45 if neighbourhood.keys.contain(v) then6 ’Add the other vertices of the triangle to the

7 ’array identified by the vertex , v.

89 for each v2 as vertex in t where v2 is not v

10 neighbourhood(v).add(v2)11 next1213 else14 ’Key value not already identifying a neighbourhood

15 ’so add a new array containing this shapes vertices

16 ’and identified by v to the hash table.

1718 Dim arr as array19 for each v2 as vertex in t where v2 is not v20 arr.add(v2)21 next22 neighbourhood.add(v,arr)2324 end if2526 next27 next§ ¦

After the neighbourhood structure was populated the smoothing processes could beapplied using the formulas given in the literature review (see 2.5.2), and the resultsobserved, see Figure 5.4. As shown the ‘supposedly’ smoothed object is not verysmooth. This is partly due to the low density mesh, which is caused by not havingapplied any subdivision steps. Due to this the smoothing method only has a limitednumber of vertices to move and is unable to create curves.

Figure 5.4: First Smoothing OutputTaubin smoothing method applied 5 times, no subdivision.

20

Page 28: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 5.5: Example of Subdivison

Figure 5.6: Smoothing with SubdivisonSubdivision applied 3 times, Taubin smoothing applied 5 times.

Subdivision

The literature review describes a method for subdivision and this method is used forall the smoothing methods to generate the higher density mesh. This is implementedby iterating through the list of triangles in the mesh and dividing them up to createfour new ones (see 2.5.2, and Figure 2.1). Figure 5.5 shows subdivision being appliedto the LEGO object. The smoothing methods can now be applied to the subdividedmesh and improvements are immediately seen, Figure 5.6 was subdivided three timesbefore having the Taubin smoothing method applied five times as before (see Figure5.4).

A system has now been built which can smooth LEGO objects to some degree.The testing section describes what the perfect ‘smoothed’ object would be, and howwell the different smoothing methods fair at reaching this goal. During the testing aproblem was discovered which applies to all the smoothing methods, and an attemptis made to correct it.

Surface Removal

The LEGO object to mesh representation is carried out by flattening the hierarchicalstructure to an array of shapes (see 3.4). The problem is this method does not take

21

Page 29: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 5.7: Example of the Pinching EffectSigns of pinching at the location highlighted.

into consideration whether these shapes are overlapping each other. So for the ex-ample shown in Figure 5.7 the mesh is that of two complete bricks, and there is stilla connection between where the two arrows are indicating. This connection causesthe averaging effect applied by the smoothing methods to pull the points inwardscreating a pinching effect. To remove this problem these overlapping areas of shapeswould have to be removed so that the constructed mesh is of only the outer ‘visible’parts.

Most LEGO bricks are constructed from quadrilaterals and so to simplify the surfaceremoval process all but the quadrilateral shapes are disregarded from the LEGO ob-ject representation. The removal process can be split into two sections; removal ofthe overlaps, and removal of trapped shapes. The first of these have been mentionedalready, the trapped shapes can occur once the removal of overlaps has been carriedout. Figure 5.8 shows how shapes can become isolated from the exterior mesh. Itshows a cross section of two bricks, one on top of the other, and then shows howafter surface removal the highlighted blue surfaces are now isolated from the theouter mesh. This may not initially appear to be a problem as the isolated surfaceswill not be visible. However once smoothing is applied it could become a problem,firstly these extra shapes do not need to be smoothed so a waste of resources occurs,but a more important issue is that because these shapes are not connected to theexterior mesh they will not smooth in the same direction, and could move throughthe exterior mesh, or worse connect with it creating undesired effects.

The surface removal process has many steps to it, requiring both surface and isolatedshape removal. The surface removal has to be able to recognise the different waysin which two quadrilaterals can overlap and apply the correct methods to resolve it.The isolated shape removal is carried out in two steps; firstly find a quadrilateral onthe object which can see the outside, i.e. a line can be drawn from the quadrilateraldirectly to the LEGO object’s bounding box without colliding with another shape.Once a quadrilateral meeting this requirement has been found, all quadrilateralsthat share one of its vertices, and all the quadrilaterals that share one of thosequadrilaterals vertices, and so on are marked as external. After this process iscomplete any quadrilaterals that are not marked as external are therefore isolatedand can be removed.

22

Page 30: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 5.8: Isolated ShapesInternal shapes can become isolated once surface removal is applied.

Below is the high level plan for overlapping and isolated shape removal, followed bya detailed plan for resolving the overlapping quadrilaterals.

1. Remove Overlapping Quadrilaterals

Resolve overlapping conflicts to leave only the parts of quadrilaterals whichare not covered by another quadrilateral.

2. Find an Outside Quadrilateral

Find a quadrilateral which can draw a line between itself and the objectsbounding box such that the line does not intersect with any other quadrilat-erals.

3. Find all Touching Quadrilaterals

Once one quadrilateral can be proven to be on the external mesh then allshapes it recursively connects to are also on the external mesh. Any that cannot be recursively connected to are isolated and can be removed.

Plan for Resolving Overlapping Quadrilaterals

This process is broken down so only two quadrilaterals are compared with eachother at any time. Three outcomes of the comparison can arise, either they are notoverlapping, requiring no change, one or both are completely covered by the other,requiring completely covered quadrilateral(s) to be removed from the mesh object,or one or both are partially covered, requiring removal of partially covered quadri-lateral(s) from the mesh object and the addition of the correct quadrilateral shapeto fill the area not covered (this may require more than one quadrilateral). Thesenewly added quadrilateral(s) are added to the end of the comparison list incase theystill overlap with another quadrilateral.

The first step is to analyse the vertices of each quadrilateral and determine if theyare either external (not inside other quadrilaterals), internal, intersection (is in thesame position as a vertex on the other quadrilateral), or line intersections (is on anedge of the other quadrilateral). Once the vertices have been correctly categorisedthe system is able to select which method to use on each quadrilateral to resolve theoverlaps.

23

Page 31: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

• Both quadrilaterals have all external vertices and no intersections

Nothing needs to be done as neither of the quadrilaterals are overlapping

• Neither quadrilateral has internal vertices and either one or bothhave line intersections

As no internal vertices, then for each quadrilateral its external verticesare left connected as they were. The line interceptions are connected together,and then these connected parts are joined to form the final quadrilateral. Theoriginal quadrilaterals are removed and the new quadrilaterals added to themesh structure. (See C.1).

• Neither quadrilateral has internal vertices or line intersections, butthey have at least one interception

The quadrilaterals could just be touching, or if they both have the sameheight, one could be inside the other as shown by C.2. The system checks ifone quadrilateral is completely inside the other, if so it can be removed. Thequadrilateral that is not inside needs to have the area of overlap removed fromit. This is done by keeping the external vertices joined, the interceptions arethen connected together by examining where on the other shape they were,and which connections are valid. These connected parts are joined to form thefinal quadrilateral.

• One or both quadrilaterals have internal vertices

The two quadrilaterals overlap and one or both of them have at least onevertex inside the other quadrilateral. The exterior vertices (should there bemore than one) remain joined as they were. The internal vertices (should therebe more than one) are kept joined as they were when in the other quadrilateral.The exterior and internal vertices are then connected by the relevant lineinterceptions, see C.3. As can be seen shapes with more than four vertices canbe created. In this case these need to be divided to create quadrilaterals.

Due to time constraints not all of this section was implemented in the final system.The vertex categorising and overlap resolution is fully implemented except for thecase when internal vertices are present. For this the correct shape outline is obtained,but there is no splitting carried out on shapes with more than four vertices. Theexterior finding algorithm which works by proving one quadrilateral is on the outside,and then removes quadrilaterals which are not recursively connected to it is notimplemented at all. However the object used to display the pinching effect whichintroduced the need for this overlap removal function (see Figure 5.7) can be shownsmoothed after the overlaps have been removed. As figure 5.9 shows the smoothingnow shows no signs of the pinching effect.

24

Page 32: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 5.9: Smoothing Applied after Overlapping Quadrilaterals are ResolvedThe pinching effect has been removed, and the object is able to smooth properly.

5.2.6 DirectX File Output

Due to time constraints this section was unable to be implemented. The aim of theproject was to show if LEGO objects could be smoothed so as to be useable in otherapplications. The rendered output of the smoothed LEGO objects can show if thisis possible and the DirectX output is only required to allow the smoothed model tobe used in other applications and not in proving that it was possible to create it.

25

Page 33: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 6

Testing

The testing is split into two sections; the first looks at how well the system meetsthe requirements specified in Chapter 4, the second looks at how well the smoothingmethods adopted, behave when applied to LEGO models.

6.1 Testing of Requirements

6.1.1 Functional Requirements

Requirement 1: The system must load LEGO objects stored in the LDrawfile formatThis requirement is met. All the commands, and required meta-commands, i.e.those concerned with vertex ordering, are fully parsed and understood. The internalrepresentation is populated with the data, and after the initial load the transforma-tions are applied, and the colours calculated.

Requirement 2: The system must store the loaded model in an inter-nal structure that is adaptable enough to hold the LEGO data, and meshstructureThis requirement is met. The internal structure consists of an array of parts. TheLEGO hierarchy is supported by the ‘part type’ being able to contain another LEGOobject. Support for the mesh structure is obtained by storing the mesh as individualtriangles, these triangle parts are stored in the array within the internal structure.

Requirement 3: The system must be able to convert from the LEGOformat into a mesh structureThis requirement is met. The system has a process which takes the hierarchicalLEGO object representation and essentially flattens it to create one array of parts,the line parts are removed, and the quadrilaterals split into triangles. While beinga mesh it does however still contain the internal sections of the structure and theremoval of this internal structure is not fully implemented, although it has beenplanned, and the method is described.

Requirement 4: The system must be capable of rendering the unchangedLEGO object, and the smoothed mesh structureThis requirement is met on both accounts. Figure 6.1 shows the LEGO objectas it was described in the LDraw file, and again after subdivision and Laplacian

26

Page 34: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

smoothing has been applied.

Figure 6.1: Test Results for Requirement 4Shows the rendering of a LEGO object before and after the smoothing process

Requirement 5: The system must also allow the user to rotate and zoomthe view so as to be able to fully examine the rendered objects. Wire-frame, and other similar options would be helpful.This requirement is met. The rendered object can be rotated and zoomed in uponby using the mouse. The system supports showing the model in wireframe mode.It also allows the user to show the object with or without sides, and will show thenormals of each shape, useful when determining if a shape’s vertices are ordered inthe correct orientation. It will also show the user the location and type of the inter-sections used during the internal surface removal algorithm, useful for debugging.

Requirement 6: The system must remove the stud characteristics fromthe LEGO object This requirement is met. As shown in Figure 6.1 the studs areremoved from the LEGO object during smoothing.

Requirement 7: The system must demonstrate the effects of differentsmoothing methodsThis requirement is met. The system allows the user to apply three smoothingtechniques; Taubin Surface Fairing, Loop’s Masking, and Laplacian Smoothing, de-scriptions of which are found in the literature review 2.5.2.

Requirement 8: The system must be able to apply different smooth-ing techniques to the original model without having to reload the modeleach timeThis requirement is met. The system takes a copy of the non-smoothed object be-fore converting it to the mesh format and applying smoothing. When the smoothingmethod is changed, or the smoothing option turned off the smoothed model is dis-regarded and the non-smoothed copy is copied back in to be the current internalrepresentation of the object.

Requirement 9: The system must be easily extendable to allow differ-ent smoothing methods to be added easilyThis requirement is partially met. The system makes it reasonable easy to add a

27

Page 35: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

new smoothing method, and while existing code does not need to be changed to adda smoothing method, the smoothing code would have to be added and the projectre-compiled.

Requirement 10: The system must be able to save the smoothed meshstructure in the DirectX file format so as to be useable by other applica-tionsThis requirement is not met. Due to time constraints this feature had to be removed.

6.1.2 Non-Functional Requirements

Requirement 11: The system should be able to load models within anacceptable durationThis requirement is met. While ‘acceptable duration’ is not an exact measurementthis requirement can be stated as being met because it is capable of loading largeLEGO objects almost instantaneously.

Requirement 12: The system should provide an easy method of selectingthe different smoothing operationsThis requirement is met. The user is provided with a list of radio buttons to selectthe type of smoothing that should be applied. They are also provided with theability to change the number of subdivision and smoothing iterations which will becarried out.

It can be seen that 10 out of the 12 requirements are fully met. Out of the tworequirements that are not; DirectX file output is not essential to understanding ifbuilding smoothed ‘useful’ objects from LEGO bricks is plausible. The smoothingis more essential, however new methods can be applied with only a limited amountof change to existing code being required. Neither of these two requirements arecritical to the project, and the results the system generates.

6.2 Testing the Smoothing Methods

This section investigates the three smoothing methods; Taubin, Loop, and Lapla-cian, and investigates the positive and negative features of these when applied toLEGO bricks. A definition of ‘smooth’ is suggested and the smoothing methods arecompared to determine which perform the best against this criteria.

6.2.1 Definition Of Smooth

For this project the idea of a smooth shape is one that removes the ‘blockly’ appear-ance. Due to the size of the blocks used in LEGO, smooth shapes such as pyramidscan only be approximately constructed, see Figure 6.2. A ‘smooth’ version of thisapproximation would be a square based pyramid, see Figure 6.3. This section willtest how well these smoothing methods perform when applied to LEGO objects toobtain this definition of ‘smooth’.

Smoothing can be greatly affected by the number of subdivisions and smoothingiterations applied, as is demonstrated by Figure 5.4. The testing attempts to applythe correct number of these iterations to produce the best smoothness so as to show

28

Page 36: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 6.2: LEGO Pyramid

Figure 6.3: Square Pyramid

if that smoothing method is capable of producing the correct result.

The testing uses the LEGO pyramid shown in Figure 6.2. The result images showthe pyramid from a side on angle. A black outline defines where the smooth out-line should occur (see Figure 6.4), a red outline shows an outline of the size of thesmoothed result, this identifies any shrinkage, and also any undulations.

Figure 6.4: Black Triangle Showing the Desired ‘Smooth’ Result

29

Page 37: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

As already mentioned (see 5.2.5) the system does not completely remove internalshapes from the mesh, and this does affect the smoothing process. This is describedin more detail in each test.

6.2.2 Laplacian Smoothing

As mentioned in the literature review this is one of the simplest smoothing methodsand has the known problem of shrinkage. As can be seen from Figure 6.5 the

Figure 6.5: Test 1: Laplacian Smoothing of the Pyramid LEGO Object4 subdivisions and 300 smoothing iterations were applied

red triangle shows quite a significant amount of shrinkage to the pyramid. Thesmoothed object does however fit quite closely to the reduced size of that triangle,and shows clearly that the pyramid has been smoothed to some degree. Signs of the‘pinching’ effect can be seen occurring between the different levels of the pyramid,and straighter edges could be obtainable if this problem was removed.

6.2.3 Taubin’s Surface Fairing

Taubin’s approach is based upon the laplacian smoothing approach, but tries toreduce the amount of shrinkage. As can be seen from Figure 6.6 there is only a verysmall amount of shrinkage. Unfortunately it is also clear that this method whiledoes smooth the sharp edges, it does not remove the ‘blocky’ look of the object.Again the ‘pinching’ effect can be seen especially on the right hand side between thegreen and red bricks.

6.2.4 Loop’s Masking

Loop’s Masking method is different in that it does not apply the smoothing afterthe subdivision process, but during it. As can be seen from Figure 6.7 there hasbeen only a small amount of shrinkage, but more clearly is the issue of the differentlayers splitting apart. From Figure 6.8 it can be seen that while the object lookssmooth, many holes have also appeared over the object.

30

Page 38: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 6.6: Test 2: Taubin’s Surface Fairing of the Pyramid LEGO Object3 subdivisions and 300 smoothing iterations were applied

Figure 6.7: Test 3: Loop’s Masking of the Pyramid LEGO Object5 subdivisions and smoothing iterations were applied

The problem lies with the uneven density of the mesh, and not particulary withthis method. The other two smoothing methods have not suffered as badly fromthis problem, although small gaps can be seen in Figure 6.5 between the layers. Theproblem arises from the way the mesh structure is created. Each original shape inthe LEGO object is subdivided the same amount of times, this means that a shapewith a small area is subdivided the same amount of times as a shape with a largerarea, causing the small shape to have more triangles in the same area as that ofthe large shape. The different densities affect how the smoothing methods work, ashigh density meshes take more smoothing iterations to create the same amount ofsmoothness as low density meshes, therefore high density areas will shows less signsof smoothing than low density areas. Due to the uneven density of the mesh the

31

Page 39: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 6.8: Test 3: Loop’s Masking of the Pyramid LEGO Object - Top View5 subdivisions and smoothing iterations were applied

smoothing is not performed evenly over the whole object.

Another problem the different densities cause, and which is the problem clearlyseen in Figure 6.7, is that of gaps occurring in the mesh. In LEGO objects mostof the shapes have different areas to those of their neighbours, and consequentlythe mesh has areas of different densities. Different density meshes do not connecttogether well and smoothing can causes these edges to be pulled apart causing thegaps. Figure 6.9 shows how the gaps are created, the diagram is simplified to onlysmooth the two vertices that cause the gap to appear. The red dots show whichvertices from the meshes of the two shapes connect. The two which do not connectcan then be seen to be smoothed away from the other shape causing the gaps toappear. The more times the smoothing methods are applied the gaps are expandeduntil the situation shown in Figures 6.7, and 6.8 occurs.

Figure 6.9: Gaps Created in the Mesh During Smoothing

32

Page 40: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

6.3 Conclusion

It can be seen from the test images that Laplacian smoothing is most likely to bethe better method of smoothing LEGO objects, however it does suffer badly fromshrinkage. Taubin surface fairing does counteract the shrinking problem as it wasdesigned to, however it does not remove the ‘blocky’ look of the LEGO object, andso is not a very good candidate for this particular purpose. Loops method providesvery smoothed shapes, but unfortunately is greatly affected by the internal parts ofthe mesh, and the changes in mesh density, leaving it difficult to determine whether,with these two problems removed, this could be a viable smoothing method.

33

Page 41: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 7

Critical Evaluation

This section examines the system and discusses whether the approaches taken werethe most appropriate, and whether with the knowledge gained from developing thesystem anything would have be done differently.

7.1 File Parser

The LDraw file format is very well documented and the development of the file parserwas a relatively simple task, and while the system handles the vertex ordering formost of the basic shapes there are some more complex objects where the orderingappears to be the wrong way around. The reason for this was never found, the filespecification was adhered to, and the code examined, all seeming correct. It couldstill be a problem with the system, or there is a chance it could be a problem withthe actual model . Figure 7.1 demonstrates the problem, while there appears to begaps they are actually being back face culled by the OpenGL renderer.

7.2 The Mesh

The system has to convert the LEGO object into a mesh representation to be ableto provide a basis for the smoothing methods. The principle of how this process iscarried out is reasonably simple and effective, however it does create a mesh withvaried densities and internal parts. However these can both be fixed; the internalparts by the method detailed within the implementation, and the varied densitiesby creating fixed sized subdivisions and rather than the size of each triangle beingrelated to the initial area of the shape, the number of subdivision will be. Withboth these fixes applied then this method is a reasonable way of constructing themesh for applying the smoothing to.

7.3 Smoothing Extensibility

As discussed within the testing of the requirements the smoothing is theoreticallyquite easy as the system can allow for new methods to be added without needingto make changes to the existing methods. However the source code would needrecompiling and this stops it being extensible by anyone other than the developers.

34

Page 42: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure 7.1: Parts Rendered with the Wrong Vertex Ordering

A better approach would have been to make the smoothing methods plug-ins tothe system, and therefore allowing anyone to write them. The system could thenload the plug-in and supply the user with that smoothing option, if the plug-in wasremoved the option would be removed from the user.

7.4 Smoothing

Due to the time constraints and unforseen problems during the mesh creation withthe internal parts and variations in the mesh density becoming a problem, only alimited number of smoothing methods could be implemented and tested. These maynot be the best methods to be applied to LEGO objects, and exploration of othersmoothing methods, or their variations could lead to better methods. Howeverthe system is able to take LEGO objects, and once the necessary fixes are fullyimplemented to the mesh creation procedure, create a mesh structure, and this canbe used as a basis for the exploration of other smoothing methods.

35

Page 43: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 8

Further Work

This section outlines areas in which this project could be further developed.

Small additions to the system would be; complete the implementation of removinginternal parts from the mesh, to create a mesh of equal density, and to implementthe DirectX File output allowing the smoothed models to be used within other ap-plications.

Other more substantial areas of development are;

• To adapt the system to provide more extensibility for different smoothingmethods.

• To use the system as a basis for investigating better or other methods ofsmoothing or otherwise, that can remove the ‘blocky’ appearance of the Legostructures.

• To improve the smoothing technique so rather than applying it to the modelas a whole, certain parts of the model could be selected to be smoothed whileother areas are left unchanged.

• To investigate methods that can reduce the polygon count of the smoothed ob-jects. For the smoothing to work well a reasonable number of subdivision arerequired. For example the test of Loop’s masking carried out five subdivisionson the pyramid object, creating a mesh consisting of 307,200 polygons. De-pending on the domain of the application which may wish to use this smoothedobject this number of polygons could be unfeasible, and methods to reduce thepolygon count while still keeping the smoothed appearance would be required.

36

Page 44: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Chapter 9

Conclusion

The project set out to investigate if LEGO models could be used as a feasiblemethod of creating 3D objects for multiple domains. This requires the objects shouldloose their noticeable LEGO characteristics of studs, and ‘blocky’ shape. The studsbecame an easy feature to remove due to the hierarchical structure contained withinthe LDraw file format. The ‘blocky’ appearance then became the main area ofinterest for the project. Methods of smoothing were researched, and it was found amesh of the object would be required. A method for converting the LEGO objectto a mesh was implemented, and new problems of internal parts, and varied meshdensity were found. A method to identify and remove the internal parts from themesh was then drawn up, and implementation attempted. Unfortunately due totime constraints this could not be completed, but some examples could be testedand the results showed the positive effects of removing these parts. Three smoothingmethods were investigated and implemented, and while being adversely affected bythe problems with the mesh they were still able to show signs of smoothing, withLaplacian giving reasonable results under the conditions. This project was unableto determine a perfect method of smoothing all LEGO objects, and more researchand implementation is needed before such a statement could be made. However itprovides a basis for this research and shows that the creation of smooth 3D objectsfrom LEGO building blocks is likely to be possible.

37

Page 45: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Bibliography

[1] Efficient, fair interpolation using catmull-clark surface, SIGGRAPH’93. Com-puter Graphics, August 1993.

[2] Lego website.URL http://www.lego.com/eng/factory/, Accessed: December, 2005.

[3] Qube software website.URL http://www.qubesoft.com/, Accessed: December, 2005.

[4] T. Bulow. Spherical diffusion for 3d surface smoothing. IEEE Transactions onPattern Analysis and Machine Intelligence, 26(12), December 2004.

[5] LDraw Committe. Ldraw file format.URL http://www.ldraw.org/modules.php?op=modload&name=News&file=article&sid=45, Accessed: December, 2005.

[6] LDraw Committee. Ldraw organistation website.URL http://www.ldraw.org, Accessed: April, 2006.

[7] LDraw Committee. Ldraw compatable lego simultors.URL http://www.ldraw.org/modules.php?op=modload&name=Downloads&file=index&req=viewdownload&cid=8, Accessed: December, 2005.

[8] L. Dupont. C# graphics library.URL http://csgl.sourceforge.net/index.html, Accessed: December 2005.

[9] C. LOOP. Smooth subdivision surfaces based on triangles. Master’s thesis,Dept. of Mathematics, University Of Utah, August 1987.

[10] B. McPhail. Loop’s subdivision.URL http://www.reed.edu/ mcphailb/opengl/proj2/, Accessed: December2005.

[11] Microsoft. Directx file format reference.URL http://msdn.microsoft.com/library/default.asp?url/̄library/en-us/directx9 c/directx/graphics/reference/fileformat/xfileformat.asp,Accessed: December 2005.

[12] Wolframe Research. Mathworld.URL http://mathworld.wolfram.com/, Accessed: April 2006.

[13] Matthew L. Staten Scott A. Cannann, Joseph R. Tristano. An approach to com-bined laplacian and optimization-based smoothing for triangular, quadrilateral,and quad-dominant meshes. Technical report, ANSYS, Inc.

38

Page 46: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

[14] I. Sommerville. Software Engineering. Addison-Wesley, 6th edition, 2001.

[15] G Taubin, editor. A signal processing approach to fair surface design, Computergraphics and interactive techniques. ACM Press, 1995.

39

Page 47: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Appendix A

File Formats

A.1 LDraw File Format

The LDraw file specification is shown below. This is taken from the specificationdocument supplied by LDRAW [5]. Key information is listed first then followed bydescriptions of available commands.

• File Extension (LDR or DAT)

• Plain Text

• Each line is a new command

• Each line is independent

• Only a few commands are used

• Commands are identified by the first number on a line (Known as the line-type)

• Contents and format of a line depend on the line-type

• Commands

0. Comment or Meta-command

1. Part file reference

2. Line

3. Triangle

4. Quadrilateral

5. Draws a line between the first two points, if the last two points are onthe same side of that line

• If the line type is not valid then the line is ignored

• Meta commands require a key word to follow the line-type. Key words must bein CAPITALS. If the meta-command does not require additional information,none should be given.

40

Page 48: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

• Meta-commands

Model Title

Step

Write

Clear

Pause

Save

File Type

BFC CW

BFC CCW

BFC INVERTNEXT

Below are descriptions of each of the commands and meta-commands. Commandsare instructions on how to display a shape. Meta-commands are instructions tothe simulation software telling it to carry out a task. The meta-commands are notimplemented in every simulation system. Additional ones are sometimes added byother systems. The ones listed here are the official ones supported by LDraw’s ownsimulation system.

Colour is used in most commands, so to avoid duplication of the definition of colourit is shown here.

• colour is a colour code: 0-15, 16, 24, 32-47, 256-511

0 = Black1 = Blue2 = Green3 = Dark Cyan4 = Red5 = Magenta6 = Brown7 = Grey8 = Dark Grey9 = Light Blue10 = Light Green11 = Cyan12 = Light Red13 = Pink14 = Yellow15 = White16 = Current Colour24 = Complementary Colour to the current colour32 - 47 = Transparent Colours256 - 511 = Dithered Colour.

To obtain a transparent colour add 32 to the original colour.To use dithered colour such as to combine colours J and K. The colour value specifiedshould be:

41

Page 49: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

colour = (J * 16) + K + 256

Part Command

Inserts a part defined in another LDraw file.Line format:

1 colour x y z a b c d e f g h i part.dat

• x, y, z is the position of the part

• a - i are orientation & transformation parameters

• parts.dat is the filename of the included part

Part files can also include Part commands, there is not a limit on the depth ofreferencing parts.The letters x, y, z, a - i represent a homogenous matrix transformation that can beapplied to the include part. They are arranged as such:

a d g 0b e h 0c f i 0x y z 1

Note only rotations and translations can be applied as scaling variables are notadjustable.

Line Command

Draws a line between two points.Line format:

2 colour x1 y1 z1 x2 y2 z2

• x1, y1, z1 is the position of the first point

• x2, y2, z2 is the position of the second point

Triangle Command

Draws a filled triangle between three points.Line format:

3 colour x1 y1 z1 x2 y2 z2 x3 y3 z3

• x1, y1, z1 is the position of the first point

• x2, y2, z2 is the position of the second point

• x3, y3, z3 is the position of the third point

42

Page 50: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Quadrilateral Command

Draws a four-sided, filled shape between four points.Line format:

4 colour x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4

• x1, y1, z1 is the position of the first point

• x2, y2, z2 is the position of the second point

• x3, y3, z3 is the position of the third point

• x4, y4, z4 is the position of the fourth point

Conditional-Line Command

Draws a line between the first two points, if the projections of the last two pointsonto the screen are on the same side of an imaginary line through the projections ofthe first two points onto the screen.Line format:

5 colour x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4

• x1, y1, z1 is the position of the first point

• x2, y2, z2 is the position of the second point

• x3, y3, z3 is the position of the third point

• x4, y4, z4 is the position of the fourth point

Model Title

The descriptive name of the model or part file.Line Format:

0 title-text

Where title-text is the name of the model. This is a location specific command. I.e.If the first line has a line-type of 0 then that line is the title. This overrides anymeta-commands on the line.

Step Meta-Command

Marks the end of a building step.Line Format:

0 STEP

The command will cause LDraw to stop until <Enter> is pressed. It will causeLDraw to save the current image into a bitmap file.

43

Page 51: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Write Meta-Command

Display a message at the top of the screen.Line Format:

0 WRITE message-text [or] PRINT message-text

Message-text is the message to be displayed.

Clear Meta-Command

Clears the screen.Line Format:

0 CLEAR

Useful for advanced model files.

Pause Meta-Command

Causes LDraw to stop until you press <Enter>.Line Format:

0 PAUSE

The is like the Step command, but does not save bitmaps.

Save Meta-Command

Causes LDraw to save the current image in a bitmap.Line Format:

0 SAVE

This saves the current image to a bitmap.

File Type Meta-Command

Indicates the type of file (model, part, etc), and if it is part of the LDraw.org PartsLibrary.Line Format:

0 LDRAW_ORG type

OR

0 Official LCAD type

OR

0 Unofficial type

OR

0 Un-official type

44

Page 52: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

This meta statement should appear as the last line of the file header. The firstformat (LDRAW_ORG) is the current standard for the official parts library. Olderfiles used the second (Official LCAD) format. The valid values for the type field are:

• Part

• Element

• Sub-Part

• Primitive

• Shortcut

• Alias

• Model

• Submodel

• File

• Hi-Res Primitive

BFC CW Meta-Command

Indicates the triangles and quadrilaterals defined in the part file have their verticesspecified such that when the shape is facing forwards they are in a clock-wise direc-tion. This information is needed when rendering using 3D renders such as OpenGL.

BFC CCW Meta-Command

Indicates the triangles and quadrilaterals defined in the part file have their verticesspecified such that when the shape is facing forwards they are in a counter clock-wisedirection.

BFC INVERT NEXT Meta-Command

Indicates that the part defined on the next line is to be inverted i.e. if the defined partspecifies it is clock-wise ordered then it should now be counter clock-wise orderedand vis versa.

A.2 DirectX File Format

The DirectX file specification is shown below. This is taken from the specificationdocument supplied by Microsoft [11]. There are 4 types of directX file as listedbelow, however the description is that of the text type. Key information is listedfirst then followed by descriptions of instructions, data structures, and templates.

• File extension is .x

• File type can be, plain text, binary, MSZip compressed text, or MSZip com-pressed binary

45

Page 53: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

• Template based

• Uses data structures

• Variable length header, defining:

File type

Version number

Floating point representation

Magic number

Comments

Comments can occur anywhere in the file. They either begin with # or // and runto the end of the line.

Reserved Words

Words that are reserved and used by the directX language are:

• ARRAY

• BINARY

• BINARY_RESOURCE

• CHAR

• CSTRING

• DOUBLE

• DWORD

• FLOAT

• SDWORD

• STRING

• SWORD

• TEMPLATE

• UCHAR

• ULONGLONG

• UNICODE

• WORD

Variable-length Header

The variable-length header is compulsory and must be at the beginning of the datastream. It contains the following data:

46

Page 54: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Table A.1: Contents of Variable Length Header. [11]

Type Size (bytes) Value DescriptionMagic Number 4 ”xof”Version Number 2 ”03” Major Version 3

”03” Minor Version 3Format Type 4 ”txt ” Text File

”bin ” Binary File”tzip” MSZip compressed text file””bzip” MSZip compressed binary file

Float Size 4 ”0064” 64-bit floats”0032” 32-bit floats

Data

Data objects contain the actual data or a reference to that data. Each data objecthas a corresponding template that specifies its data type.

Form, Identifier, and Name

Data objects have the following form.<Identifier> [name] { [<UUID>]

<member 1>;...<member n>;

}

The identifier is compulsory and must match a previously defined data type orprimitive. The name, however, is optional.

Data Members

Data members are either one of the following: data object, data reference, integerlist, float list, or string list.A data object is a nested data object, allowing the hierarchical nature of the fileformat to be expressed. A data reference is a reference to a previously encountereddata object, as shown below:{

name |UUID |name UUID

}Integer, float, and string lists are semicolon delimited. For example, integer list:Integer List: 1; 2; 3;Float List: 1.0; 2.0; 3.0;String List: "One"; "Two"; "Three";

47

Page 55: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Templates

Templates define how the data stream is interpreted.There is one special template called the header template. This can store applicationspecific information such as version numbers. A flags member can also be definedas a DWORD. If clear (i.e. equals 0) then the following data in the file is binary, ifits set (i.e equals 1) then the following data is text. Multiple header data objectscan be used to switch between binary and text format within the file.

Template Form, Name, and UUID

A template has the flowing form.template <template-name> {<UUID>

<member 1>;...<member n>;

[restrictions]}template-name is alphanumeric and can contain the underscore character (_). Itmust not start with a digit. The UUID is a universally unique identifier formattedto the Open Software Foundation’s Distributed Computing Environment standardand enclosed by angle brackets (< >).For example: <34A3066F-AE1F-4410-B7DC-6DFBB6DC82D7>

Template Members

Template members are a named data type followed by an optional name, or an arrayof a named type.

Table A.2: Valid primitive data types. [11]

Type SizeWORD 16 bitsDWORD 32 bitsFLOAT IEEE floatDOUBLE 64 bitsCHAR 8 bitsUCHAR 8 bitsBYTE 8 bitsSTRING NULL terminated stringCSTRING Formatted C string (not supported)UNICODE Unicode string (not supported)

Additional data types defined by templates can be used, but these must be definedabove the point they are being used. No forward references are allowed.Any valid data type can be expressed as an array in the template definition.

array <data-type> <name>[<dimension-size>];

48

Page 56: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

<dimension-size> can be either an integer or named reference to another tem-plate member whose value is then substituted. Arrays can be multidimensional.The number of dimensions is determined by the number of paired square bracketstrailing the statement. For example:

array DWORD FixedHerd[24];array DWORD Herd[nCows];array FLOAT Matrix4x4[4][4];

Template Restrictions

Templates can be open, closed, or restricted. These restrictions determine whichdata types can appear in the data object the template defines. An open templatehas no restrictions, a closed template rejects all template defined data types, and arestricted template only allows those specified.Open template: [ ... ]Restricted template: [ { data-type [ UUID ] , } ... ]The absence of these two indicate a closed template.

Template Example

template Mesh {<34A3066F-AE1F-4410-B7DC-6DFBB6DC82D7>DWORD nVertices;array Vector vertices[nVertices];DWORD nFaces;[ ... ] //An open template}

template Vector {<39G4829D-FK59-DJF9-384K-JJ49FLDS8FL0>FLOAT x;FLOAT y;FLOAT z;} //a closed template

template FileSystem {<UUID>STRING name[ Directory <UUID>, File <UUID> ] //A restricted template}

49

Page 57: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Appendix B

Part Structures

These are the definitions for the object representation used in the system for thefive different part types declared in the LDraw file format.

• Base Part Object (which all parts are inherited from)

Type Stores the type of the object, is redundant as the type can be derivedfrom the type of the object, but is quicker to test against in computingterms.

Colour The LDraw colour code of the part.

RealColour The actual RGB colour that will be rendered.

• Part Type

Part The referenced part stored as another LEGO object.

Transformation Matrix The matrix defined in the LDraw file specifyinghow the referenced part should be scaled, and rotated.

Stud Is a boolean flag that is set to true during the loading if the part namecontains the word stud. This is used for stud removal.

Inverted Is a boolean flag used to specify it the referenced part should beinverted.

Name The name of the part, used as the key in the hash table of alreadyloaded parts.

• Line Type

P1 Start point of the line

P2 End point of the line

• Triangle Type

P1 First vertex of the triangle

P2 Second vertex of the triangle

P3 Third vertex of the triangle

Norm The normal to the surface of the triangle

50

Page 58: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

• Quadrilateral Type

P1 First vertex of the quadrilateral

P2 Second vertex of the quadrilateral

P3 Third vertex of the quadrilateral

P4 Forth vertex of the quadrilateral

Norm The normal to the surface of the quadrilateral

• Special Line Type

LineP1 Start point of the line

LineP2 End point of the line

TestP1 Start point of conditional line

TestP2 End point of the conditional line

51

Page 59: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Appendix C

Overlap Resolving Images

Figure C.1: Overlap Resolving for External Vertices and Line Intersections

Image 1 shows where the overlapping sections of the bright red and green quadrilat-erals have been removed. Image 2 shows the same process on the other overlappingquadrilateral. The bold black lines show where the line intersections were and howthey were joined.

Figure C.2: Overlap Resolving for External Vertices and Intersections

The bright blue area shows how one quadrilateral can be inside the other quadrilat-eral, shown here by its green outline. The bright red section is the only part thatremains after the overlap has been resolved.

52

Page 60: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Figure C.3: Overlap Resolving for Internal Vertices

Image 1 shows the overlap of the two bricks in 3D giving an example of when thiscase can occur. Image 2 shows this again from the top and only displaying the twoquadrilaterals we are concerned with. Image 3 shows the two newly created shapesin red and gray. Taking the red shape, the red circles show its external vertices, theblue its internal vertex, and the green the line intersections. The red lines show howthe externals vertices and line interceptions are connected, and the blue lines showhow the internal vertex and line interceptions are connected. As can be seen a 5vertex shape has been created.

53

Page 61: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

Appendix D

Code Listing

Below is the complete code listing for the system.

D.1 Common.vb

This file holds useful calculations for example the vector mathematics.1 Imports LEGO_Smoothing.ModelDefs

23 Public Class Common

45 Public Shared GlobID As Integer = 0

67 Public Class Point3D

8 Public x, y, z As Single

9 Public Sub New(ByVal _X As Single , ByVal _Y As Single , ByVal _Z As Single)

10 x = _X

11 y = _Y

12 z = _Z

13 End Sub

1415 Public Function Copy() As Point3D

16 Return New Point3D(x, y, z)

17 End Function

1819 Public Sub New()

20 End Sub

2122 Public Sub Clear()

23 x = 0

24 y = 0

25 z = 0

26 End Sub

2728 Public Shadows Function Equals(ByVal p As Point3D) As Boolean

29 Return x = p.x AndAlso y = p.y AndAlso z = p.z

30 End Function

3132 Public Function IntEquals(ByVal p As Point3D) As Boolean

33 ’Carries out the check but rounds the values to integers , due to the calculations used to find intersections

34 ’these can sometimes come out as close approximations , i.e. instead of 20 they give 19.999999999998.

35 ’These should be the same , so intEquals would return true for this case.

36 If Not (Single.IsNaN(x) AndAlso Single.IsNaN(y) AndAlso Single.IsNaN(z)) Then

37 Return CInt(x) = CInt(p.x) AndAlso CInt(y) = CInt(p.y) AndAlso CInt(z) = CInt(p.z)

38 Else

39 Return False

40 End If

41 End Function

42 End Class

4344 Public Class Matrix

45 Public matrix(,) As Single

46 Public Identity As Boolean

4748 Public Sub New()

49 ’This is a matrix class designed just for the loading of the lego models

50 ’so will only be used for loading the part files , and only requires 3x3

51 ’matrices

52 ReDim matrix(2, 3)

53 Identity = False

54 End Sub

5556 Public Sub New(ByVal data(,) As Single)

57 ’Can fill it with a different matrix

58 matrix = data

59 Identity = CheckIdentity ()

60 End Sub

54

Page 62: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

6162 Public Sub New(ByVal part() As String , ByVal startIndex As Integer)

63 ’For speed and memory doesn ’t bother to store the 0,0,0,1 column of the homegenious matrix

64 ’Creates the matrix directly from the string array obtained from the lego file.

6566 ’Takes the string array and the start and finish of it and will create a square matrix.

67 ’Fills it in top to bottom left to right (i.e. goes down the 1st column then down the 2nd , then down the 3rd)

6869 ReDim matrix(2, 3)

70 For x As Integer = 0 To 2

71 For y As Integer = 0 To 2

72 ’The + 3 moves over the x,y,z values which are added at the end

73 matrix(x, y) = CSng(part(startIndex + 3 + (x * 3) + y))

74 Next

75 Next

76 For x As Integer = 0 To 2

77 matrix(x, 3) = CSng(part(startIndex + x))

78 Next

7980 Identity = CheckIdentity ()

81 End Sub

8283 Private Function CheckIdentity () As Boolean

84 Return matrix(0, 0) = 1 AndAlso matrix(1, 1) = 1 AndAlso matrix(2, 2) = 1 AndAlso _

85 matrix(0, 1) = 0 AndAlso matrix(0, 2) = 0 AndAlso _

86 matrix(1, 0) = 0 AndAlso matrix(1, 2) = 0 AndAlso _

87 matrix(2, 0) = 0 AndAlso matrix(2, 1) = 0

88 End Function

8990 Public ReadOnly Property IsReversed () As Boolean

91 Get

92 ’Reversed Matrices are those which have a negative determinant .

93 ’Remove the x,y,z entries on the bottom row of the matrix , as these aren ’t needed for this calculation

94 Dim tmpMatrix (2, 2) As Single

95 For c1 As Integer = 0 To 2

96 For c2 As Integer = 0 To 2

97 tmpMatrix(c1, c2) = matrix(c1, c2)

98 Next

99 Next

100 Return Determinant(tmpMatrix) < 0

101 End Get

102 End Property

103104 Private Function Determinant(ByVal Mat(,) As Single) As Single

105 ’Just needs to be done for a 3x3 matrix in this application , so hard codes a lot of the calculated values

106 ’such as -ve or +ve signs , and recursive nature of finding each determinate as these are known for a fixed

107 ’matrix size , and is faster done hard coded to 3x3 matrix size.

108109 Return (Mat(0, 0) * ((Mat(1, 1) * Mat(2, 2)) - (Mat(2, 1) * Mat(1, 2)))) _

110 - (Mat(1, 0) * ((Mat(0, 1) * Mat(2, 2)) - (Mat(2, 1) * Mat(0, 2)))) _

111 + (Mat(2, 0) * ((Mat(0, 1) * Mat(1, 2)) - (Mat(1, 1) * Mat(0, 2))))

112 End Function

113114 End Class

115116 Public Enum eVertexDirection

117 Clockwise

118 CounterClockWise

119 End Enum

120121 Public Shared Function CalcNormal(ByVal Points As Point3D ()) As Point3D

122 ’Triangle or Quadralatural - Count the points in the array

123 Dim p1, p2 As Point3D

124 Dim ret As Point3D = Nothing

125 Select Case Points.Length

126 Case 3 ’Triangle

127 p1 = SubVector(Points (1), Points (0))

128 p2 = SubVector(Points (2), Points (0))

129 ret = CrossProductVector(p1 , p2)

130 Case 4 ’Quad

131 p1 = SubVector(Points (1), Points (0))

132 p2 = SubVector(Points (3), Points (0))

133 ret = CrossProductVector(p1 , p2)

134 End Select

135 If Not ret Is Nothing Then

136 Return NormaliseVector(ret)

137 Else

138 Return Nothing ’ERROR incorrect shape

139 End If

140 End Function

141142 Public Shared Function NormaliseVector(ByVal vec As Point3D) As Point3D

143 Dim res As Point3D

144 With vec

145 Dim scale As Single = CSng(1 / MagnitudeVector(vec))

146 res = New Point3D (.x * scale , .y * scale , .z * scale)

147 End With

148 Return res

149 End Function

150151 Public Shared Function MagnitudeVector(ByVal vec As Point3D) As Double

152 With vec

153 Return Math.Sqrt ((.x ^ 2) + (.y ^ 2) + (.z ^ 2))

154 End With

155 End Function

55

Page 63: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

156157 Public Shared Function CrossProductVector(ByVal a As Point3D , ByVal b As Point3D) As Point3D ’=a x b

158 Dim C As New Point3D

159 C.x = a.y * b.z - a.z * b.y

160 C.y = a.z * b.x - a.x * b.z

161 C.z = a.x * b.y - a.y * b.x

162 Return C

163 End Function

164165 Public Shared Function CrossProductMagnitude(ByVal a As Point3D , ByVal b As Point3D) As Double ’=|a x b|

166 Return Math.Abs(MagnitudeVector(a)) * Math.Abs(MagnitudeVector(b)) * _

167 Math.Sqrt(1 - (DotProductVector(NormaliseVector(a), NormaliseVector(b))) ^ 2)

168 End Function

169170 Public Shared Function DotProductVector(ByVal a As Point3D , ByVal b As Point3D) As Double ’= a . b

171 Return (a.x * b.x) + (a.y * b.y) + (a.z * b.z)

172 End Function

173174 Public Shared Function SubVector(ByVal a As Point3D , ByVal b As Point3D) As Point3D ’= a - b

175 Return New Point3D(a.x - b.x, a.y - b.y, a.z - b.z)

176 End Function

177178 Public Shared Function AddVector(ByVal a As Point3D , ByVal b As Point3D) As Point3D ’= a - b

179 Return New Point3D(a.x + b.x, a.y + b.y, a.z + b.z)

180 End Function

181182 Public Shared Function ScaleVector(ByVal p As Point3D , ByVal scaler As Single) As Point3D

183 Return New Point3D(p.x * scaler , p.y * scaler , p.z * scaler)

184 End Function

185186 Public Enum eInstruction

187 Line

188 Triangle

189 Quadrilateral

190 Colour

191 Normal

192 End Enum

193194 Public Enum eInterceptType

195 None

196 Intercept

197 Internal

198 End Enum

199200 Public Enum eSmoothMethod

201 Taubin

202 [Loop]

203 Laplacian

204 End Enum

205206 Public Structure InstructionSet

207 Dim Instructions () As eInstruction

208 Dim Values () As Single

209 End Structure

210211 Public Shared Function MakeTriangles(ByVal Quad As Part_Quadrilateral) As Point3D ()()

212 ’Triangles defined in this order of vertices , so the devide line through the

213 ’middle of the quad is defined by the first and last vertex of the triangle

214 ’this allows me to check if a point is on the diagonal line , and therefore

215 ’actually internal , and not intercepting in the DoesIntercept function

216 Dim t1() As Point3D = New Point3D () {Quad.P1 , Quad.P2, Quad.P3}

217 Dim t2() As Point3D = New Point3D () {Quad.P3 , Quad.P4, Quad.P1}

218 Dim ret ()() As Point3D = New Point3D ()() {t1 , t2}

219 Return ret

220 End Function

221222 Public Shared Sub RemoveDuplicates(ByRef arr As ArrayList)

223 Dim i As Integer = 0

224 Dim i2 As Integer = 0

225 While i < (arr.Count - 1)

226 i2 = i + 1

227 While i2 < (arr.Count)

228 If DirectCast(arr(i), Point3D ). Equals(DirectCast(arr(i2), Point3D )) Then

229 arr.RemoveAt(i2)

230 i2 -= 1

231 End If

232 i2 += 1

233 End While

234 i += 1

235 End While

236 End Sub

237238 End Class

56

Page 64: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.2 datReader.vb

The file parser used to load the LEGO LDraw files into the internal representation.1 Imports LEGO_Smoothing.Common

2 Imports LEGO_Smoothing.ModelDefs

34 Public Class datReader

56 Private Shared loadedModels As ModelDefs.LegoModels

78 Public Shared Function LoadLegoFile(ByVal LDrawFolder As String , ByVal Filename As String) As LegoModel

9 loadedModels = New LegoModels ’Clears the model information

10 Dim lm As LegoModel = ReadLEGOFile(LDrawFolder , Filename , False)

11 Transformer.TransformModel(lm)

12 Return lm

13 End Function

1415 Private Shared Function ReadLEGOFile(ByVal LDrawFolder As String , ByVal Filename As String , _

16 ByVal Invert As Boolean) As LegoModel

1718 Dim fullName As String = Filename

19 Dim InvertNext As Boolean = False

20 Dim InvertNextCount As Integer = 0

2122 Dim mVertexDir As eVertexDirection = eVertexDirection.CounterClockWise ’Files default to counterclockwise

2324 If Not IO.Directory.Exists(LDrawFolder) Then

25 MsgBox("Invalid Lego Part Folder: " & LDrawFolder , MsgBoxStyle.OkOnly Or MsgBoxStyle.Critical , "Error")

26 Return Nothing

27 End If

2829 ’Check if the filename is is a complete path to the model , or just the name of a part.

30 ’If it is a complete path and exists - just use it. Else try and find it in the parts folders

3132 If Not IO.File.Exists(fullName) Then

33 ’Folder structure allows for lego parts to be either in a folder named "P"

34 ’or a folder named "PARTS" withing the LDrawFolder . So need to check where it is

35 fullName = LDrawFolder & "\P\" & Filename

36 If Not IO.File.Exists(fullName) Then

37 fullName = LDrawFolder & "\PARTS\" & Filename

38 If Not IO.File.Exists(fullName) Then

39 Return Nothing

40 End If

41 End If

42 End If

4344 Dim name As String = New IO.FileInfo(fullName ).Name

45 Dim sr As New IO.StreamReader(fullName)

46 Dim retModel As New LegoModel

4748 While Not sr.Peek = -1

49 Dim line As String = sr.ReadLine.ToLower

50 If Not (line Is Nothing OrElse line.Trim = "") Then

51 Dim parts () As String = line.TrimStart.Split(" "c)

52 parts = SortParts(parts) ’removes "" entries where multiple spaces have been used

5354 Select Case (parts (0))

55 Case ""

56 ’Empty lines can be ignored

5758 Case "0" ’Comment / Meta Command

59 ’Some meta commands may be impletmented

6061 ’Detect if shape declared counter clockwise or clockwise.

62 ’OPENGL supports counter clockwise

63 If line.Contains("bfc") Then

64 If line.Contains("ccw") Then ’Following shapes in counterclockwise vertex order

65 mVertexDir = eVertexDirection.CounterClockWise

66 ElseIf line.Contains("cw") And Not line.Contains("ccw") Then

67 ’Following shapes in Clockwise vertex order

68 mVertexDir = eVertexDirection.Clockwise

69 ElseIf line.Contains("invertnext") Then

70 InvertNext = True

71 InvertNextCount = 0

72 End If

73 End If

7475 Case "1" ’Part - Files that represent other lego parts/models + colour + transformation

7677 Dim lp As New Part_External

78 lp.colour = CInt(parts (1))

79 lp.transformMatrix = New Matrix(parts , 2)

80 Dim matrixReversed As Boolean = lp.transformMatrix.IsReversed

81 InvertNext = (InvertNext Xor matrixReversed) Xor Invert

82 ’InvertNext = (InvertNext Xor lp.transformMatrix.IsReversed) Xor Invert

83 ’Recursive call to load the lego model described by the part file

84 ’Checks if the part has already been loaded before.

85 ’If so will use the already loaded version.

86 lp.inverted = InvertNext

8788 ’InvertNext and the counter InvertNextCount works when the line before a part specifies

89 ’invert next. However if the matrix of the current line says to invert , then want to make

90 ’sure invert next is droped before the next line after this. So incrementing the

57

Page 65: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

91 ’invertnextcount will make this work

9293 If matrixReversed Then InvertNextCount += 1

9495 If Not loadedModels.ModelExist(parts (14)) Then

96 Dim tmpModel As LegoModel = ReadLEGOFile(LDrawFolder , parts (14), InvertNext)

97 If tmpModel Is Nothing Then

98 MsgBox("Error loading referenced part:" & parts (14))

99 ’Won ’t add the part if it can ’t load

100 Else

101 loadedModels.addModel(parts (14), tmpModel)

102 lp.part = tmpModel

103 End If

104 Else

105 lp.part = loadedModels.getModel(parts (14))

106 End If

107 lp.Stud = name.ToLower.Contains("stud")

108 lp.Name = name.ToLower

109 retModel.addPart(lp)

110111 Case "2" ’Line - Defined by two points + colour

112 Dim lp As New Part_Line

113 lp.colour = CInt(parts (1))

114 lp.P1 = SortPoint3D(parts , 2)

115 lp.P2 = SortPoint3D(parts , 5)

116 retModel.addPart(lp)

117118 Case "3" ’Triangle - Defined by 3 points + colour

119 Dim lp As New Part_Triangle

120 lp.colour = CInt(parts (1))

121122 If (mVertexDir = eVertexDirection.Clockwise) Then

123 lp.P1 = SortPoint3D(parts , 8)

124 lp.P2 = SortPoint3D(parts , 5)

125 lp.P3 = SortPoint3D(parts , 2)

126 Else

127 lp.P1 = SortPoint3D(parts , 2)

128 lp.P2 = SortPoint3D(parts , 5)

129 lp.P3 = SortPoint3D(parts , 8)

130 End If

131132 ’lp.Norm = Common.CalcNormal(Invert , New Point3D () {lp.P1, lp.P2, lp.P3})

133 retModel.addPart(lp)

134135 Case "4" ’Quadrilateral - Defined by 4 points + colour

136 Dim lp As New Part_Quadrilateral

137 lp.colour = CInt(parts (1))

138139 If (mVertexDir = eVertexDirection.Clockwise) Then

140 lp.P1 = SortPoint3D(parts , 8)

141 lp.P2 = SortPoint3D(parts , 5)

142 lp.P3 = SortPoint3D(parts , 2)

143 lp.P4 = SortPoint3D(parts , 11)

144 Else

145 lp.P1 = SortPoint3D(parts , 2)

146 lp.P2 = SortPoint3D(parts , 5)

147 lp.P3 = SortPoint3D(parts , 8)

148 lp.P4 = SortPoint3D(parts , 11)

149 End If

150151152 retModel.addPart(lp)

153154 Case "5" ’Special Line - Defined by 4 points + colour

155 Dim lp As New Part_SpecialLine

156 lp.colour = CInt(parts (1))

157 lp.LineP1 = SortPoint3D(parts , 2)

158 lp.LineP2 = SortPoint3D(parts , 5)

159 lp.TestP1 = SortPoint3D(parts , 8)

160 lp.TestP2 = SortPoint3D(parts , 11)

161 retModel.addPart(lp)

162163 End Select

164 End If

165166 If InvertNext Then InvertNextCount += 1

167 If InvertNext AndAlso InvertNextCount > 1 Then InvertNext = False

168 End While

169170171 sr.Close ()

172173 Return retModel

174175 End Function

176177 Private Shared Function SortParts(ByVal Parts () As String) As String ()

178 If Parts.Length = 0 Then Return Parts

179 Dim al As New ArrayList

180 For Each s As String In Parts

181 If Not s = "" Then al.Add(s)

182 Next

183 Return DirectCast(al.ToArray(GetType(String)), String ())

184 End Function

185

58

Page 66: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

186 Private Shared Function SortPoint3D(ByVal Parts() As String , ByVal startIndex As Integer) As Point3D

187 ’Takes the parts string array loaded from the current line in the file , and

188 ’then loads the startindex and next 2 of the items into a new point3D object

189 Return New Point3D(CSng(Parts(startIndex )), CSng(Parts(startIndex + 1)), CSng(Parts(startIndex + 2)))

190 End Function

191192 End Class

59

Page 67: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.3 Form1.vb

The main form which the user controls the program from. It is the central partof the program controlling the calling of loading, mesh conversion subdivision andsmoothing.

1 Imports LEGO_Smoothing.Common

23 Public Class Form1

4 Inherits System.Windows.Forms.Form

56 Private WithEvents mView As OpenGLViewer

7 Private thrOpenGL As Threading.Thread

8 Private mLegoModel As ModelDefs.LegoModel

9 Private mUnsurfacedLegoModel As ModelDefs.LegoModel

10 Private mUnsmoothedModel As ModelDefs.LegoModel

1112 Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)

13 MyBase.OnLoad(e)

14 ’Hard coded part folder - just for speed. Could become a registry entry in the future

15 lblPartFolder.Text = "C:\ Documents and Settings\Michael Ball\My Documents\Uni\Year 3\ Semester 2\" _

16 + "CM30082 - Double Module Project\Lego Parts"

17 mView = New OpenGLViewer

18 mView.Parent = pnlOpenGLHolder

19 mView.Dock = DockStyle.Fill

20 mView.AllowDrop = True

21 End Sub

2223 Private Sub cmdLoadModel_Click(ByVal sender As System.Object , ByVal e As System.EventArgs) _

24 Handles cmdLoadModel.Click

2526 If New IO.DirectoryInfo(lblPartFolder.Text). Exists Then

27 Dim file As New OpenFileDialog

28 file.CheckFileExists = True

29 file.CheckPathExists = True

30 file.ShowHelp = False

31 file.ValidateNames = True

32 file.Title = "Select Model To Load"

33 file.InitialDirectory = lblPartFolder.Text

34 file.Filter = "Lego Files (*.ldr; *.dat )|*. ldr ;*.dat"

35 file.Multiselect = False

36 If file.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then

37 LoadModel(file.FileName)

38 End If

39 Else

40 MsgBox("Invalid Part Folder", MsgBoxStyle.OkOnly Or MsgBoxStyle.Critical , "Error")

41 End If

42 End Sub

4344 Private Sub LoadModel(ByVal FileName As String)

45 If Not thrOpenGL Is Nothing Then thrOpenGL.Abort () ’Stop the current display of the current model

46 mLegoModel = datReader.LoadLegoFile(lblPartFolder.Text , FileName)

47 If mLegoModel Is Nothing Then

48 MsgBox("ERROR LOADING MODEL: FileName")

49 Else

50 ’Used to confirm loading , then display model button would be pressed , now it just displays if loading

51 ’was successful

52 updateInstructionSet ()

53 thrOpenGL = New Threading.Thread(AddressOf OpenGL_Display)

54 thrOpenGL.Start()

55 End If

56 mUnsurfacedLegoModel = mLegoModel

57 chkOuterShell.Checked = False

58 End Sub

5960 Private Sub cmdPart_Click(ByVal sender As System.Object , ByVal e As System.EventArgs) Handles cmdPart.Click

61 Dim fldr As New FolderBrowserDialog

62 fldr.Description = "Select Lego Parts Folder"

63 fldr.ShowNewFolderButton = False

64 If fldr.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then

65 If Not thrOpenGL Is Nothing Then thrOpenGL.Abort() ’Stop the current display of the current model

66 lblPartFolder.Text = fldr.SelectedPath

67 End If

68 End Sub

6970 Private FPSstartTime As DateTime = Now

71 Private FPSCount As Integer = 0

7273 Delegate Sub UpdateFPSTextCallBack(ByVal text As String)

7475 Private Sub UpdateFPSText(ByVal text As String)

76 If Me.lblFPS.InvokeRequired Then

77 Try

78 Dim d As New UpdateFPSTextCallBack(AddressOf UpdateFPSText)

79 Me.Invoke(d, New Object () {text})

80 Catch ex As Exception

81 ’Only errors on close when there is no object to invoke. I.e. the main form has closed.

82 ’Therefore don ’t care about the error , as the program is no longer really running.

83 End Try

84 Else

85 lblFPS.Text = text

86 End If

60

Page 68: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

87 End Sub

8889 Private Sub OpenGL_Display ()

90 While True

91 If Now.Subtract(FPSstartTime ). TotalSeconds > 1 Then

92 FPSstartTime = Now

93 UpdateFPSText(CStr(FPSCount ))

94 FPSCount = 0

95 Else

96 FPSCount += 1

97 End If

9899 mView.Refresh ()

100 ’A small slow down. Should really be checked against FPS so as to hold it at a sensible rate

101 Threading.Thread.Sleep (12)

102 End While

103 End Sub

104105 Private Sub cmdShot_Click(ByVal sender As System.Object , ByVal e As System.EventArgs) Handles cmdShot.Click

106 Me.Enabled = False

107 Try

108 Dim bm As Bitmap = mView.takeScreenShot ()

109 If IO.File.Exists("c:\tmp.bmp") Then

110 IO.File.Delete("c:\tmp.bmp")

111 End If

112 bm.Save("c:\tmp.bmp")

113 Catch ex As Exception

114 MsgBox("Error saving snap shot file." & vbCrLf & ex.Message , MsgBoxStyle.OkOnly Or _

115 MsgBoxStyle.Critical , "Error")

116 Finally

117 Me.Enabled = True

118 End Try

119 End Sub

120121 Private Sub cmdLoadPyramid_Click(ByVal sender As System.Object , ByVal e As System.EventArgs) _

122 Handles cmdLoadPyramid.Click

123124 LoadModel("C:\ Documents and Settings\Michael Ball\Desktop\Lego Stuff\Pyramid.dat")

125 End Sub

126127 Private Sub Form1_MouseWheel(ByVal sender As Object , ByVal e As System.Windows.Forms.MouseEventArgs) _

128 Handles Me.MouseWheel

129 ’Pass this event through to the openglviewer

130 mView.OpenGLViewer_MouseWheel(sender , e)

131 End Sub

132133 Private Sub OptionsChanged(ByVal sender As System.Object , ByVal e As System.EventArgs) _

134 Handles chkStuds.CheckedChanged , chkNorms.CheckedChanged , chkBounds.CheckedChanged

135 updateInstructionSet ()

136 End Sub

137138 Private Sub updateInstructionSet ()

139 If Not mView Is Nothing Then

140 mView.InstructionList = ListRenderer.ListModel(mLegoModel , chkStuds.Checked , chkWireframe.Checked , _

141 chkNorms.Checked , chkBounds.Checked , chkOuterShell.Checked)

142 End If

143 End Sub

144145 Private Sub chkWireframe_CheckedChanged(ByVal sender As System.Object , ByVal e As System.EventArgs) _

146 Handles chkWireframe.CheckedChanged

147148 ’Disables this option as it can ’t be deactivated in this mode

149 chkBounds.Enabled = Not (chkWireframe.Checked Or chkOuterShell.Checked)

150 If Not mView Is Nothing Then

151 mView.WireFrame = chkWireframe.Checked

152 updateInstructionSet ()

153 End If

154 End Sub

155156 Private Sub chkOuterShell_CheckedChanged(ByVal sender As System.Object , ByVal e As System.EventArgs) _

157 Handles chkOuterShell.CheckedChanged

158159 chkStuds.Enabled = Not chkOuterShell.Checked ’Disables these options as they can ’t be activated in this mode

160 chkBounds.Enabled = Not (chkOuterShell.Checked Or chkWireframe.Checked)

161 chkShowInterceptions.Enabled = chkOuterShell.Checked

162 chkSmooth.Checked = False

163 chkSmooth.Enabled = chkOuterShell.Checked

164165 If chkOuterShell.Checked Then

166 If Not mLegoModel Is Nothing Then

167 mUnsurfacedLegoModel = mLegoModel

168 mLegoModel = SurfaceFinder.GetOuterSurface(mLegoModel , chkShowInterceptions.Checked ).copy

169 End If

170 ElseIf Not mUnsurfacedLegoModel Is Nothing Then

171 mLegoModel = mUnsurfacedLegoModel

172 End If

173174 updateInstructionSet ()

175 End Sub

176177 Private Sub cmdLoad2Bricks_Click(ByVal sender As System.Object , ByVal e As System.EventArgs) _

178 Handles cmdLoadTestModel.Click

179180 LoadModel("C:\ Documents and Settings\Michael Ball\Desktop \3 bricks.dat")

181 End Sub

61

Page 69: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

182183 Private Sub mView_DragDrop(ByVal sender As Object , ByVal e As System.Windows.Forms.DragEventArgs) _

184 Handles mView.DragDrop

185186 ’ Handle FileDrop data.

187 If e.Data.GetDataPresent(DataFormats.FileDrop) Then

188 ’ Assign the file names to a string array , in

189 ’ case the user has selected multiple files.

190 Dim files As String () = CType(e.Data.GetData(DataFormats.FileDrop), String ())

191 Try

192 LoadModel(files (0))

193 Catch ex As Exception

194 MessageBox.Show(ex.Message)

195 Return

196 End Try

197 End If

198199 End Sub

200201 Private Sub mView_DragOver(ByVal sender As Object , ByVal e As System.Windows.Forms.DragEventArgs) _

202 Handles mView.DragOver

203204 e.Effect = DragDropEffects.All

205 End Sub

206207 Private Sub cmdLoad2Bricks_Click_1(ByVal sender As System.Object , ByVal e As System.EventArgs) _

208 Handles cmdLoad2Bricks.Click

209210 LoadModel("C:\ Documents and Settings\Michael Ball\Desktop \2 bricks.dat")

211 End Sub

212213 Private Sub chkShowInterceptions_CheckedChanged(ByVal sender As System.Object , ByVal e As System.EventArgs) _

214 Handles chkShowInterceptions.CheckedChanged

215 mLegoModel = SurfaceFinder.GetOuterSurface(mLegoModel , chkShowInterceptions.Checked)

216 updateInstructionSet ()

217 End Sub

218219 Private Sub chkSmooth_CheckedChanged(ByVal sender As System.Object , ByVal e As System.EventArgs) _

220 Handles chkSmooth.CheckedChanged

221 Dim smoothMethod As eSmoothMethod

222 Select Case True

223 Case optLaplacian.Checked

224 smoothMethod = eSmoothMethod.Laplacian

225 Case optTaubin.Checked

226 smoothMethod = eSmoothMethod.Taubin

227 Case optLoops.Checked

228 smoothMethod = eSmoothMethod.Loop

229 End Select

230231 If chkSmooth.Checked Then

232 If Not mLegoModel Is Nothing Then

233 mUnsmoothedModel = mLegoModel

234 mLegoModel = Smoother.SmoothShape(mLegoModel , smoothMethod , CInt(nudSubdivisions.Value), _

235 CInt(nudSmoothing.Value), Me).copy

236 End If

237 ElseIf Not mUnsurfacedLegoModel Is Nothing Then

238 mLegoModel = mUnsmoothedModel

239 End If

240241 updateInstructionSet ()

242 End Sub

243244 Private Sub SmoothingOptionsChanged_CheckedChanged(ByVal sender As System.Object , ByVal e As System.EventArgs) _

245 Handles optLoops.CheckedChanged , optLaplacian.CheckedChanged , optTaubin.CheckedChanged

246247 chkSmooth.Checked = False

248249 End Sub

250 End Class

62

Page 70: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.4 ListRenderer.vb

Creates the instruction and value stacks from the internal representation.1 Imports LEGO_Smoothing.ModelDefs

2 Imports LEGO_Smoothing.Common

34 Public Class ListRenderer

56 Private Shared mShowStuds As Boolean

7 Private Shared mWireframe As Boolean

8 Private Shared mShowNorms As Boolean

9 Private Shared mShowBounds As Boolean

10 Private Shared mShowOuterShell As Boolean

1112 Private Shared mInstructions As New ArrayList

13 Private Shared mValues As New ArrayList

1415 Private Shared mCurCol As Single ()

1617 Public Shared Function ListModel(ByVal LM As LegoModel , ByVal ShowStuds As Boolean , _

18 ByVal Wireframe As Boolean , ByVal ShowNorms As Boolean , ByVal showBounds As Boolean , _

19 ByVal showOuterShell As Boolean) As Long

2021 ’This sub just allows defaults to be set , the realDrawModel does the work , and is called recursively

22 mShowStuds = ShowStuds

23 mWireframe = Wireframe

24 mShowNorms = ShowNorms

25 mShowBounds = showBounds

26 mShowOuterShell = showOuterShell

27 mValues.Clear()

28 mInstructions.Clear()

2930 ’Create the initial Identity Matrix

31 RealListModel(LM, False)

3233 mCurCol = Nothing ’Clear mCurCol

3435 Dim reIS As InstructionSet

36 reIS.Instructions = DirectCast(mInstructions.ToArray(GetType(eInstruction )), eInstruction ())

37 reIS.Values = DirectCast(mValues.ToArray(GetType(Single)), Single ())

38 Return Renderer.Render(reIS)

39 End Function

4041 Private Shared Sub RealListModel(ByVal LM As LegoModel , ByVal Inverted As Boolean)

42 If LM IsNot Nothing AndAlso LM.Parts IsNot Nothing Then

43 For Each p As LegoPart In LM.Parts

44 Select Case p.type

45 Case PartType.PartFile

46 DrawExternal(DirectCast(p, Part_External), Inverted)

47 Case PartType.Line

48 DrawLine(DirectCast(p, Part_Line ))

49 Case PartType.Triangle

50 DrawTriangle(DirectCast(p, Part_Triangle), Inverted)

51 Case PartType.Quadrilateral

52 DrawQuad(DirectCast(p, Part_Quadrilateral), Inverted)

53 Case PartType.SpecialLine

54 DrawSpecialLine(DirectCast(p, Part_SpecialLine ))

55 End Select

56 Next

57 End If

58 End Sub

5960 Private Shared Sub DrawExternal(ByVal p As Part_External , ByVal Inverted As Boolean)

61 If p.Stud And (Not mShowStuds) Then ’Or mShowOuterShell ) Then

62 Exit Sub ’Won ’t draw studs

63 End If

6465 RealListModel(p.part , p.inverted Xor Inverted)

66 End Sub

6768 Private Shared Sub DrawLine(ByVal p As Part_Line)

69 ’Wire frame now done by culling front and back of polygons

70 ’so don ’t want to draw the lines aswell

7172 If ((Not mShowBounds) Or mWireframe) And (Not mShowOuterShell) Then Exit Sub

73 AddColour(p.RealColour)

7475 mInstructions.Add(eInstruction.Line)

76 AddPointValues(p.P1)

77 AddPointValues(p.P2)

78 End Sub

7980 Private Shared Sub DrawTriangle(ByVal p As Part_Triangle , ByVal Inverted As Boolean)

81 ’If mWireframe Then Exit Sub ’or mShowOuterShell Then Exit Sub

82 If mShowNorms Then DrawNormal(p.Norm , p)

83 With p

84 AddColour (. RealColour)

8586 mInstructions.Add(eInstruction.Triangle)

87 AddPointValues (.Norm)

88 AddPointValues (.P1)

89 AddPointValues (.P2)

90 AddPointValues (.P3)

63

Page 71: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

91 End With

92 End Sub

9394 Private Shared Sub DrawQuad(ByVal p As Part_Quadrilateral , ByVal Inverted As Boolean)

95 If mShowNorms Then DrawNormal(p.Norm , p)

96 ’If mWireframe Then Exit Sub

9798 With p

99 AddColour (. RealColour)

100101 mInstructions.Add(eInstruction.Quadrilateral)

102 AddPointValues (.Norm)

103 AddPointValues (.P1)

104 AddPointValues (.P2)

105 AddPointValues (.P3)

106 AddPointValues (.P4)

107 End With

108 End Sub

109110 Private Shared Sub DrawSpecialLine(ByVal p As Part_SpecialLine)

111 Dim pLine As New Part_Line

112 pLine.colour = p.colour

113 pLine.RealColour = p.RealColour

114 pLine.P1 = p.LineP1

115 pLine.P2 = p.LineP2

116 DrawLine(pLine)

117 End Sub

118119 Private Shared Sub DrawNormal(ByVal Norm As Point3D , ByVal part As LegoPart)

120121 Dim startp As Point3D = Nothing

122123 If TypeOf part Is Part_Quadrilateral Then

124 With DirectCast(part , Part_Quadrilateral)

125 ’startp = Common.SubVector (.P3 , .P1)

126 ’startp = New Point3D (.P3.x - startp.x / 2, .P3.y - startp.y / 2, .P3.z - startp.z / 2)

127 startp = New Point3D ((.P1.x + .P2.x + .P3.x + .P4.x) / 4, (.P1.y + .P2.y + .P3.y + .P4.y) / 4, _

128 (.P1.z + .P2.z + .P3.z + .P4.z) / 4)

129 End With

130 ElseIf TypeOf part Is Part_Triangle Then

131 With DirectCast(part , Part_Triangle)

132 startp = New Point3D ((.P1.x + .P2.x + .P3.x) / 3, (.P1.y + .P2.y + .P3.y) / 3, _

133 (.P1.z + .P2.z + .P3.z) / 3)

134 End With

135 End If

136 Dim endP1 As New Point3D(startp.x + (Norm.x * 4), startp.y + (Norm.y * 4), startp.z + (Norm.z * 4))

137 Dim endP2 As New Point3D(endP1.x + (Norm.x * 2), endP1.y + (Norm.y * 2), endP1.z + (Norm.z * 2))

138 Dim endP3 As New Point3D(startP.x - (Norm.x * 2), startP.y - (Norm.y * 2), startP.z - (Norm.z * 2))

139140 mInstructions.Add(eInstruction.Normal)

141 mValues.Add (0.0F)

142 mValues.Add (0.0F)

143 mValues.Add (1.0F)

144 AddPointValues(startP)

145 AddPointValues(endP1)

146 mValues.Add (1.0F)

147 mValues.Add (0.0F)

148 mValues.Add (0.0F)

149 AddPointValues(endP1)

150 AddPointValues(endP2)

151 mValues.Add (0.0F)

152 mValues.Add (1.0F)

153 mValues.Add (0.0F)

154 AddPointValues(startP)

155 AddPointValues(endP3)

156 mCurCol = New Single () {0.0F, 1.0F, 0.0F}

157 End Sub

158159 Private Shared Sub AddColour(ByVal colour As Single ())

160 ’Check if colour is already correct , if so don ’t add it again , will cut down instruction and value list lengths

161 ’and will mean sending less commands to OPENGL.

162 If Not mCurCol Is Nothing AndAlso colour.Length = mCurCol.Length Then

163 Dim count As Integer = 0

164 For i As Integer = 0 To colour.Length - 1

165 If colour(i) = mCurCol(i) Then

166 count += 1

167 Else

168 ’If one fails then not the same so can exit the loop , as count will never reach

169 ’colour.length anyway

170 Exit For

171 End If

172 Next

173 If count = colour.Length Then

174 Exit Sub

175 End If

176177 End If

178179 mInstructions.Add(eInstruction.Colour)

180 For i As Integer = 0 To colour.Length - 1

181 mValues.Add(colour(i))

182 Next

183 ’Need to pad with 1, i.e. if the alpha isn ’t set , otherwise the render will error as it doesn ’t carry out any

184 ’checks for speed

185

64

Page 72: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

186 If colour.Length = 3 Then

187 mValues.Add (1.0F)

188 End If

189190 mCurCol = colour

191 End Sub

192193 Private Shared Sub AddPointValues(ByVal P As Point3D)

194 With P

195 mValues.Add(.x)

196 mValues.Add(.y)

197 mValues.Add(.z)

198 End With

199 End Sub

200201 End Class

65

Page 73: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.5 ModelDefs.vb

Defines the different objects used within the internal representation (e.g the line,quadrilateral, and triangle parts).

1 Imports LEGO_Smoothing.Common

23 Public Class ModelDefs

4 Public Enum PartType

5 PartFile = 1

6 Line = 2

7 Triangle = 3

8 Quadrilateral = 4

9 SpecialLine = 5

10 End Enum

1112 Public MustInherit Class LegoPart

13 Public type As PartType

14 Public colour As Integer

15 Public RealColour (2) As Single

1617 Public MustOverride Function Copy() As LegoPart

18 End Class

1920 Public Class Part_External

21 Inherits LegoPart

22 Public part As LegoModel

23 Public transformMatrix As Matrix

24 Public Stud As Boolean

25 Public inverted As Boolean = False

26 Public Name As String

2728 Public Sub New()

29 type = PartType.PartFile

30 End Sub

3132 Public Overrides Function Copy() As LegoPart

33 Dim ret As New Part_External

34 ret.colour = Me.colour

35 If Me.RealColour.Length = 3 Then

36 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2)}

37 Else

38 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2), Me.RealColour (3)}

39 End If

40 ret.Name = Me.Name

41 ret.inverted = Me.inverted

42 ret.Stud = Me.Stud

43 ret.transformMatrix = Me.transformMatrix

44 ret.part = Me.part.copy

45 Return ret

46 End Function

47 End Class

4849 Public Class Part_Line

50 Inherits LegoPart

51 Public P1 As Point3D

52 Public P2 As Point3D

5354 Public Sub New()

55 type = PartType.Line

56 End Sub

5758 Public Overrides Function Copy() As LegoPart

59 Dim ret As New Part_Line

60 ret.colour = Me.colour

61 If Me.RealColour.Length = 3 Then

62 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2)}

63 Else

64 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2), Me.RealColour (3)}

65 End If

66 ret.P1 = Me.P1.Copy

67 ret.P2 = Me.P2.Copy

68 Return ret

69 End Function

70 End Class

7172 Public Class Part_Triangle

73 Inherits LegoPart

74 Public P1 As Point3D

75 Public P2 As Point3D

76 Public P3 As Point3D

77 Public Norm As Point3D

7879 Public Sub New()

80 type = PartType.Triangle

81 End Sub

8283 Public Overrides Function Copy() As LegoPart

84 Dim ret As New Part_Triangle

85 ret.colour = Me.colour

86 If Me.RealColour.Length = 3 Then

87 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2)}

88 Else

66

Page 74: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

89 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2), Me.RealColour (3)}

90 End If

91 ret.P1 = Me.P1.Copy

92 ret.P2 = Me.P2.Copy

93 ret.P3 = Me.P3.Copy

94 If Me.Norm IsNot Nothing Then ret.Norm = Me.Norm.Copy

95 Return ret

96 End Function

97 End Class

9899 Public Class Part_Quadrilateral

100 Inherits LegoPart

101 Public P1 As Point3D

102 Public P2 As Point3D

103 Public P3 As Point3D

104 Public P4 As Point3D

105 Public Norm As Point3D

106107 Public Sub New()

108 type = PartType.Quadrilateral

109 End Sub

110111 Public Overrides Function Copy() As LegoPart

112 Dim ret As New Part_Quadrilateral

113 ret.colour = Me.colour

114 If Me.RealColour.Length = 3 Then

115 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2)}

116 Else

117 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2), Me.RealColour (3)}

118 End If

119 ret.P1 = Me.P1.Copy

120 ret.P2 = Me.P2.Copy

121 ret.P3 = Me.P3.Copy

122 ret.P4 = Me.P4.Copy

123 If Me.Norm IsNot Nothing Then ret.Norm = Me.Norm.Copy

124 Return ret

125 End Function

126 End Class

127128 Public Class Part_SpecialLine

129 Inherits LegoPart

130 Public LineP1 As Point3D

131 Public LineP2 As Point3D

132 Public TestP1 As Point3D

133 Public TestP2 As Point3D

134135 Public Sub New()

136 type = PartType.SpecialLine

137 End Sub

138139 Public Overrides Function Copy() As LegoPart

140 Dim ret As New Part_SpecialLine

141 ret.colour = Me.colour

142 If Me.RealColour.Length = 3 Then

143 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2)}

144 Else

145 ret.RealColour = New Single () {Me.RealColour (0), Me.RealColour (1), Me.RealColour (2), Me.RealColour (3)}

146 End If

147 ret.LineP1 = Me.LineP1.Copy

148 ret.LineP2 = Me.LineP2.Copy

149 ret.TestP1 = Me.TestP1.Copy

150 ret.TestP2 = Me.TestP2.Copy

151 Return ret

152 End Function

153 End Class

154155 Public Class LegoModels

156 Dim models As Hashtable

157158 Public Sub New()

159 models = New Hashtable

160 End Sub

161162 Public Sub addModel(ByVal Name As String , ByVal LM As LegoModel)

163 models.Add(Name , LM)

164 End Sub

165166 Public Function getModel(ByVal Name As String) As LegoModel

167 ’Clones models

168 If ModelExist(Name) AndAlso Not models(Name) Is Nothing Then

169 Return (DirectCast(models(Name), LegoModel )). copy

170 End If

171 Return Nothing

172 End Function

173174 Public Function ModelExist(ByVal Name As String) As Boolean

175 Return models.ContainsKey(Name)

176 End Function

177 End Class

178179 Public Class LegoModel

180 Public Parts As ArrayList

181182 Public Sub New()

183 Parts = New ArrayList

67

Page 75: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

184 End Sub

185186 Public Sub addPart(ByVal LP As LegoPart)

187 Parts.Add(LP)

188 End Sub

189190 Public Function getPart(ByVal index As Integer) As LegoPart

191 Return DirectCast(Parts(index), LegoPart)

192 End Function

193194 Public Function copy() As LegoModel

195 Dim ret As New LegoModel

196 For Each p As LegoPart In Parts

197 ret.addPart(p.Copy)

198 Next

199 Return ret

200 End Function

201 End Class

202203 End Class

68

Page 76: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.6 OpenGLViewer.vb

The viewer which displays the rendered LEGO object. It extends the control pro-vided within CSGL [8].

1 Imports CsGL.OpenGL

23 <CLSCompliant(False)> _

4 Public Class OpenGLViewer

5 Inherits CsGL.OpenGL.OpenGLControl

67 Private mSizeChecked As Boolean = False

8 Private mMaxModelSize As Single

9 Private mLastMousePos As Point

10 Private mCurrentRot As PointF

11 ’Private mChangeRot As PointF

12 Private mCurrentZ As Integer = -200

1314 Private lightAmbient () As Single = {0.4F, 0.4F, 0.4F, 0.4F}

15 Private lightDiffuse () As Single = {1, 1, 1, 1}

16 Private lightSpecular () As Single = {1, 1, 1, 1}

17 Private lightPosition () As Single = {-10, 10, 2, 1}

1819 Private specReflection () As Single = {0.8F, 0.8F, 0.8F, 1.0F} ’Defines the specular Reflection amount

2021 Private mInstructionList As Long

22 Private mWireFrame As Boolean = False

2324 Delegate Sub refreshCallBack ()

2526 Public Overrides Sub Refresh ()

27 If Me.InvokeRequired Then

28 Dim d As New refreshCallBack(AddressOf Refresh)

29 If Me IsNot Nothing Then Me.Invoke(d, Nothing)

30 Else

31 MyBase.Refresh ()

32 End If

33 End Sub

3435 Public Property InstructionList () As Long

36 Get

37 Return mInstructionList

38 End Get

39 Set(ByVal Value As Long)

40 mInstructionList = Value

41 End Set

42 End Property

4344 Public Property WireFrame () As Boolean

45 Get

46 Return mwireframe

47 End Get

48 Set(ByVal value As Boolean)

49 mwireframe = value

50 If mWireFrame Then

51 GL.glDisable(GL.GL_CULL_FACE)

52 GL.glPolygonMode(GL.GL_FRONT_AND_BACK , GL.GL_LINE)

53 Else

54 GL.glEnable(GL.GL_CULL_FACE)

55 GL.glPolygonMode(GL.GL_FRONT_AND_BACK , GL.GL_FILL)

56 End If

57 End Set

58 End Property

5960 Public Overrides Sub glDraw ()

61 GL.glClearColor (0.0, 0.0, 0.0, 0.0) ’Black

62 ’GL. glClearColor (1, 1, 1, 0) ’White

63 GL.glClear(Convert.ToUInt32(GL.GL_COLOR_BUFFER_BIT Or GL.GL_DEPTH_BUFFER_BIT ))

64 GL.glLoadIdentity ()

6566 GL.glTranslatef (0, 0, mCurrentZ)

67 GL.glRotatef (180, 1.0F, 0.0F, 0.0F)

68 GL.glRotatef(mCurrentRot.Y, 1.0F, 0.0F, 0.0F)

69 GL.glRotatef(mCurrentRot.X, 0.0F, 1.0F, 0.0F)

7071 If mInstructionList <> 0 Then

72 GL.glCallList(CUInt(mInstructionList ))

73 End If

74 GL.glFlush ()

7576 End Sub

7778 Protected Overrides Sub InitGLContext ()

7980 GL.glBlendFunc(GL.GL_SRC_ALPHA , GL.GL_ONE_MINUS_SRC_ALPHA)

81 GL.glEnable(GL.GL_BLEND)

8283 GL.glCullFace(GL.GL_BACK)

84 GL.glEnable(GL.GL_CULL_FACE)

8586 GL.glEnable(GL.GL_LIGHTING)

87 GL.glEnable(GL.GL_COLOR_MATERIAL)

88 GL.glShadeModel(GL.GL_SMOOTH) ’ Enable Smooth Shading

69

Page 77: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

89 GL.glClearDepth (1) ’ Depth Buffer Setup

90 GL.glEnable(GL.GL_DEPTH_TEST) ’ Enables Depth Testing

91 GL.glDepthFunc(GL.GL_LEQUAL) ’ The Type Of Depth Testing To Do

92 GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT , GL.GL_NICEST) ’ Really Nice Perspective Calculations

93 GL.glLightfv(GL.GL_LIGHT1 , GL.GL_AMBIENT , lightAmbient) ’ Setup The Ambient Light

94 GL.glLightfv(GL.GL_LIGHT1 , GL.GL_DIFFUSE , lightDiffuse) ’ Setup The Diffuse Light

95 GL.glLightfv(GL.GL_LIGHT1 , GL.GL_SPECULAR , lightSpecular) ’ Setup The Specular Light

96 GL.glLightfv(GL.GL_LIGHT1 , GL.GL_POSITION , lightPosition) ’ Position The Light

97 GL.glEnable(GL.GL_LIGHT1)

98 OpenGLViewer_Resize(Nothing , Nothing)

99100 ’All bricks will have the same shininess property , so can be set once here.

101 GL.glMaterialfv(GL.GL_FRONT , GL.GL_SPECULAR , specReflection)

102 GL.glMateriali(GL.GL_FRONT , GL.GL_SHININESS , 96)

103 End Sub

104105 Private fRotate As Single = 0.0F

106 Protected Sub myView_OnKeyDown(ByVal Sender As Object , ByVal kea As System.Windows.Forms.KeyEventArgs) _

107 Handles MyBase.KeyDown

108109 Select Case kea.KeyData

110 Case Keys.Escape

111 Application.Exit()

112 End Select

113 End Sub

114115 Public Function takeScreenShot () As Bitmap

116 Try

117 Dim mSize As Integer = 3 * Width * Height

118 Dim bm As New Bitmap(Width , Height)

119 Dim pixels(mSize) As Byte

120 GL.glReadPixels (0, 0, Width , Height , Convert.ToUInt32(GL.GL_RGB), _

121 Convert.ToUInt32(GL.GL_UNSIGNED_BYTE), pixels)

122123 Dim index As Integer = 0

124 While index < mSize

125 Dim ly As Integer = CInt(Int(( index / 3) / Width ))

126 Dim lx As Integer = CInt(index / 3) - (ly * Width)

127 bm.SetPixel(lx, Height - ly - 1, Color.FromArgb(Convert.ToInt32(pixels(index)), _

128 Convert.ToInt32(pixels(index + 1)), Convert.ToInt32(pixels(index + 2))))

129130 index += 3

131 End While

132 Return bm

133 Catch ex As Exception

134 MsgBox("Error trying to take snap shot." & vbCrLf & ex.Message , MsgBoxStyle.OkOnly Or _

135 MsgBoxStyle.Critical , "Error")

136137 Return Nothing

138 End Try

139 End Function

140141 Private Sub OpenGLViewer_MouseDown(ByVal sender As Object , ByVal e As System.Windows.Forms.MouseEventArgs) _

142 Handles Me.MouseDown

143144 If e.Button = Windows.Forms.MouseButtons.Left Then

145 mLastMousePos = e.Location

146 End If

147 End Sub

148149 Private Sub OpenGLViewer_MouseMove(ByVal sender As Object , ByVal e As System.Windows.Forms.MouseEventArgs) _

150 Handles Me.MouseMove

151152 If MouseButtons = Windows.Forms.MouseButtons.Left AndAlso mLastMousePos.X >= 0 Then

153 mCurrentRot = New PointF(mCurrentRot.X + (mLastMousePos.X - e.X), mCurrentRot.Y - (mLastMousePos.Y - e.Y))

154 mLastMousePos = e.Location

155 End If

156 End Sub

157158 Public Sub OpenGLViewer_MouseWheel(ByVal sender As Object , ByVal e As System.Windows.Forms.MouseEventArgs) _

159 Handles Me.MouseWheel

160161 ’One "turn" of the mouse wheel is e.Delta = 120. So dividing by 12 means each "turn" changes the z by 10

162 mCurrentZ += CInt(e.Delta / 12)

163 End Sub

164165 Private Sub OpenGLViewer_Resize(ByVal sender As Object , ByVal e As System.EventArgs) Handles Me.Resize

166 If Me.Height = 0 Then Height = 1 ’ Prevent a divide by zero by making height equal one

167 GL.glViewport (0, 0, Me.Width , Me.Height) ’Reset the current viewport

168 GL.glMatrixMode(GL.GL_PROJECTION) ’Select the projection matrix

169 GL.glLoadIdentity () ’Reset the project matrix

170 GL.gluPerspective (45.0F, Me.Width / Me.Height , 0.1F, 1000.0F) ’Calculate the aspect ration of the window

171 GL.glMatrixMode(GL.GL_MODELVIEW) ’ Select the modelview matrix

172 GL.glLoadIdentity ()

173 End Sub

174 End Class

70

Page 78: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.7 Renderer.vb

Converts the instruction and value stacks into OpenGL instructions and rendersthem to the OpenGL internal list.

1 Imports LEGO_Smoothing.Common

2 Imports CsGL.OpenGL

34 Public Class Renderer

56 Private Shared mValues () As Single

7 Private Shared mValPtr As Integer

89 Public Shared Function Render(ByVal Instructions As InstructionSet) As Long

10 Dim list As Long = GL.glGenLists (1)

11 GL.glNewList(CUInt(list), GL.GL_COMPILE)

1213 GL.glLineWidth (2.0F)

14 mValues = Instructions.Values

15 Dim ins() As eInstruction = Instructions.Instructions

16 mValPtr = 0

1718 For i As Integer = 0 To ins.Length - 1

19 Select Case ins(i)

20 Case eInstruction.Line

21 GL.glBegin(GL.GL_LINES)

22 DrawVertex ()

23 DrawVertex ()

24 GL.glEnd()

2526 Case eInstruction.Quadrilateral

27 GL.glBegin(GL.GL_QUADS)

28 SetNormal ()

29 DrawVertex ()

30 DrawVertex ()

31 DrawVertex ()

32 DrawVertex ()

33 GL.glEnd()

3435 Case eInstruction.Triangle

36 GL.glBegin(GL.GL_TRIANGLES)

37 SetNormal ()

38 DrawVertex ()

39 DrawVertex ()

40 DrawVertex ()

41 GL.glEnd()

4243 Case eInstruction.Normal

44 GL.glBegin(GL.GL_LINES)

45 SetColour3 ()

46 DrawVertex ()

47 DrawVertex ()

48 SetColour3 ()

49 DrawVertex ()

50 DrawVertex ()

51 SetColour3 ()

52 DrawVertex ()

53 DrawVertex ()

54 GL.glEnd()

5556 Case eInstruction.Colour

57 SetColour4 ()

58 End Select

59 Next

6061 GL.glEndList ()

62 Return list

63 End Function

6465 Private Shared Sub DrawVertex ()

66 GL.glVertex3f(mValues(mValPtr), mValues(mValPtr + 1), mValues(mValPtr + 2))

67 mValPtr += 3

68 End Sub

6970 Private Shared Sub SetNormal ()

71 GL.glNormal3f(mValues(mValPtr), mValues(mValPtr + 1), mValues(mValPtr + 2))

72 mValPtr += 3

73 End Sub

7475 Private Shared Sub SetColour3 ()

76 GL.glColor3f(mValues(mValPtr), mValues(mValPtr + 1), mValues(mValPtr + 2))

77 mValPtr += 3

78 End Sub

7980 Private Shared Sub SetColour4 ()

81 GL.glColor4f(mValues(mValPtr), mValues(mValPtr + 1), mValues(mValPtr + 2), mValues(mValPtr + 3))

82 mValPtr += 4

83 End Sub

8485 End Class

71

Page 79: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.8 Smoother.vb

Provides the smoothing and subdivision code, and is the file which can be changedto include more or different smoothing methods.

1 Imports LEGO_Smoothing.Common

2 Imports LEGO_Smoothing.ModelDefs

34 Public Class Smoother

56 Const lambda As Single = 0.4 ’0.6307 ’0.4

7 Const Kpb As Single = 0.01

8 Const mu As Single = 1.0 / (Kpb - (1.0 / lambda ))

910 Const PassNum As Integer = 1

11 Private Shared SmoothIterations As Integer = 100

12 Private Shared SubdivideIterations As Integer = 3

1314 Private Shared HashFixedPoints As New Hashtable

1516 ’Private Shared fixedPoints As New ArrayList

17 Private Shared newPoints As New ArrayList

1819 Private Shared Vertices As New Hashtable

2021 Private Shared frmSmoothProg As frmSmoothProgress

2223 Public Shared Function SmoothShape(ByVal LM As LegoModel , ByVal Method As eSmoothMethod , _

24 ByVal Subdivisons As Integer , ByVal Smoothing As Integer , Optional ByVal Parent As Form = Nothing) As LegoModel

25 SmoothIterations = Smoothing

26 SubdivideIterations = Subdivisons

272829 Vertices.Clear()

3031 Dim smoothedModel As LegoModel = LM.copy

32 ’fixedPoints .Clear ()

33 HashFixedPoints.Clear ()

3435 smoothedModel = CutIntoTriangles(smoothedModel)

3637 ’This creates smaller and more regualarly shape triangles which produce a better effect for smoothing

38 ’smoothedModel = subdivide( smoothedModel )

39 ’MergeVertices ( smoothedModel )

40 ’addTrianglesToHashTab ( smoothedModel )

4142 frmSmoothProg = New frmSmoothProgress

43 frmSmoothProg.Show(Parent)

44 frmSmoothProg.TopMost = True

45 frmSmoothProg.PassTotal = 0

46 Application.DoEvents ()

4748 Select Case Method

49 Case eSmoothMethod.Loop

50 LoopControl(smoothedModel)

51 Case eSmoothMethod.Taubin

52 TaubinControl(smoothedModel)

53 Case eSmoothMethod.Laplacian

54 LaplacianControl(smoothedModel)

55 End Select

5657 frmSmoothProg.Process = "Calculating Normals"

5859 ’Recalculate the normals of each shape in the mesh so lighting looks correct

60 For Each s As LegoPart In smoothedModel.Parts

61 Select Case s.type

62 Case PartType.Quadrilateral

63 With DirectCast(s, Part_Quadrilateral)

64 .Norm = Common.CalcNormal(New Point3D () {.P1, .P2 , .P3, .P4})

65 End With

66 Case PartType.Triangle

67 With DirectCast(s, Part_Triangle)

68 .Norm = Common.CalcNormal(New Point3D () {.P1, .P2 , .P3})

69 End With

70 End Select

71 frmSmoothProg.Percent += (0.25 / smoothedModel.Parts.Count)

72 Next

7374 frmSmoothProg.Close()

7576 Return smoothedModel

77 End Function

7879 Private Shared Sub LaplacianControl(ByRef LM As LegoModel)

80 frmSmoothProg.Process = "Subdividing"

81 For subdivideindex As Integer = 1 To SubdivideIterations

82 LM = subdivide(LM)

83 frmSmoothProg.Percent += (0.25 / SubdivideIterations)

84 Next

8586 MergeVertices(LM, 0.25)

87 addTrianglesToHashTab(LM)

88

72

Page 80: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

89 frmSmoothProg.Process = "Smoothing"

90 For smoothIndex As Integer = 1 To SmoothIterations

91 LaplacianSmooth ()

92 frmSmoothProg.Percent += (0.25 / SmoothIterations)

93 Next smoothIndex

94 End Sub

9596 Private Shared Sub LoopControl(ByRef LM As LegoModel)

97 For subdivideIndex As Integer = 1 To SubdivideIterations

98 frmSmoothProg.Process = "Subdividing"

99 LM = subdivide(LM)

100101 MergeVertices(LM, CSng (0.25 / SubdivideIterations ))

102103 addTrianglesToHashTab(LM)

104105 frmSmoothProg.Process = "Smoothing"

106 LoopsMask ()

107 frmSmoothProg.Percent += (0.5 / SubdivideIterations)

108 Next subdivideIndex

109110 End Sub

111112 Private Shared Sub TaubinControl(ByRef LM As LegoModel)

113 frmSmoothProg.Process = "Subdividing"

114 For subdivideIndex As Integer = 1 To SubdivideIterations

115 LM = subdivide(LM)

116 frmSmoothProg.Percent += (0.25 / SubdivideIterations)

117 Next subdivideIndex

118119 MergeVertices(LM, 0.25)

120 addTrianglesToHashTab(LM)

121122 ’’Smooth

123124 frmSmoothProg.Process = "Smoothing"

125 For smoothIndex As Integer = 1 To SmoothIterations

126 TaubinSmoothModel(lambda)

127 TaubinSmoothModel(mu)

128 frmSmoothProg.Percent += (0.25 / SmoothIterations)

129 Next smoothIndex

130 End Sub

131132 Private Shared Sub addTrianglesToHashTab(ByVal LM As LegoModel)

133 Vertices.Clear()

134 For Each p As LegoPart In LM.Parts

135 If TypeOf p Is Part_Triangle Then

136 AddTriangleToHash(DirectCast(p, Part_Triangle ))

137 End If

138 Next

139 End Sub

140141 Private Shared Function subdivide(ByVal LM As LegoModel) As LegoModel

142 ’Should only be called after CutIntoTriangles , as only subdivides triangles

143144 ’Uses Loops Subdivision method which is based on the umbrella subdivison method.

145 ’Will cut each triangle into 4 new ones , by spliting the original edges in their centres , and then connecting

146 ’all points up to create the 4 new triangles .

147148 ’Only the subdivision is carried out here. Loops Masking is implemented in LoopsMask

149150 Dim ret As New LegoModel

151152 For Each p As Part_Triangle In LM.Parts

153 With p

154 Dim newPoint1 As Point3D = AddVector(ScaleVector(SubVector (.P2 , .P1), 0.5), .P1)

155 Dim newPoint2 As Point3D = AddVector(ScaleVector(SubVector (.P3 , .P1), 0.5), .P1)

156 Dim newPoint3 As Point3D = AddVector(ScaleVector(SubVector (.P3 , .P2), 0.5), .P2)

157158 Dim newT1 As New Part_Triangle

159 newT1.RealColour = .RealColour

160 newT1.colour = .colour

161 newT1.Norm = .Norm

162 newT1.P1 = .P1

163 newT1.P2 = newPoint1

164 newT1.P3 = newPoint2

165166 Dim newT2 As New Part_Triangle

167 newT2.RealColour = .RealColour

168 newT2.colour = .colour

169 newT2.Norm = .Norm

170 newT2.P1 = .P2

171 newT2.P2 = newPoint3

172 newT2.P3 = newPoint1

173174 Dim newT3 As New Part_Triangle

175 newT3.RealColour = .RealColour

176 newT3.colour = .colour

177 newT3.Norm = .Norm

178 newT3.P1 = .P3

179 newT3.P2 = newPoint2

180 newT3.P3 = newPoint3

181182 Dim newT4 As New Part_Triangle

183 newT4.RealColour = .RealColour

73

Page 81: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

184 newT4.colour = .colour

185 newT4.Norm = .Norm

186 newT4.P1 = newPoint1

187 newT4.P2 = newPoint3

188 newT4.P3 = newPoint2

189190 ret.addPart(newT1)

191 ret.addPart(newT2)

192 ret.addPart(newT3)

193 ret.addPart(newT4)

194 End With

195 Next

196 Return ret

197 End Function

198199 Private Shared Sub LoopsMask ()

200 ’Loop ’s Mask new vertex positioning

201 Dim alpha , Beta As Double

202 Dim neighbourhood As ArrayList

203 Dim neighbourhoodSize As Integer

204 newPoints.Clear()

205 Dim v As Point3D

206207 For Each p As Point3D In HashFixedPoints.Values

208 v = New Point3D

209 neighbourhood = DirectCast(Vertices(p), ArrayList)

210 neighbourhoodSize = neighbourhood.Count

211 Beta = (5 / 4) - (((3 + 2 * Math.Cos((2 * Math.PI) / neighbourhoodSize )) ^ 2) / 32)

212 alpha = (neighbourhoodSize * (1 - Beta)) / Beta

213214 For Each neighbour As Point3D In neighbourhood

215 v = AddVector(v, neighbour)

216 Next

217218 v = AddVector(ScaleVector(p, CSng(alpha)), v)

219 v = ScaleVector(v, CSng(1 / (alpha + neighbourhoodSize )))

220 newPoints.Add(v)

221 Next

222223 Dim i As Integer = 0

224 For Each p As Point3D In HashFixedPoints.Values

225 p.x = DirectCast(newPoints(i), Point3D ).x

226 p.y = DirectCast(newPoints(i), Point3D ).y

227 p.z = DirectCast(newPoints(i), Point3D ).z

228 i += 1

229 Next

230231 End Sub

232233 Private Shared Sub TaubinSmoothModel(ByVal constant As Single)

234 Dim weight As Double

235 Dim dx As Point3D

236 Dim neighbourhood As ArrayList

237 newPoints.Clear()

238239 For Each p As Point3D In HashFixedPoints.Values

240 dx = New Point3D

241 neighbourhood = DirectCast(Vertices(p), ArrayList)

242 weight = 1 / neighbourhood.Count

243244 For Each neighbour As Point3D In neighbourhood

245 dx = AddVector(dx, ScaleVector(SubVector(neighbour , p), CSng(weight )))

246 Next

247 newPoints.Add(AddVector(p, ScaleVector(dx, constant )))

248 Next

249250 Dim i As Integer = 0

251 For Each p As Point3D In HashFixedPoints.Values

252 p.x = DirectCast(newPoints(i), Point3D ).x

253 p.y = DirectCast(newPoints(i), Point3D ).y

254 p.z = DirectCast(newPoints(i), Point3D ).z

255 i += 1

256 Next

257258 End Sub

259260 Private Shared Sub LaplacianSmooth ()

261 Dim dx As Point3D

262 Dim neighbourhood As ArrayList

263 newPoints.Clear()

264265 dx = New Point3D

266 For Each p As Point3D In HashFixedPoints.Values

267 dx.clear()

268 neighbourhood = DirectCast(Vertices(p), ArrayList)

269270 For Each neighbour As Point3D In neighbourhood

271 dx = AddVector(dx, neighbour)

272 Next

273 newPoints.Add(ScaleVector(dx , CSng(1 / neighbourhood.Count )))

274 Next

275276 Dim i As Integer = 0

277 For Each p As Point3D In HashFixedPoints.Values

278 p.x = DirectCast(newPoints(i), Point3D ).x

74

Page 82: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

279 p.y = DirectCast(newPoints(i), Point3D ).y

280 p.z = DirectCast(newPoints(i), Point3D ).z

281 i += 1

282 Next

283 End Sub

284285 Private Shared Sub LaplacianSmoothNonShrink(ByVal constant As Single)

286 Dim dx As Point3D

287 Dim neighbourhood As ArrayList

288 newPoints.Clear()

289290 For Each p As Point3D In HashFixedPoints.Values

291 dx = New Point3D

292 neighbourhood = DirectCast(Vertices(p), ArrayList)

293294 For Each neighbour As Point3D In neighbourhood

295 dx = AddVector(dx, ScaleVector(neighbour , constant ))

296 Next

297 newPoints.Add(ScaleVector(dx , CSng(1 / neighbourhood.Count )))

298 Next

299300 Dim i As Integer = 0

301 For Each p As Point3D In HashFixedPoints.Values

302 p.x = DirectCast(newPoints(i), Point3D ).x

303 p.y = DirectCast(newPoints(i), Point3D ).y

304 p.z = DirectCast(newPoints(i), Point3D ).z

305 i += 1

306 Next

307 End Sub

308309 Private Shared Function CutIntoTriangles(ByVal LM As LegoModel) As LegoModel

310 ’Just cuts quads into triangles by splitting them in half

311 Dim t1, t2 As Part_Triangle

312 Dim triangles ()() As Point3D

313 Dim ret As New LegoModel

314 Dim q As Part_Quadrilateral

315316 For Each p As LegoPart In LM.Parts

317 If TypeOf p Is Part_Quadrilateral Then

318 q = DirectCast(p, Part_Quadrilateral)

319320 t1 = New Part_Triangle

321 t2 = New Part_Triangle

322323 t1.Norm = q.Norm

324 t1.RealColour = q.RealColour

325 t1.colour = q.colour

326 t2.Norm = q.Norm

327 t2.RealColour = q.RealColour

328 t2.colour = q.colour

329330 triangles = Common.MakeTriangles(q)

331 t1.P1 = triangles (0)(0)

332 t1.P2 = triangles (0)(1)

333 t1.P3 = triangles (0)(2)

334335 t2.P1 = triangles (1)(0)

336 t2.P2 = triangles (1)(1)

337 t2.P3 = triangles (1)(2)

338339 ret.addPart(t1)

340 ret.addPart(t2)

341 ElseIf TypeOf p Is Part_Triangle Then

342343 ret.addPart(p)

344 End If

345346 Next

347 Return ret

348 End Function

349350 Private Shared Sub AddTriangleToHash(ByVal T As Part_Triangle)

351 Dim arr As ArrayList

352 Dim contained As Boolean

353 Dim points () As Point3D = New Point3D () {T.P1, T.P2, T.P3}

354355 For i As Integer = 0 To 2

356 If Vertices.ContainsKey(points(i)) Then

357 arr = DirectCast(Vertices(points(i)), ArrayList)

358 contained = True

359 Else

360 arr = New ArrayList

361 contained = False

362 End If

363364 Select Case i

365 Case 0

366 arr.AddRange(New Point3D () {T.P2, T.P3})

367 Case 1

368 arr.AddRange(New Point3D () {T.P1, T.P3})

369 Case 2

370 arr.AddRange(New Point3D () {T.P1, T.P2})

371 End Select

372 RemoveDuplicates(arr)

373

75

Page 83: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

374 If Not contained Then

375 Vertices.Add(points(i), arr)

376 End If

377 Next

378 End Sub

379380 Private Shared Sub MergeVertices(ByVal LM As LegoModel , ByVal PercentageValue As Single)

381 ’Percentage Value is the percentage of this process compared to the whole smoothing method

382383 frmSmoothProg.Process = "Merging Vertices"

384 For Each t As Part_Triangle In LM.Parts

385 PointInFixedPoints(t.P1)

386 PointInFixedPoints(t.P2)

387 PointInFixedPoints(t.P3)

388 frmSmoothProg.Percent += (PercentageValue / LM.Parts.Count)

389 Next

390 End Sub

391392 Structure PointTest

393 Dim x As Single

394 Dim y As Single

395 Dim z As Single

396 End Structure

397398 Private Shared Sub PointInFixedPoints(ByRef P As Point3D)

399 Dim pt As PointTest

400 pt.x = P.x

401 pt.y = P.y

402 pt.z = P.z

403404 If HashFixedPoints.ContainsKey(pt) Then

405 P = DirectCast(HashFixedPoints.Item(pt), Point3D)

406 Else

407 HashFixedPoints.Add(pt, P)

408 End If

409 End Sub

410411 End Class

76

Page 84: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.9 SurfaceFinder.vb

Carries out the overlap resolving and when completed would return a mesh holdingjust the outer surface.

1 Imports LEGO_Smoothing.Common

2 Imports LEGO_Smoothing.ModelDefs

34 Public Class SurfaceFinder

56 Private Shared mShowInterceptions As Boolean

78 Private Class Shape

9 Public Part As Part_Quadrilateral

10 Public ExterierVertices As New ArrayList

11 Public IntersectionVertices As New ArrayList

12 Public InternalVertices As New ArrayList

13 Public LineIntersections As New ArrayList

14 Public ValidVertexPairs As New ArrayList

15 End Class

1617 Private Shared Function NoSurfaceFind(ByVal LM As LegoModel) As LegoModel

18 Dim quickRet As New LegoModel

1920 For Each p As LegoPart In LM.Parts

21 If TypeOf p Is Part_Quadrilateral Then

22 quickRet.addPart(p)

23 ElseIf TypeOf p Is Part_External AndAlso Not DirectCast(p, Part_External ).Name.Contains("stud") Then

24 For Each p2 As LegoPart In NoSurfaceFind(DirectCast(p, Part_External ).part).parts

25 quickRet.addPart(p2)

26 Next

27 End If

28 Next

29 Return quickRet

30 End Function

313233 Public Shared Function GetOuterSurface(ByVal LM As LegoModel , ByVal ShowInterceptions As Boolean) As LegoModel

34 ’Return NoSurfaceFind (LM)

353637 mShowInterceptions = ShowInterceptions

38 ’Remove all shapes but quads. Triangles could be kept , but will not be for the simple case as they

39 ’are not present in simple lego bricks

4041 ’Dim tmpQuads As New ArrayList ’An array list is used as this is simple to add an unknown number of items to ,

42 ’a typed array would have to be ’redimed ’ each time round as the length is unknown

4344 Dim Quads As New ArrayList ’Part_Quadrilateral ’After the list length is known , i.e. tmpQuads is populated

45 ’it is converted to a typed array , to save every operation having to type cast each item

4647 ’Main is the prefix for the part actually being tested

48 Dim mainIndex As Integer = 0

49 Dim mainPart As Part_Quadrilateral

5051 ’Check is the prefix for the parts the main part is being checked against

52 Dim checkIndex As Integer = 0

53 Dim checkPart As Part_Quadrilateral = Nothing

5455 ’Populate tmpQuads

56 ’tmpQuads = GetQuads(LM.Parts)

57 Quads = GetQuads(LM.Parts)

5859 ’Convert to typed array

60 ’Quads = DirectCast (tmpQuads.ToArray(GetType( Part_Quadrilateral )), Part_Quadrilateral ())

6162 ’See documentation for better description of this part

6364 ’1 - Remove overlapping quads

6566 ’1.1 - Find intersections and remove quads/vertex based only on vertices

6768 ’1.1.1 - If all 4 vertices are the same then remove

69 Check1_1_1(DirectCast(Quads.ToArray(GetType(Part_Quadrilateral )), Part_Quadrilateral ()))

70 ’1.1.2 - Find intersecting vertices

7172 Dim ret As New LegoModel

73 Dim shp1 , shp2 As Shape

7475 While mainIndex < Quads.Count

76 mainPart = DirectCast(Quads(mainIndex), Part_Quadrilateral)

77 checkIndex = mainIndex + 1

78 While checkIndex < Quads.Count

79 ’checkPart = DirectCast (Quads( checkIndex ), Part_Quadrilateral )

8081 ’If the two quads aren ’t in the same direction then they don ’t overlap in any way , and

82 ’therefore don ’t need to be removed and therefore tested against.

83 ’In this case the same direction means either the same normal or the inverted normal

84 While checkIndex < Quads.Count

85 checkPart = DirectCast(Quads(checkIndex), Part_Quadrilateral)

86 If mainPart.Norm.Equals(checkPart.Norm) OrElse _

87 mainPart.Norm.Equals(New Point3D(-checkPart.Norm.x, -checkPart.Norm.y, -checkPart.Norm.z)) Then

88 ’The same direction , so can proceed with testing

77

Page 85: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

89 Exit While

90 End If

91 checkIndex += 1

92 End While

93 ’If it got to the end of the check parts , then should skip to the next main part

94 If checkIndex = Quads.Count Then Exit While

9596 ’1.1.2 - Find if mainpart vertices are ’inside , intercepting , or outside the check quad

97 shp1 = IntersectVertexCheck1_1_2(mainPart , checkPart , True)

9899 ’1.1.2 - Find if check quad vertices are inside , intercepting , or outside the mainpart

100 shp2 = IntersectVertexCheck1_1_2(checkPart , mainPart , True)

101102 ’Create an array of pairs specifying how the different intersections and vertices

103 ’can be correctly joined together

104 CalculateValidVertexPairs(shp1 , shp2)

105106 If shp1.ExterierVertices.Count = 0 And shp2.ExterierVertices.Count = 0 Then

107 ’1.1.4 - All vertices of both shapes intercept , both can be removed

108 Quads.Remove(mainPart)

109 Quads.Remove(checkPart)

110 mainIndex -= 1

111 Exit While

112 End If

113114 If mShowInterceptions Then

115 DisplayIntersections(shp1 , shp2 , ret)

116 End If

117118 ’1.2.1 - THIS HAS BEEN REMOVED AS WASN ’T VALID FOR ALL CASES. See documentation for more information .

119 ’1.2.1 - No line intersections and only a max or two intersecting vertices then shape is just touching

120 ’the other shape , so can move onto next as nothing to remove

121122 If shp1.InternalVertices.Count = 0 AndAlso shp2.InternalVertices.Count = 0 _

123 AndAlso (shp1.LineIntersections.Count > 0 Or shp2.LineIntersections.Count > 0) Then

124125 ’1.2.2a - No internal points , so join valid intersections , line intersections and external vertices

126 ’Used to use its on method , but this is the same as now used in MakeQuads122c so re -uses code

127 If MakeQuads122c(shp1 , shp2 , Quads , mainIndex , checkIndex) Then

128 ’As the original quads will have been removed need to deduct 1 from the mainIndex

129 Exit While ’No point checking any more quads against this main part as it no longer exists

130 End If

131 ElseIf shp1.InternalVertices.Count = 0 AndAlso shp2.InternalVertices.Count = 0 _

132 AndAlso shp1.LineIntersections.Count = 0 AndAlso shp1.IntersectionVertices.Count > 1 Then

133134 ’1.2.2.b - No internal points , or line intersections , but has got vertex intersections , so

135 ’could be overlapping shapes or could just be touching shapes

136137 ’Test if the validPairs created earlier define a complete path , i.e. get from start to start

138 ’going via all the other points. If so , can just keep this quad as is. If one is ok then

139 ’both are ok. So only need to test once for both quads.

140141 ’Shape 1 has no exterier vertices either , so it is covered completly by shape 2, so can

142 ’be removed , but needs to be used by shape 2 to create the correct remaining shape , this

143 ’is then swapped to test the case of shape 2 having no exterier vertices

144 Dim CanRemoveShape1 As Boolean = (shp1.ExterierVertices.Count = 0)

145 Dim CanRemoveShape2 As Boolean = (shp2.ExterierVertices.Count = 0)

146147 ’If all shape 1 interception points are also its vertex points then it doesn ’t need to

148 ’be tested against the other shape , as it will remain the same shape.

149 ’The other shape may still need to be checked though

150151 ’Exterier vertices are kept , and now just find if an exterier can still connected to

152 ’another exterier. If not it now connects to the closest interception of the other shape.

153154 If (Not CanRemoveShape2) Then

155 If MakeAndAddQuadsToQuadList(DirectCast(shp2.ValidVertexPairs.ToArray(GetType(Object ())), _

156 Object ()), mainPart , checkPart , Quads , False) Then

157158 checkIndex -= 1

159 End If

160 Else

161 Quads.Remove(checkPart)

162 checkIndex -= 1

163 End If

164165 If Not CanRemoveShape1 Then

166 If MakeAndAddQuadsToQuadList(DirectCast(shp1.ValidVertexPairs.ToArray(GetType(Object ())), _

167 Object ()), checkPart , mainPart , Quads , False) Then

168169 mainIndex -= 1

170 Exit While

171 End If

172 Else

173 Quads.Remove(mainPart)

174 mainIndex -= 1

175 Exit While

176 End If

177 Else

178 ’1.2.2c - Handle Internal intersections , by joining all known vertices as in parts 1.2.2a

179 ’and 1.2.2b, and then connect the ends to the internal intersections . Which will complete

180 ’the shape. Then split this shape to give 4 vertex shapes , i.e. quads

181182 ’1.1.5 - Swap internal vertices between the two shapes , as these are internal they are no longer

183 ’needed by the original shape , but are now part of the other shape

78

Page 86: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

184 ’(as its being cut by the original shape)

185186 ’## Only needs doing when looking for internal vertices

187 ’## causes 1.2.2b to fail otherwise

188 If shp1.InternalVertices.Count > 0 Or shp2.InternalVertices.Count > 0 Then

189 Dim tmpInternals As ArrayList = shp1.InternalVertices

190 shp1.InternalVertices = shp2.InternalVertices

191 shp2.InternalVertices = tmpInternals

192 End If

193194 If MakeQuads122c(shp1 , shp2 , Quads , mainIndex , checkIndex) Then

195 ’Check if MakeQuads122c has removed the main part

196 Exit While

197 End If

198 End If

199 checkIndex += 1

200 End While

201 mainIndex += 1

202 End While

203204 For Each quad As Part_Quadrilateral In Quads

205 ’Add the remaining quads to the returning lego model , these should only be the quads which make up

206 ’the outside surface of the model

207 ret.addPart(quad)

208 Next

209210 Return ret

211 End Function

212213 Private Shared Function MakeQuads122c(ByVal MainShape As Shape , ByVal CheckShape As Shape , _

214 ByRef QuadList As ArrayList , ByRef MainIndex As Integer , ByRef CheckIndex As Integer) As Boolean

215 ’ ’’The valid vertex pairs found for 1.2.2a which are generated while finding the different

216 ’ ’’interceptions , and are therefore available to all the methods. Do not work correctly for internal

217 ’ ’’vertices. While this could probably be changed in the initial finding for 1.2.2a it could

218 ’ ’’also stop the other methods working. Therefore correct valid vertex pairs for 1.2.2c will be

219 ’ ’’calculated here.

220221 ’ ’’CalculateValidVertexPairs122c (MainShape , CheckShape )

222223 ’ ’’Join externals , but need to check there are no intersecion points in the way.

224 ’ ’’If an external is an interception point then join to it , but don ’t go beyond that external.

225 ’ ’’If there is an interception then make a valid pair to it , and then from it to the next external.

226 ’ ’’If line interceptions should already be known. Join the external to the line interception , and again

227 ’ ’’go no further.

228229 Dim shapes () As Shape = New Shape() {CheckShape , MainShape}

230 Dim validPairs As New ArrayList

231 Dim ret As Boolean = False

232 Dim splitValidVertexPairs As New ArrayList

233234 For i As Integer = 0 To 1

235 validPairs.Clear ()

236237 ’((i - 1) * -1) - Swaps 0 to 1 and 1 to 0. So is able to select the other shape.

238 Dim otherShape As Shape = shapes ((i - 1) * -1)

239240 With shapes(i)

241 If .ExterierVertices.Count = 0 Then

242 ’If no exterier then the shape is completly overlapping so can be removed

243 QuadList.Remove (.Part)

244 If i = 0 Then

245 CheckIndex -= 1

246 Else

247 MainIndex -= 1

248 ret = True

249 End If

250 Else

251 If .InternalVertices.Count > 0 Then

252 If .InternalVertices.Count = 4 Then

253 ’The shape is completly inside the other one

254 Else

255 ’Add connections between internals

256 Dim endPoints As ArrayList = getPointsIJoin2 (. ValidVertexPairs.ToArray , True)

257 Dim internalEndPoints As ArrayList

258259 If .InternalVertices.Count > 1 Then

260 If arrayHoldsPoint (. InternalVertices , otherShape.Part.P1) > -1 Then

261 If arrayHoldsPoint (. InternalVertices , otherShape.Part.P2) > -1 Then

262 validPairs.Add(New Point3D () {otherShape.Part.P1, otherShape.Part.P2})

263 ElseIf arrayHoldsPoint (. InternalVertices , otherShape.Part.P4) > -1 Then

264 validPairs.Add(New Point3D () {otherShape.Part.P1, otherShape.Part.P4})

265 End If

266 End If

267268 If arrayHoldsPoint (. InternalVertices , otherShape.Part.P2) > -1 Then

269 If arrayHoldsPoint (. InternalVertices , otherShape.Part.P3) > -1 Then

270 validPairs.Add(New Point3D () {otherShape.Part.P2, otherShape.Part.P3})

271 End If

272 End If

273274 If arrayHoldsPoint (. InternalVertices , otherShape.Part.P3) > -1 Then

275 If arrayHoldsPoint (. InternalVertices , otherShape.Part.P4) > -1 Then

276 validPairs.Add(New Point3D () {otherShape.Part.P3, otherShape.Part.P4})

277 End If

278 End If

79

Page 87: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

279280 internalEndPoints = getPointsIJoin2(validPairs.ToArray , True)

281282 ’Merge these validPairs with the normal points

283 .ValidVertexPairs.AddRange(validPairs)

284 Else

285 internalEndPoints = New ArrayList

286 internalEndPoints.Add(. InternalVertices (0))

287 End If

288289 ’Now need to find the connections between the internal end points and the

290 ’end points of the new quad shape being constructed so far

291292 ConnectEndPointsToInternals (. ValidVertexPairs , internalEndPoints , otherShape , endPoints)

293294 If .IntersectionVertices.Count = 2 Then

295 ’Need to find if they are on the same line , or on different lines

296 Dim intVert0 As Point3D = DirectCast (. IntersectionVertices (0), Point3D)

297 Dim intVert1 As Point3D = DirectCast (. IntersectionVertices (1), Point3D)

298 Dim pointsOnSameLine As Boolean = _

299 (PointOnLine (.Part.P1 , .Part.P2, intVert0) AndAlso _

300 PointOnLine (.Part.P1, .Part.P2 , intVert1 )) Or _

301 (PointOnLine (.Part.P2 , .Part.P3, intVert0) AndAlso _

302 PointOnLine (.Part.P2, .Part.P3 , intVert1 )) Or _

303 (PointOnLine (.Part.P3 , .Part.P4, intVert0) AndAlso _

304 PointOnLine (.Part.P3, .Part.P4 , intVert1 )) Or _

305 (PointOnLine (.Part.P4 , .Part.P1, intVert0) AndAlso _

306 PointOnLine (.Part.P4, .Part.P1 , intVert1 ))

307308 If Not pointsOnSameLine Then

309 splitValidVertexPairs = getSplitPairs (. ValidVertexPairs , .IntersectionVertices , _

310 otherShape.Part)

311312 For Each ep As ArrayList In splitValidVertexPairs

313 Dim quads As ArrayList = MakeQuads(ep.ToArray , otherShape.Part , _

314 shapes (0). Part.Norm , False)

315316 Dim triangles As Point3D ()() = _

317 MakeTriangles(DirectCast(quads (0), Part_Quadrilateral ))

318319 Dim q2t1Area As Double = CalcTriangleArea(triangles (0))

320 Dim q2t2area As Double = CalcTriangleArea(triangles (1))

321 Dim thisQuad As Boolean = False

322 For Each iv As Point3D In .IntersectionVertices

323 If (Not DoesIntercept(triangles (0), q2t1Area , iv) = eInterceptType.None) Or _

324 (Not DoesIntercept(triangles (1), q2t2area , iv) = eInterceptType.None) Then

325 thisQuad = True

326 End If

327 Next

328 If thisQuad Then

329 ’Then this is the quad with the internal vertices in it.

330 ConnectEndPointsToInternals(ep, internalEndPoints , otherShape , _

331 .IntersectionVertices)

332 Exit For

333 End If

334 Next

335 Else

336 splitValidVertexPairs.Add(. ValidVertexPairs)

337 End If

338339 ElseIf .IntersectionVertices.Count = 1 Then

340 ’This will create two seperate shapes , with the intersection being where

341 ’they divide.

342 splitValidVertexPairs = getSplitPairs (. ValidVertexPairs , .IntersectionVertices , _

343 otherShape.Part)

344345 Else

346 splitValidVertexPairs.Add(. ValidVertexPairs)

347 End If

348 End If

349 Else

350 splitValidVertexPairs = New ArrayList

351 splitValidVertexPairs.Add(. ValidVertexPairs)

352 End If

353 ’Can now connect up as with 1.2.2a, which now comes through here too

354 ’Shapes with more than 4 vertices will be divided up correctly in the function called below

355 For Each pair As ArrayList In splitValidVertexPairs

356 If MakeAndAddQuadsToQuadList(pair.ToArray , otherShape.Part , .Part , QuadList , True) Then

357 If i = 0 Then

358 CheckIndex -= 1

359 Else

360 MainIndex -= 1

361 ret = True

362 End If

363 End If

364 Next

365 End If

366 End With

367 Next

368369 ’Returns true if the mainindex is removed , so know to exit while

370 Return ret

371 End Function

372373 Private Shared Sub ConnectEndPointsToInternals(ByRef ValidVertexPairs As ArrayList , _

80

Page 88: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

374 ByVal internalEndPoints As ArrayList , ByVal OtherShape As Shape , ByVal EndPoints As ArrayList)

375376 For Each ip As Point3D In internalEndPoints

377 If ip.Equals(OtherShape.Part.P1) Then

378 For Each ep As Point3D In EndPoints

379 If PointOnLine(OtherShape.Part.P1, OtherShape.Part.P2, ep) Or _

380 PointOnLine(OtherShape.Part.P1, OtherShape.Part.P4 , ep) Then

381 ValidVertexPairs.Add(New Point3D () {ep, ip})

382 End If

383 Next

384 ElseIf ip.Equals(OtherShape.Part.P2) Then

385 For Each ep As Point3D In EndPoints

386 If PointOnLine(OtherShape.Part.P2, OtherShape.Part.P3, ep) Or _

387 PointOnLine(OtherShape.Part.P2, OtherShape.Part.P1 , ep) Then

388 ValidVertexPairs.Add(New Point3D () {ep, ip})

389 End If

390 Next

391 ElseIf ip.Equals(OtherShape.Part.P3) Then

392 For Each ep As Point3D In EndPoints

393 If PointOnLine(OtherShape.Part.P3, OtherShape.Part.P4, ep) Or _

394 PointOnLine(OtherShape.Part.P3, OtherShape.Part.P2 , ep) Then

395 ValidVertexPairs.Add(New Point3D () {ep, ip})

396 End If

397 Next

398 ElseIf ip.Equals(OtherShape.Part.P4) Then

399 For Each ep As Point3D In EndPoints

400 If PointOnLine(OtherShape.Part.P4, OtherShape.Part.P1, ep) Or _

401 PointOnLine(OtherShape.Part.P4, OtherShape.Part.P3 , ep) Then

402 ValidVertexPairs.Add(New Point3D () {ep, ip})

403 End If

404 Next

405 End If

406 Next

407 End Sub

408409 Private Shared Function getSplitPairs(ByVal ValidPairs As ArrayList , ByVal Intersections As ArrayList , _

410 ByVal CheckPart As Part_Quadrilateral) As ArrayList

411412 Dim ret As New ArrayList

413 Dim points () As Point3D

414 Dim testPoints As New ArrayList

415 Dim intPoint As Point3D = DirectCast(Intersections (0), Point3D)

416417 Dim index As Integer = 0

418 While index < ValidPairs.Count

419 points = DirectCast(ValidPairs(index), Point3D ())

420 ’Find where what the intersection point joins to. Then get the valid pairs from that point (having

421 ’removed the link to the intersection . This will return just that half , and then re -add the link

422 ’to the intersection to

423424 If points (0). Equals(intPoint) Then

425 ValidPairs.Remove(points)

426 testPoints.Add(points (1))

427 ElseIf points (1). Equals(intPoint) Then

428 ValidPairs.Remove(points)

429 testPoints.Add(points (0))

430 End If

431 ’Optimisation

432 If testPoints.Count = 2 Then Exit While

433 index += 1

434 End While

435436 Dim tmpValidPairs As New ArrayList

437 Dim vertices () As Point3D

438 For Each tp As Point3D In testPoints

439 tmpValidPairs.Clear ()

440 vertices = DirectCast(getPointsIJoin2(ValidPairs.ToArray , False , CheckPart , tp). ToArray(GetType(Point3D)), _

441 Point3D ())

442443 For i As Integer = vertices.Length - 2 To 0 Step -1

444 If Intersections.Count = 2 AndAlso vertices(i + 1). Equals(DirectCast(Intersections (1), Point3D )) Then

445 ’Make sure it jumps out at the other intersection point , so don ’t go all the way round

446 Exit For

447 End If

448 tmpValidPairs.Add(New Point3D () {vertices(i), vertices(i + 1)})

449 Next

450 tmpValidPairs.Add(New Point3D () {tp , intPoint })

451 ret.Add(tmpValidPairs.Clone)

452 Next

453 Return ret

454 End Function

455456 Private Shared Sub CalculateValidVertexPairs(ByVal MainShape As Shape , ByVal CheckShape As Shape)

457 ’All this cares about is valid vertex pairs which connect the external vertices of mainshape to any other

458 ’external , line interceptions , or intersections points which are outside of checkshape .

459460 ’It checks each of the part vertices for if it is external. If so will then check that it can connect

461 ’to the other correct vertices , or if there is a line intesection , or intersection in the way.

462463 Dim ret As New ArrayList

464 Dim allIntersections As New ArrayList

465466 ’Merge the intersectionVertices of each shape

467 MainShape.IntersectionVertices.AddRange(CheckShape.IntersectionVertices)

468 RemoveDuplicates(MainShape.IntersectionVertices)

81

Page 89: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

469 CheckShape.IntersectionVertices = MainShape.IntersectionVertices

470471 Dim shapes () As Shape = New Shape() {MainShape , CheckShape}

472473 For i As Integer = 0 To 1

474 With shapes(i)

475 allIntersections.Clear ()

476 ret.Clear()

477 allIntersections.AddRange (. IntersectionVertices)

478 allIntersections.AddRange (. LineIntersections)

479480 ’P1 - which originally could connect to P2 and P4

481 If arrayHoldsPoint (. ExterierVertices , .Part.P1) > -1 Then

482 ’It is external now find if it can connect to P2

483 ’nearestPoint will return the end point if it can be seen or else the closest intersection

484 ret.Add(New Point3D () {.Part.P1 , nearestPoint (.Part.P1 , .Part.P2 , allIntersections )})

485 ret.Add(New Point3D () {.Part.P1 , nearestPoint (.Part.P1 , .Part.P4 , allIntersections )})

486 End If

487488 ’P2 - which originally could connect to P3 and P1

489 If arrayHoldsPoint (. ExterierVertices , .Part.P2) > -1 Then

490 ret.Add(New Point3D () {.Part.P2 , nearestPoint (.Part.P2 , .Part.P3 , allIntersections )})

491 ret.Add(New Point3D () {.Part.P2 , nearestPoint (.Part.P2 , .Part.P1 , allIntersections )})

492 End If

493494 ’P3 - which originally could connect to P4 and P2

495 If arrayHoldsPoint (. ExterierVertices , .Part.P3) > -1 Then

496 ret.Add(New Point3D () {.Part.P3 , nearestPoint (.Part.P3 , .Part.P4 , allIntersections )})

497 ret.Add(New Point3D () {.Part.P3 , nearestPoint (.Part.P3 , .Part.P2 , allIntersections )})

498 End If

499500 ’P4 - which originally could connect to P1 and P3

501 If arrayHoldsPoint (. ExterierVertices , .Part.P4) > -1 Then

502 ret.Add(New Point3D () {.Part.P4 , nearestPoint (.Part.P4 , .Part.P1 , allIntersections )})

503 ret.Add(New Point3D () {.Part.P4 , nearestPoint (.Part.P4 , .Part.P3 , allIntersections )})

504 End If

505506 ’Remove Duplicates

507508 Dim index1 As Integer = 0

509 Dim index2 As Integer = 0

510511 While index1 < ret.Count

512 index2 = index1 + 1

513 While index2 < ret.Count

514 If (DirectCast(ret(index1), Point3D ())(0). Equals(DirectCast(ret(index2), Point3D ())(0)) _

515 AndAlso DirectCast(ret(index1), Point3D ())(1). Equals(DirectCast(ret(index2), _

516 Point3D ())(1))) Or _

517 (DirectCast(ret(index1), Point3D ())(1). Equals(DirectCast(ret(index2), _

518 Point3D ())(0)) AndAlso DirectCast(ret(index1), Point3D ())(0). Equals( _

519 DirectCast(ret(index2), Point3D ())(1))) Then

520521 ’Pair at index2 is the same as the pair at index1 , so will remove the pair at index2

522 ret.RemoveAt(index2)

523 Exit While

524 End If

525 index2 += 1

526 End While

527 index1 += 1

528 End While

529530531 ’For to externals which link to each other this will cause to directional valid pairs i.e.

532 ’from A to B, and from B to A, but this isn ’t a problem

533 .ValidVertexPairs.Clear ()

534 .ValidVertexPairs.AddRange(ret)

535 End With

536 Next

537538 End Sub

539540 Private Shared Function nearestPoint(ByVal StartPoint As Point3D , ByVal EndPoint As Point3D , _

541 ByVal intersections As ArrayList) As Point3D

542543 ’Finds the direction from start point to end point , then checks against the intersection points in

544 ’the Shape to see if any others are the same direction , if so returns the closest , if none are then

545 ’returns the EndPoint

546547 Dim subVects As Point3D = SubVector(EndPoint , StartPoint)

548 Dim dir As Point3D = NormaliseVector(subVects)

549 Dim dist As Double = MagnitudeVector(subVects)

550 Dim closestDist As Double = dist

551 Dim closestPoint As Point3D = EndPoint

552 Dim tmpDist As Double

553 For Each p As Point3D In intersections

554 subVects = SubVector(p, StartPoint)

555 If NormaliseVector(subVects ). Equals(dir) Then

556 tmpDist = MagnitudeVector(subVects)

557 If tmpDist < closestDist Then

558 closestDist = tmpDist

559 closestPoint = p

560 End If

561 End If

562 Next

563

82

Page 90: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

564 Return closestPoint

565 End Function

566567 Private Shared Function arrayHoldsPoint(ByVal array As ArrayList , ByVal point As Point3D) As Integer

568 Dim index As Integer

569 For Each p As Point3D In array

570 If p.Equals(point) Then Return index

571 index += 1

572 Next

573 Return -1

574 End Function

575576 Private Shared Function MakeAndAddQuadsToQuadList(ByVal ValidPairs () As Object , _

577 ByVal OtherPart As Part_Quadrilateral , ByVal OwnPart As Part_Quadrilateral , _

578 ByRef quadList As ArrayList , ByVal ConainsInternalVertices As Boolean) As Boolean

579580 Dim newQuads As ArrayList = MakeQuads(ValidPairs , OtherPart , OwnPart.Norm , ConainsInternalVertices)

581 If newQuads IsNot Nothing AndAlso newQuads.Count > 0 Then

582 ’If the new part is the same as the old part , then don ’t add it to the list ,

583 ’and continue to next part

584 If newQuads.Count = 1 AndAlso CheckParts(DirectCast(newQuads (0), Part_Quadrilateral), OwnPart) Then

585 Return False

586 Else

587 ’1.2.6 - Add new quads to the list

588 For Each q As Part_Quadrilateral In newQuads

589 q.RealColour = OwnPart.RealColour

590 q.colour = OwnPart.colour

591 q.Norm = OwnPart.Norm

592593 quadList.Add(q)

594 Next

595596 ’remove the old one

597 quadList.Remove(OwnPart)

598 Return True

599 End If

600 End If

601602 End Function

603604 Private Shared Function CheckParts(ByVal Part1 As Part_Quadrilateral , ByVal Part2 As Part_Quadrilateral) As Boolean

605 Dim part1Vs As New ArrayList

606 Dim part2Vs As New ArrayList

607608 With Part1

609 part1Vs.AddRange(New Point3D () {.P1 , .P2, .P3 , .P4})

610 End With

611612 With Part2

613 part2Vs.AddRange(New Point3D () {.P1 , .P2, .P3 , .P4})

614 End With

615616 Dim count As Integer = 0

617 For Each p1 As Point3D In part1Vs

618 If arrayHoldsPoint(part2Vs , p1) > -1 Then count += 1

619 Next

620 ’If count = 4 then all the new vertices were in the old shape , and they are the same

621 Return count = 4

622 End Function

623624 Private Shared Function MakeQuads(ByVal ValidPairs () As Object , ByVal CheckPart As Part_Quadrilateral , _

625 ByVal Norm As Point3D , ByVal ConainsInternalVertices As Boolean) As ArrayList

626627 ’1.2.2a - No internal points , so keep valid vertex pairs (found when finding line intersections )

628 ’and join to these to the remaining vertices if it doesn ’t mean passing through CheckPart

629630 Dim ret As New ArrayList

631632 Dim newQuadObj As Part_Quadrilateral

633 Dim newQuad As ArrayList = getPointsIJoin2(ValidPairs , False , CheckPart)

634 If newQuad Is Nothing Then Return Nothing

635 ’Its a valid quad

636 ’Now make correct orientation and then create Part_Quadrilateral object

637 newQuadObj = MakeQuad(newQuad , Norm , ConainsInternalVertices)

638 If Not newQuadObj Is Nothing Then

639 ret.Add(newQuadObj)

640 End If

641642 ’Removes used points , so next time round the next correct quad can be made

643 Dim points () As Point3D

644 Dim pairsIndex As Integer

645 For Each p As Point3D In newQuad

646 pairsIndex = 0

647 While pairsIndex < ValidPairs.Length

648 points = DirectCast(ValidPairs(pairsIndex), Point3D ())

649 If points (0). Equals(p) OrElse points (1). Equals(p) Then

650 ValidPairs = removeObject(ValidPairs , pairsIndex)

651 If ValidPairs.Length = 0 Then Exit For

652 Else

653 pairsIndex += 1

654 End If

655 End While

656 Next

657 If ValidPairs.Length > 0 Then

658 Dim tmpQuads As ArrayList = MakeQuads(ValidPairs , CheckPart , Norm , ConainsInternalVertices)

83

Page 91: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

659 If Not tmpQuads Is Nothing Then

660 ret.AddRange(tmpQuads)

661 End If

662 End If

663664 Return ret

665666 End Function

667668 Private Shared Function MakeQuad(ByVal vertices As ArrayList , ByVal Norm As Point3D , _

669 ByVal ContainsInternalVertices As Boolean) As Part_Quadrilateral

670671 ’1.2.5 - Create Part_Quadrilateral Object from sorted vertices

672673 ’Need to check that do have 4 points , and if no duplicate the final point until I do have 4 points!

674 If vertices.Count = 3 Then

675 vertices.Add(vertices.Item(vertices.Count - 1))

676 ElseIf vertices.Count < 3 Then

677 Return Nothing

678 ElseIf vertices.Count > 4 Then

679 If ContainsInternalVertices = False Then

680 ’Have too many vertices , need to either detect a vertex in the middle of a straight line , or

681 ’cut the shape into multiple quads

682683 ’Test if a vertex on a straight line between two others

684685 ’1.2.4a - Check if vertex is on the same line as that between two other vertices , if so remove

686 ’the middle one. Only if there are no internal vertices to the shape

687 Dim index1 , index2 , index3 As Integer

688 Dim counter2 , counter3 As Integer

689690 Dim initialPoint As Point3D

691 Dim currentTestPoint , testPoint , testDir As Point3D

692 Dim testDist As Double

693 Dim removed As Boolean = False

694695 Dim SubVects As Point3D

696697 While vertices.Count > 4

698 Dim initialVerticesCount As Integer = vertices.Count

699 index1 = 0

700 While index1 < (vertices.Count - 1)

701 initialPoint = DirectCast(vertices(index1), Point3D)

702 index2 = index1

703 counter2 = 0

704705 While counter2 < vertices.Count - 1

706 index2 = (index2 + 1) Mod vertices.Count

707 testPoint = DirectCast(vertices(index2), Point3D)

708 SubVects = SubVector(testPoint , initialPoint)

709 testDir = NormaliseVector(SubVects)

710 testDist = MagnitudeVector(SubVects)

711 counter3 = 0

712713 index3 = index2

714 While counter3 < (vertices.Count - 2)

715 index3 = (index3 + 1) Mod vertices.Count

716 currentTestPoint = DirectCast(vertices(index3), Point3D)

717 SubVects = SubVector(currentTestPoint , initialPoint)

718 If NormaliseVector(SubVects ). Equals(testDir) Then

719 If MagnitudeVector(SubVects) < testDist Then

720 vertices.Remove(currentTestPoint)

721 removed = True

722 Exit While

723 End If

724 End If

725726 counter3 += 1

727 End While

728 If removed Then Exit While

729 counter2 += 1

730 End While

731 If removed Then Exit While

732 index1 += 1

733 End While

734735 removed = False

736 If vertices.Count = initialVerticesCount Then

737 MsgBox("PANIC")

738 Exit While

739 End If

740 End While

741 Else

742 ’Need to sort out shapes with internals which correctly gives shapes with more than four vertices

743 Dim i As Integer = 0

744 End If

745 End If

746747 If vertices.Count > 4 Then Return Nothing

748749 ’1.2.3 - Sort vertices into counter clockwise direction

750751 ’If the signed area is positive then the vertices are counter clockwise

752 ’ Equation for signed area - 2 A(P) = (N . (sum_{i=0}^{n -1} (v_i x v_{i+1})))

753

84

Page 92: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

754 Dim verts() As Point3D = DirectCast(vertices.ToArray(GetType(Point3D)), Point3D ())

755756 Dim SumOfCrossProducts As Point3D = AddVector(CrossProductVector(verts (0), verts (1)), _

757 AddVector(CrossProductVector(verts(1), verts (2)), _

758 CrossProductVector(verts (2), verts (3))))

759760 Dim ret As New Part_Quadrilateral

761 If DotProductVector(Norm , SumOfCrossProducts) > 0 Then

762 ret.P1 = verts (0)

763 ret.P2 = verts (1)

764 ret.P3 = verts (2)

765 ret.P4 = verts (3)

766 Else

767 ret.P1 = verts (0)

768 ret.P2 = verts (3)

769 ret.P3 = verts (2)

770 ret.P4 = verts (1)

771 End If

772773 Return ret

774 End Function

775776 Private Shared Function getPointsIJoin2(ByVal ValidPairs () As Object , ByVal ReturnEndPoints As Boolean , _

777 Optional ByVal CheckPart As Part_Quadrilateral = Nothing , _

778 Optional ByVal TestPoint As Point3D = Nothing) As ArrayList

779780 ’Find an end , or find that valid pairs define a complete loop , and then start adding points

781 ’either from the end , or from the start point

782783 ’Have to specify checkpart if want all the points , not just the end points

784 If ReturnEndPoints = False And CheckPart Is Nothing Then Return Nothing

785786 If TestPoint Is Nothing Then TestPoint = DirectCast(ValidPairs (0), Point3D ())(0)

787 Dim tester As Point3D = TestPoint

788 Dim previous As Point3D = Nothing

789 Dim foundPoint As Boolean = False

790 Dim startPoint As Point3D = Nothing

791 Dim realStartPoint As Point3D

792793 Do

794 If startPoint Is Nothing OrElse Not tester.Equals(startPoint) Then

795 If startPoint Is Nothing Then startPoint = TestPoint

796 For Each points () As Point3D In ValidPairs

797 If points (0). Equals(tester) And (previous Is Nothing OrElse Not points (1). Equals(previous )) Then

798 previous = tester

799 tester = points (1)

800 foundPoint = True

801 Exit For

802 ElseIf points (1). Equals(tester) And (previous Is Nothing OrElse Not points (0). Equals(previous )) Then

803 previous = tester

804 tester = points (0)

805 foundPoint = True

806 Exit For

807 End If

808 Next

809 End If

810 If Not foundPoint Then

811 ’We didn ’t find a point , so is either the end or we have circled back to the startpoint

812 realStartPoint = tester

813 Exit Do

814 Else

815 foundPoint = False

816 End If

817 Loop

818819 Dim ret As New ArrayList

820 ret.Add(realStartPoint)

821 startPoint = Nothing

822 foundPoint = False

823 tester = realStartPoint

824 previous = Nothing

825826 Do

827 ’If startPoint Is Nothing Then

828 If startPoint Is Nothing Then startPoint = realStartPoint

829 For Each points () As Point3D In ValidPairs

830 If points (0). Equals(tester) And (previous Is Nothing OrElse Not points (1). Equals(previous )) Then

831 If points (1). Equals(startPoint) Then Exit For

832 previous = tester

833 tester = points (1)

834 foundPoint = True

835 ret.Add(tester)

836 Exit For

837 ElseIf points (1). Equals(tester) And (previous Is Nothing OrElse Not points (0). Equals(previous )) Then

838 If points (0). Equals(startPoint) Then Exit For

839 previous = tester

840 tester = points (0)

841 foundPoint = True

842 ret.Add(tester)

843 Exit For

844 End If

845 Next

846 ’End If

847 If (Not foundPoint) Or (ret.Count > 100) Then ’ValidPairs .Length) Then

848 ’We didn ’t find a point , so is either the end or we have circled back to the startpoint

85

Page 93: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

849 ’and now have our list of vertices

850851 ’If ret.Count > ValidPairs .Length then there has been a problem. Most likely the

852 ’valid pairs array has not been created properly , and has points linking back to the

853 ’wrong points. This will happen if the intersection between two quads isn ’t properly

854 ’recognised . If there is an error this loop will continue indefinitly just jumping between the

855 ’same points. This will jump out if it has gone wrong. It won ’t create a proper shape though.

856 ’Changed to a catch of 100, as there won ’t be shapes created with 100 vertices

857 ’this needed changing as there will be more vertices than valid pairs when

858 ’running test 1.2.2d, and having shapes created with more than for vertices due

859 ’to internal vertices.

860 Exit Do

861 Else

862 foundPoint = False

863 End If

864 Loop

865866867 ’The first point will be one of the open ends , and the last point the other open end. Then just

868 ’need to check these can join!

869 Dim pStart As Point3D = DirectCast(ret(0), Point3D)

870 Dim pEnd As Point3D = DirectCast(ret(ret.Count - 1), Point3D)

871872 If ReturnEndPoints Then

873 ret.Clear ()

874 ret.Add(pStart)

875 ret.Add(pEnd)

876 Return ret

877 End If

878879 If CanSee(pStart , pEnd , CheckPart) AndAlso (Not LineInside(pStart , pEnd , CheckPart )) Then

880 Return ret

881 Else

882 MsgBox("Error joining first and last vertices")

883 Return Nothing

884 End If

885886 End Function

887888 Private Shared Function CanSee(ByVal v1 As Point3D , ByVal v2 As Point3D , ByVal checkpart As Part_Quadrilateral) _

889 As Boolean

890891 ’Detects if vertex 1 (v1) can join with vertex 2 (v2) without intercepting with the checkpart

892893 Dim Index1 , Index2 As Integer

894 Dim checkVertices () As Point3D

895896 With checkpart

897 checkVertices = New Point3D () {.P1, .P2, .P3, .P4}

898 End With

899 For i As Integer = 0 To 3

900 Index1 = i

901 If i < 3 Then

902 Index2 = i + 1

903 Else

904 Index2 = 0

905 End If

906907 If GetLineInterceptionPoint(v1 , v2 , checkVertices(Index1), checkVertices(Index2 )) IsNot Nothing Then

908 Return False

909 End If

910 Next

911912 Return True

913 End Function

914915 Private Shared Sub DisplayIntersections(ByVal shp1 As Shape , ByVal shp2 As Shape , ByRef LM As LegoModel)

916 ’Adds crosses to the final legoModel (LM), these are then displayed on the final model.

917 ’Yellow cross for vertices intersecting

918 ’Green cross for internal vertices

919 ’Cyan cross for line intersections

920921 Dim shapes () As Shape = New Shape() {shp1 , shp2}

922 For Each s As Shape In shapes

923 For Each p As Point3D In s.IntersectionVertices

924 Dim lp As New Part_Line

925 lp.RealColour = New Single () {1, 1, 0, 1}

926 lp.P1 = New Point3D(p.x + 1, p.y + 1, p.z)

927 lp.P2 = New Point3D(p.x - 1, p.y - 1, p.z)

928 Dim lp2 As New Part_Line

929 lp2.RealColour = New Single () {1, 1, 0, 1}

930 lp2.P1 = New Point3D(p.x + 1, p.y - 1, p.z)

931 lp2.P2 = New Point3D(p.x - 1, p.y + 1, p.z)

932 LM.addPart(lp)

933 LM.addPart(lp2)

934 Next

935936 For Each p As Point3D In s.InternalVertices

937 Dim lp As New Part_Line

938 lp.RealColour = New Single () {0, 1, 0, 1}

939 lp.P1 = New Point3D(p.x, p.y + 1, p.z + 1)

940 lp.P2 = New Point3D(p.x, p.y - 1, p.z - 1)

941 Dim lp2 As New Part_Line

942 lp2.RealColour = New Single () {0, 1, 0, 1}

943 lp2.P1 = New Point3D(p.x, p.y - 1, p.z + 1)

86

Page 94: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

944 lp2.P2 = New Point3D(p.x, p.y + 1, p.z - 1)

945 LM.addPart(lp)

946 LM.addPart(lp2)

947 Next

948949 For Each p As Point3D In s.LineIntersections

950 Dim lp As New Part_Line

951 lp.RealColour = New Single () {0, 1, 1, 1}

952 lp.P1 = New Point3D(p.x - 1, p.y, p.z + 1)

953 lp.P2 = New Point3D(p.x + 1, p.y, p.z - 1)

954 Dim lp2 As New Part_Line

955 lp2.RealColour = New Single () {0, 1, 1, 1}

956 lp2.P1 = New Point3D(p.x + 1, p.y, p.z + 1)

957 lp2.P2 = New Point3D(p.x - 1, p.y, p.z - 1)

958 LM.addPart(lp)

959 LM.addPart(lp2)

960 Next

961 Next

962 End Sub

963964 Private Shared Function GetQuads(ByVal Parts As ArrayList) As ArrayList

965 Dim ret As New ArrayList

966 For Each p As LegoPart In Parts

967 Select Case p.type

968 Case PartType.PartFile

969 With DirectCast(p, Part_External)

970 If Not .Stud Then ’remove studs

971 ret.AddRange(GetQuads (.part.Parts ))

972 End If

973 End With

974 Case PartType.Quadrilateral

975 ret.Add(p)

976 End Select

977 Next

978 Return ret

979 End Function

980981 Private Shared Sub Check1_1_1(ByRef Quads () As Part_Quadrilateral)

982 ’If all 4 vertices are the same then remove (this is an optimisation , as this case would be found in 1.1.2

983 ’however that is more complex , and so reducing the number of quadrilaterals to be checked here speeds that

984 ’process up. This is also quite a common case if bricks are placed next to each other , or end to end.

985986 Dim mainIndex As Integer

987 Dim checkIndex As Integer

988 Dim mainPart As Part_Quadrilateral

989 Dim checkPart As Part_Quadrilateral

990991 While mainIndex < Quads.Length

992 ’If new parts are added to quads this will still work , whereas the inbuilt for each will fail

993 ’if the list changes

994995 mainPart = Quads(mainIndex)

996 ’Only check the items following the main part in the list (as the previous ones have already

997 ’been check against this main part)

998999 For checkIndex = mainIndex + 1 To Quads.Length - 1

1000 checkPart = Quads(checkIndex)

1001 If CheckParts(mainPart , checkPart) Then ’1.1.1 - If all 4 vertices are the same remove both quads

1002 ’Done in this order , because checkpart is is always below mainpart , and therefore will not

1003 ’affect the mainindex

1004 Quads = removeQuad(Quads , checkIndex)

1005 Quads = removeQuad(Quads , mainIndex)

1006 mainIndex -= 1 ’Done , else will skip the next item (which is now in the mainIndex location)

1007 Exit For

1008 End If

1009 Next

1010 mainIndex += 1

1011 End While

1012 End Sub

10131014 Private Shared Function CheckIfPointIsVertex(ByVal Point As Point3D , ByVal Quad As Part_Quadrilateral) As Boolean

1015 ’Checks if Point is one of the vertices on the quad

1016 With Point

1017 Return .Equals(Quad.P1) Or .Equals(Quad.P2) Or .Equals(Quad.P3) Or .Equals(Quad.P4)

1018 End With

1019 End Function

10201021 Private Shared Function IntersectVertexCheck1_1_2(ByVal Quad1 As Part_Quadrilateral , _

1022 ByVal Quad2 As Part_Quadrilateral , ByVal allowVertices As Boolean) As Shape

10231024 ’Both 1.1.2 and 1.1.3 are carried out here

1025 ’1.1.2 - Find if mainpart vertices are inside or outside the check quad

1026 ’1.1.3 - Find interception of boundary lines

10271028 ’1.1.2 - Starts here

10291030 ’Split into two triangles .

1031 ’Given corners of triangle are A, B, C and given point is D, then D is inside iff

1032 ’area(ABC) = area(ABD) + area(ACD) + area(BCD ). Point intersects if one of the areas is 0

10331034 ’Area of triangle = 0.5|(B-A)x(C-A)| (cross product)

10351036 ’Triangle 1 = p1 ,p2 ,p3 Triangle 2 = p1 ,p3 ,p4

10371038 ’e.g. q1t1 = quad 1, triangle 1

87

Page 95: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

1039 Dim Triangles ()() As Point3D = MakeTriangles(Quad2)

10401041 ’Calculate triangle Areas to test against

1042 Dim q2t1Area As Double = CalcTriangleArea(Triangles (0))

1043 Dim q2t2area As Double = CalcTriangleArea(Triangles (1))

10441045 Dim q1vertices () As Point3D = {Quad1.P1, Quad1.P2 , Quad1.P3 , Quad1.P4}

1046 Dim q2vertices () As Point3D = {Quad2.P1, Quad2.P2 , Quad2.P3 , Quad2.P4}

10471048 ’Check for quad1 intersecting

1049 Dim quad1Shape As New Shape

1050 quad1Shape.Part = Quad1

10511052 For Each q1vertex As Point3D In q1vertices

1053 ’check if vertex is the same as one in the other shape

1054 If CheckIfPointIsVertex(q1vertex , Quad2) Then

1055 quad1Shape.IntersectionVertices.Add(q1vertex)

1056 Else

1057 Select Case (DoesIntercept(Triangles (0), q2t1Area , q1vertex ))

1058 Case eInterceptType.Intercept

1059 quad1Shape.IntersectionVertices.Add(q1vertex)

1060 Case eInterceptType.Internal

1061 quad1Shape.InternalVertices.Add(q1vertex)

1062 Case eInterceptType.None

1063 Select Case (DoesIntercept(Triangles (1), q2t2area , q1vertex ))

1064 Case eInterceptType.Intercept

1065 quad1Shape.IntersectionVertices.Add(q1vertex)

1066 Case eInterceptType.Internal

1067 quad1Shape.InternalVertices.Add(q1vertex)

1068 Case eInterceptType.None

1069 quad1Shape.ExterierVertices.Add(q1vertex)

1070 End Select

1071 End Select

1072 End If

1073 Next

10741075 ’1.1.3 - Find interception of the boundary lines

10761077 ’Checks edge against every other edge on the other quad

1078 Dim thisLineIntersections As New ArrayList

1079 Dim quad1index , quad1index2 , quad2index , quad2index2 As Integer

1080 Dim v1, v2 As Point3D

1081 For quad1index = 0 To 3

1082 ’When index is 3 then we create the line from 3 back to 0

1083 quad1index2 = (( quad1index Mod 3) + 1) - CInt(Int(quad1index / 3))

1084 v1 = q1vertices(quad1index)

1085 v2 = q1vertices(quad1index2)

1086 thisLineIntersections.Clear()

10871088 For quad2index = 0 To 3

1089 ’When index is 3 then we create the line from 3 back to 0

1090 quad2index2 = (( quad2index Mod 3) + 1) - CInt(Int(quad2index / 3))

1091 Dim interception As Point3D = _

1092 GetLineInterceptionPoint(v1, v2, q2vertices(quad2index), q2vertices(quad2index2 ))

1093 If interception IsNot Nothing Then

1094 quad1Shape.LineIntersections.Add(interception)

1095 thisLineIntersections.Add(interception)

1096 End If

1097 Next

1098 Next

10991100 ’These methods will find overlapping interceptions , therefore the interception list is cleared of duplications

1101 ’Dim index , index2 As Integer

11021103 RemoveDuplicates(quad1Shape.IntersectionVertices)

1104 RemoveDuplicates(quad1Shape.LineIntersections)

11051106 Return quad1Shape

1107 End Function

11081109 Private Shared Function LineInside(ByVal p1 As Point3D , ByVal p2 As Point3D , ByVal testQuad As Part_Quadrilateral) _

1110 As Boolean

11111112 ’To detect if the line is inside , points p1 , and p2 will be brought together very slightly

1113 ’(i.e. shorten the line ). Then will test if either of these points are inside the test quad

1114 ’then the function will return false , else will return true

11151116 ’Finds vector direction from p1 to p2 (i.e. the normal vector in this direction

1117 Dim triangles ()() As Point3D = MakeTriangles(testQuad)

1118 ’Make it a half unit to shorten the line from each end

1119 Dim dir As Point3D = ScaleVector(NormaliseVector(SubVector(p2 , p1)), 0.5)

1120 Dim testPoints () As Point3D = New Point3D () {AddVector(p1, dir), SubVector(p2, dir)}

1121 Dim ret As Boolean = True

1122 Dim tmpRet As Boolean = False

11231124 For Each p As Point3D In testPoints

1125 For Each t() As Point3D In triangles

1126 ’If one or the other triangle has the point then tmpRet will be true

1127 tmpRet = tmpRet Or (DoesIntercept(t, CalcTriangleArea(t), p) = eInterceptType.Internal)

1128 Next

1129 ’If all the points are internal then ret will be true , else will be false

1130 ret = ret And tmpRet

1131 tmpRet = False

1132 Next

1133 Return ret

88

Page 96: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

1134 End Function

11351136 Private Shared Function GetLineInterceptionPoint(ByVal L1P1 As Point3D , ByVal L1P2 As Point3D , _

1137 ByVal L2P1 As Point3D , ByVal L2P2 As Point3D) As Point3D

11381139 ’Find if lines are skew , if so they don ’t intercept

1140 ’(x1 - x3 ).[( x2 - x1)x(x4 - x3)] != 0

1141 ’a = (x1 - x3), b=(x2 - x1), c=(x4 - x3)

11421143 Dim a, b, c As Point3D

11441145 a = SubVector(L1P1 , L2P1)

1146 b = SubVector(L1P2 , L1P1)

1147 c = SubVector(L2P2 , L2P1)

1148 If DotProductVector(a, CrossProductVector(b, c)) = 0 Then

1149 ’don ’t skew , so can now check for interception

11501151 ’x = x1 + b ( [(a x c) . (b x c)] / |b x c| ^ 2 )

1152 ’x is point of interception , updated a = x3 - x1 now

1153 ’d = a x c, e = b x c, f = |b x c|^2

11541155 a = SubVector(L2P1 , L1P1)

1156 Dim d, e, x As Point3D

1157 Dim f As Double

1158 d = CrossProductVector(a, c)

1159 e = CrossProductVector(b, c)

1160 f = CrossProductMagnitude(b, c) ^ 2

11611162 Dim tmp As Single = CSng(DotProductVector(d, e) / f)

1163 x = AddVector(L1P1 , ScaleVector(b, tmp))

1164 If Single.IsNaN(x.x) Then

1165 ’No interception

1166 Else

1167 ’This gives interceptions of infinite length lines , so need to check that the actual

1168 ’interception is within the length of the line

1169 If IsCorrectInterception(L1P1 , L1P2 , L2P1 , L2P2 , x) Then

1170 Return x

1171 End If

1172 End If

1173 End If

11741175 Return Nothing

1176 End Function

11771178 Private Shared Function IsCorrectInterception(ByVal L1P1 As Point3D , ByVal L1P2 As Point3D , _

1179 ByVal L2P1 As Point3D , ByVal L2P2 As Point3D , ByVal Interception As Point3D) As Boolean

11801181 ’Sort the min and max of each dimension

1182 Dim lines ()() As Point3D = New Point3D ()() {New Point3D () {L1P1 , L1P2}, New Point3D () {L2P1 , L2P2}}

1183 Dim ret As Boolean

11841185 ’See if want to allow vertices to be collided with or not ,

1186 ’if not then don ’t include the vertices of quad 1 and quad 2

11871188 ’AllowVertices means ’It is allowed to collide with vertices , and still be a correct Interception

1189 If (Interception.IntEquals(L1P1) Or Interception.IntEquals(L1P2) Or Interception.IntEquals(L2P1) Or _

1190 Interception.IntEquals(L2P2)) Then

1191 Return False

1192 End If

11931194 For Each Line As Point3D () In lines

11951196 Dim xMin , xMax , yMin , yMax , zMin , zMax As Single

1197 If Line (0).x > Line (1).x Then

1198 xMin = Line (1).x : xMax = Line (0).x

1199 Else

1200 xMin = Line (0).x : xMax = Line (1).x

1201 End If

12021203 If Line (0).y > Line (1).y Then

1204 yMin = Line (1).y : yMax = Line (0).y

1205 Else

1206 yMin = Line (0).y : yMax = Line (1).y

1207 End If

12081209 If Line (0).z > Line (1).z Then

1210 zMin = Line (1).z : zMax = Line (0).z

1211 Else

1212 zMin = Line (0).z : zMax = Line (1).z

1213 End If

12141215 With Interception

1216 ret = (.x >= xMin And .x <= xMax And .y >= yMin And .y <= yMax And .z >= zMin And .z <= zMax)

1217 End With

12181219 ’It it fails with the first line , don ’t need to check with the second , and will return false

1220 ’if second line fails

1221 If ret = False Then Return False

1222 Next

12231224 ’Nether line fails so interception ok

1225 Return True

1226 End Function

12271228 Private Shared Function DoesIntercept(ByVal Triangle () As Point3D , ByVal TriangleArea As Double , _

89

Page 97: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

1229 ByVal point As Point3D) As eInterceptType

12301231 Dim checkArea1 As Double = CalcTriangleArea(New Point3D () {Triangle (0), Triangle (1), point})

1232 Dim checkArea2 As Double = CalcTriangleArea(New Point3D () {Triangle (0), Triangle (2), point})

1233 Dim checkArea3 As Double = CalcTriangleArea(New Point3D () {Triangle (1), Triangle (2), point})

12341235 ’checkArea2 is the triangle formed along the edge in the middle of the

1236 ’quad , see makeTriangles . Therefore if this area is 0 it is actually an internal

1237 ’point , not an interception . Vertices have been removed before the function so

1238 ’won ’t be wrongly specified

1239124012411242 If Math.Round(TriangleArea) = Math.Round(checkArea1 + checkArea2 + checkArea3) Then

1243 ’Only if the quad norms are the same is the vertex counted as internal , as it will need to cut the shape

1244 ’its overlapping with , if the normals aren ’t the same then this won ’t need to be done , and therefore is

1245 ’counted as an interception

1246 ’### Update , quads in different direction don ’t count as any kind of interception , and will not reach

1247 ’this function

12481249 ’If CInt( checkArea2 ) = 0 then this is internal , as this tests along the

1250 ’internal diagonal through the quad formed by spliting it into two triangles

1251 If CInt(checkArea1) = 0 Or CInt(checkArea3) = 0 Then

1252 Return eInterceptType.Intercept

1253 Else

1254 Return eInterceptType.Internal

1255 End If

1256 Else

1257 Return eInterceptType.None

1258 End If

1259 End Function

12601261 Private Shared Function CalcTriangleArea(ByVal Points () As Point3D) As Double

1262 Dim ret As Double = Math.Abs(CrossProductMagnitude(SubVector(Points (1), Points (0)), _

1263 SubVector(Points (2), Points (0)))) / 2

1264 If Double.IsNaN(ret) Then ret = 0

1265 Return ret

1266 End Function

12671268 Private Shared Function removeObject(ByVal array () As Object , ByVal Index As Integer) As Object ()

1269 Dim ret(array.Length - 2) As Object

1270 Dim writeIndex As Integer = 0

1271 For i As Integer = 0 To array.Length - 1

1272 If i <> Index Then

1273 ret(writeIndex) = array(i)

1274 writeIndex += 1

1275 End If

1276 Next

1277 Return ret

1278 End Function

12791280 Private Shared Function removeQuad(ByVal Quads As Part_Quadrilateral (), ByVal Index As Integer) _

1281 As Part_Quadrilateral ()

1282 Dim ret(Quads.Length - 2) As Part_Quadrilateral

1283 Dim writeIndex As Integer = 0

1284 For i As Integer = 0 To Quads.Length - 1

1285 If i <> Index Then

1286 ret(writeIndex) = Quads(i)

1287 writeIndex += 1

1288 End If

1289 Next

1290 Return ret

1291 End Function

12921293 Private Shared Function PointOnLine(ByVal L1P1 As Point3D , ByVal L1P2 As Point3D , ByVal TestPoint As Point3D) _

1294 As Boolean

1295 ’If direction between L1P1 and L1P2 is the same as that betwenn L1P1 and

1296 ’testPoint , and that testPoint is closer to L1P1 than L1P2 is then its on the line

1297 If L1P1.Equals(TestPoint) Or L1P2.Equals(TestPoint) Then

1298 ’If point is one of the vertices then its on the line

1299 Return True

1300 End If

1301 If NormaliseVector(SubVector(L1P2 , L1P1 )). Equals(NormaliseVector(SubVector(TestPoint , L1P1 ))) Then

1302 Return MagnitudeVector(SubVector(TestPoint , L1P1)) <= MagnitudeVector(SubVector(L1P2 , L1P1))

1303 End If

1304 Return False

1305 End Function

1306 End Class

90

Page 98: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

D.10 Transformer.vb

Applies the transformations to all the parts within the internal representation afterloading, and calculates the normals, and correct colours of all the parts.

1 Imports LEGO_Smoothing.ModelDefs

2 Imports LEGO_Smoothing.Common

34 Public Class Transformer

56 Private Shared TransformMatrixStack As New Stack

7 Private Const DefaultCurCol As Integer = 7

89 Public Shared Sub TransformModel(ByVal LM As LegoModel)

10 InternalTransformModel(LM, DefaultCurCol , False)

11 End Sub

1213 Private Shared Sub InternalTransformModel(ByVal LM As LegoModel , ByVal curCol As Integer , ByVal Invert As Boolean)

14 ’This sub takes all the loaded parts , and applies the transformations specified when loading , and also sets the

15 ’colours so it doesn ’t have to keep doing the lookup on each frame , and sorts inversions of the

16 ’individual items. Its done here as the models are static , so don ’t need to change once loaded , and saves doing

17 ’it on the fly for each frame , which causes very low FPS rate.

1819 If LM IsNot Nothing AndAlso LM.Parts IsNot Nothing Then

20 For Each p As LegoPart In LM.Parts

21 Select Case p.type

22 Case PartType.PartFile

23 TransformExternal(DirectCast(p, Part_External), curCol)

24 Case PartType.Line

25 TransformLine(DirectCast(p, Part_Line), curCol)

26 Case PartType.Triangle

27 TransformTriangle(DirectCast(p, Part_Triangle), curCol , Invert)

28 Case PartType.Quadrilateral

29 TransformQuad(DirectCast(p, Part_Quadrilateral), curCol , Invert)

30 Case PartType.SpecialLine

31 TransformSpecialLine(DirectCast(p, Part_SpecialLine), curCol)

32 End Select

33 Next

34 End If

35 End Sub

3637 Private Shared Sub TransformExternal(ByVal p As Part_External , ByVal curCol As Integer)

38 Dim usedCol As Integer

3940 TransformMatrixStack.Push(p.transformMatrix)

4142 Select Case p.colour

43 Case 16 ’Current Colour

44 usedCol = curCol

45 Case 24 ’Reverse Of Current Colour

46 usedCol = GetReversedCol(curCol)

47 Case Else ’All other cases the colour has been given so use it

48 usedCol = p.colour

49 End Select

5051 InternalTransformModel(p.part , usedCol , p.inverted)

52 TransformMatrixStack.Pop()

53 End Sub

5455 Private Shared Sub TransformLine(ByVal p As Part_Line , ByVal curCol As Integer)

56 p.P1 = TransformPoint(p.P1)

57 p.P2 = TransformPoint(p.P2)

5859 p.RealColour = GetColorArray(p.colour , curCol)

60 End Sub

6162 Private Shared Sub TransformTriangle(ByVal p As Part_Triangle , ByVal curCol As Integer , ByVal Invert As Boolean)

63 ’p.Norm = TransformPoint (p.Norm)

6465 If Invert Then

66 Dim tmpPoint As Point3D = TransformPoint(p.P3)

67 p.P2 = TransformPoint(p.P2)

68 p.P3 = TransformPoint(p.P1)

69 p.P1 = tmpPoint.Copy

70 Else

71 p.P1 = TransformPoint(p.P1)

72 p.P2 = TransformPoint(p.P2)

73 p.P3 = TransformPoint(p.P3)

74 End If

7576 p.Norm = Common.CalcNormal(New Point3D () {p.P1, p.P2, p.P3})

7778 p.RealColour = GetColorArray(p.colour , curCol)

79 End Sub

8081 Private Shared Sub TransformQuad(ByVal p As Part_Quadrilateral , ByVal curCol As Integer , ByVal Invert As Boolean)

82 ’p.Norm = TransformPoint (p.Norm)

8384 If Invert Then

85 Dim tmpPoint As Point3D = TransformPoint(p.P3)

86 p.P2 = TransformPoint(p.P2)

87 p.P3 = TransformPoint(p.P1)

88 p.P4 = TransformPoint(p.P4)

91

Page 99: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

89 p.P1 = tmpPoint.Copy

90 Else

91 p.P1 = TransformPoint(p.P1)

92 p.P2 = TransformPoint(p.P2)

93 p.P3 = TransformPoint(p.P3)

94 p.P4 = TransformPoint(p.P4)

95 End If

9697 p.Norm = Common.CalcNormal(New Point3D () {p.P1, p.P2, p.P3, p.P4})

9899 p.RealColour = GetColorArray(p.colour , curCol)

100 End Sub

101102 Private Shared Sub TransformSpecialLine(ByVal p As Part_SpecialLine , ByVal curCol As Integer)

103 p.LineP1 = TransformPoint(p.LineP1)

104 p.LineP2 = TransformPoint(p.LineP2)

105 p.TestP1 = TransformPoint(p.TestP1)

106 p.TestP2 = TransformPoint(p.TestP2)

107108 p.RealColour = GetColorArray(p.colour , curCol)

109 End Sub

110111 Private Shared Function TransformPoint(ByVal P As Point3D) As Point3D

112 Dim arr() As Object = TransformMatrixStack.ToArray

113 Dim tmpP As New Point3D(P.x, P.y, P.z)

114 Dim oldP As Point3D = tmpP.Copy

115 For i As Integer = 0 To arr.Length - 1 ’ arr.Length - 2 To 0 Step -1

116 With DirectCast(arr(i), Matrix)

117 If .Identity Then

118 tmpP.x = oldP.x + .matrix(0, 3)

119 tmpP.y = oldP.y + .matrix(1, 3)

120 tmpP.z = oldP.z + .matrix(2, 3)

121 Else

122 tmpP.x = .matrix(0, 0) * oldP.x + .matrix(0, 1) * oldP.y + .matrix(0, 2) * oldP.z + .matrix(0, 3)

123 tmpP.y = .matrix(1, 0) * oldP.x + .matrix(1, 1) * oldP.y + .matrix(1, 2) * oldP.z + .matrix(1, 3)

124 tmpP.z = .matrix(2, 0) * oldP.x + .matrix(2, 1) * oldP.y + .matrix(2, 2) * oldP.z + .matrix(2, 3)

125 End If

126 End With

127 oldP = tmpP.Copy ’New Point3D(tmpP.x, tmpP.y, tmpP.z) ’Else clones object if do oldP = tmpP

128 Next

129 Return oldP

130 End Function

131132 Private Shared Function GetColorArray(ByVal Col As Integer , ByVal curCol As Integer) As Single ()

133 Dim c As Color = SortColor(Col , curCol)

134 Return New Single () {CSng(c.R / 255), CSng(c.G / 255), CSng(c.B / 255), CSng(c.A / 255)}

135 End Function

136137 Private Shared Function SortColor(ByVal col As Integer , ByVal curCol As Integer) As Color

138 ’Sorts out the colour codes

139140 ’Colours 0 to 15 represent colours as defined by the old style quick basic

141 ’colour codes - would use the built in functionality but it has , at least ,

142 ’blue and red swapped!

143144 Select Case col

145146 Case 0

147 Return Color.Black

148 Case 1

149 Return Color.DarkBlue

150 Case 2

151 Return Color.DarkGreen

152 Case 3

153 Return Color.DarkCyan

154 Case 4

155 Return Color.DarkRed

156 Case 5

157 Return Color.DarkMagenta

158 Case 6

159 Return Color.Brown

160 Case 7

161 Return Color.Gray

162 Case 8

163 Return Color.DarkGray

164 Case 9

165 Return Color.Blue

166 Case 10

167 Return Color.Green

168 Case 11

169 Return Color.Cyan

170 Case 12

171 Return Color.Red

172 Case 13

173 Return Color.Pink

174 Case 14

175 Return Color.Yellow

176 Case 15

177 Return Color.White

178 Case 16

179 ’16 stands for the current colour - i.e that used by the last line

180 Return SortColor(curCol , curCol)

181 Case 24

182 ’Reverse of the current colour

183 Dim chkCol As Integer = curCol

92

Page 100: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

184185 If curCol >= 32 And curCol <= 47 Then ’transparent colours - col + 32

186 chkCol = curCol - 32

187 End If

188189 If curCol >= 256 And curCol <= 511 Then ’dithered colours

190 ’colour = (J * 16) + K + 256

191 ’Use J to for the complementary colour

192193 chkCol = chkCol - 256

194 Dim J As Integer = CInt(Int(chkCol / 16)) ’will give the rounded down number

195 Dim K As Integer = chkCol - (J * 16)

196197 chkCol = J

198 End If

199200 Return SortColor(GetReversedCol(chkCol), curCol)

201202203 Case 72 ’Extra New Colours Below Until the End Select statement

204 Return Color.FromArgb (99, 95, 97)

205 Case 28

206 Return Color.FromArgb (197, 151, 80)

207 Case 17

208 Return Color.FromArgb (186, 255, 206)

209 Case 20

210 Return Color.FromArgb (215, 196, 230)

211 Case 18

212 Return Color.FromArgb (253, 232, 150)

213 Case 27

214 Return Color.FromArgb (215, 240, 0)

215 Case 26

216 Return Color.FromArgb (216, 27, 109)

217 Case 25

218 Return Color.FromArgb (249, 96, 0)

219 Case 134

220 Return Color.FromArgb (147, 135, 103)

221 Case 142

222 Return Color.FromArgb (215, 169, 75)

223 Case 135

224 Return Color.FromArgb (171, 173, 172)

225 Case 137

226 Return Color.FromArgb (106, 122, 150)

227 Case 21

228 Return Color.FromArgb (224, 255, 176)

229 Case 70

230 Return Color.FromArgb (105, 64, 39)

231 Case 71

232 Return Color.FromArgb (163, 162, 164)

233 Case 19

234 Return Color.FromArgb (232, 207, 161)

235 Case 57

236 Return Color.FromArgb (50, 249, 96, 0)

237 Case 22

238 Return Color.FromArgb (129, 0, 123)

239 Case 23

240 Return Color.FromArgb (71, 50, 176)

241242 End Select

243244 If col >= 32 And col <= 47 Then ’(32 + 15) ’32 for transparancy

245 Return Color.FromArgb (128, SortColor(col - 32, curCol )) ’Sets transparancy to 50%

246 End If

247248 If col >= 256 And col <= 511 Then

249 ’Dithered Colours!

250 col = col - 256

251 Dim J As Integer = CInt(Int(col / 16)) ’will give the rounded down number

252 Dim K As Integer = col - (J * 16)

253254 ’mixes the two colour values (rather than using dithered patterns which was used when only 16

255 ’colour displays were available

256257 Dim tmpcol As Color = SortColor(J, curCol)

258 Dim tmpcol2 As Color = SortColor(K, curCol)

259 Return Color.FromArgb(CInt(( tmpcol.R + tmpcol2.R) / 2), CInt(( tmpcol.G + tmpcol2.G) / 2), _

260 CInt(( tmpcol.B + tmpcol2.B) / 2))

261 End If

262263264 End Function

265266 Private Shared Function GetReversedCol(ByVal Col As Integer) As Integer

267 Select Case Col

268 Case 0, 7, 14, 15

269 Return 8

270 Case 1, 2, 3, 4, 5

271 Return Col + 8

272 Case 6, 8

273 Return 0

274 Case 9, 10, 11, 12, 13

275 Return Col - 8

276 Case Else ’For any undefined colour (i.e. the extended colours use darkend colour (i.e. mix with black)

277 Return 7

278 End Select

93

Page 101: DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D …mdv/courses/CM30082/projects... · DEVELOPMENT OF A SYSTEM TO CREATE SMOOTH 3D COMPUTER MODELS USING LEGO BUILDING BLOCKS Submitted

279 End Function

280 End Class

94