Version 7 (modified by 13 years ago) (diff) | ,
---|
PythonOCC omogoča enostavnejšo uporabo jedra modelirnika OpenCascade v jeziku Python. Prednost Pythona v primerjavi z C++ je:
- Prenosljivosti. Programi se interpretirajo in jih ni potrebno prevajati zato delujejo na vseh operacijskih sistemih. So pa nekoliko pošasnejši.
- Enostavnejša namestitev potrebnih knjižnic, brez zahtevne konfiguracije povezovalnih parametrov, ki so značilni za C++.
- Lažje učenje jezika. V interaktivnem načinu obstaja tudi refleksija oziroma dinamično prepoznavanje možnih ukazov v objektu.
Za vaje je potrebno na Windowsih (tudi 63 bitnih) namestiti naslednje pakete:
- Python 2.6 interpreter jezika z osnovnimi knjižnicami
- wxPython za opravljanje z okni
- PythonOCC povezava Pytona z jedrom OpenCascade
Neobvezno vendar priporočljivo je namesti še:
- iPython za interektivno delo
- NumPy za delo z numeričnimi metodami in matrikami.
- SciPy za delo z znanstvenimi algoritmi.
Pred preizkusom prvih primerov je potrebno nastaviti še pot do interpreterja v Moj računalnik -> Lastnosti -> Dodatne nastavitve sistema -> Spremenljivke okolja ... -> Sistemske spremenljivke -> Path -> Uredi -> Vrednost spremeljivke: in na koncu dodamo ;c:\Python26;
. Po tem je potremn računalnik vnovič zagnati.
V primeru, da nam klik na Start->Vsi programi->pythonOCC -> Examples -> Level1 -> HelloWorld -> helloworld.py okno na hitro odpre, vendar modela ne prikaže, imamo težave z OpenGL krmilniki. Najenostavneje težavo odpravimo s spremembo osnovnega prikazovalnika v datoteki C:\Python26\Lib\site-packages\OCC\Display\wxDisplay.py
v kateri platformo darwin
poistovetimo z win32
tako da del kode v tej datoteki izgleda:
if sys.platform=='win32': BaseClass = wx.Panel else: import wx.glcanvas BaseClass = wx.glcanvas.GLCanvas
Predstavitev CAD-jedra Open CASCADE na primerih
Pregled uporabljenih OCC knjižnic
## Importanje različnih knjižnic # Uporabniški vmesnik GUI from OCC.Display.SimpleGui import * # Matematična knjižnica import math # OpenCascade from OCC.gp import * #točke from OCC.BRepBuilderAPI import * #gradimo robove, segmente, mreže ... from OCC.BRepPrimAPI import * #izdelava osnovnih geometrijskih primitivov from OCC.BRepFilletAPI import * #izdelava zaokrožitev
Točnejša navodila, opis funkcij in knjižnic lahko dobimo v PythonOCC dokumentaciji.
Inicializacija zaslona in izdelava grafičnega vmesnika
# OCC.Display.SimpleGui.init_display() returns multiple # values which are assigned here display, start_display, add_menu, add_function_to_menu = \ init_display() draw_bottle() #kličemo CAD model, ki ga želimo prikazati na zaslonu start_display()
Risanje točk v prostoru
Izdelava točk v prostoru je najosnovnejša operacija v OCC.
# Definiranje začetnih točk aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0) aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0) aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0) aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0) aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0)
Izdelava robnih elementov
V naslednjem koraku se iz začetnih točk izdela robove:
# Definiranje geometrije aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4) aSegment1 = GC_MakeSegment(aPnt1 , aPnt2) aSegment2 = GC_MakeSegment(aPnt4 , aPnt5) # Definiranje topologije aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value())
Povezovanje robnih elementov v mreže
Robne elemente se v nadaljevanju združi v mrežo.
# Izdelava mreže aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,aEdge3.Edge())
Uporaba funkcij za izdelavo objektov v prostoru
# Izdelava celotnega profila - mirror xAxis = gp_OX() aTrsf = gp_Trsf() aTrsf.SetMirror(xAxis) aBRepTrsf = BRepBuilderAPI_Transform(aWire.Shape() , aTrsf) aMirroredShape = aBRepTrsf.Shape() aMirroredWire = TopoDS_wire(aMirroredShape) mkWire = BRepBuilderAPI_MakeWire() mkWire.Add(aWire.Wire()) mkWire.Add(aMirroredWire) myWireProfile = mkWire.Wire() # Telo: Iz profila se izdela telo (Funkcija izvleka 3D) myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) aPrismVec = gp_Vec(0 , 0 , myHeight) myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec)
Risanje geometrijskih primitivov
V OCC že obstajajo funkcije za izdelavo geometrijskih primitivov (kocka, valj,...), kar je prikazano na spodnjem primeru.
from OCC.Display.SimpleGui import * from OCC.BRepPrimAPI import * display, start_display, add_menu, add_function_to_menu = init_display() my_box = BRepPrimAPI_MakeBox(10.,20.,30.).Shape() # ali my_cylinder = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , myNeckHeight), kjer so spremenljivke že preddefinirane display.DisplayShape(my_box) # ali display.DisplayShape(my_cylinder) start_display()
Izdelava primera Bottle z uporabo programskega jezika Python in knjižnice OCC
Naslednji primer prikazuje izdelavo primera BottleCAD. Podrobnejši razdelek posameznih delov programske kode dobimo na MakeBottleCAD(C++).
##Copyright 2011 Simon Kulovec (simon.kulovec@lecad.si) ##Example: MakeCADBottle ##This file is part of pythonOCC. ## Importanje različnih knjižnic # Uporabniški vmesnik GUI from OCC.Display.SimpleGui import * # OpenCascade from OCC.gp import * from OCC.TopoDS import * from OCC.GC import * from OCC.BRepBuilderAPI import * from OCC.BRepPrimAPI import * from OCC.BRepFilletAPI import * from OCC.BRepAlgoAPI import * from OCC.Utils.Topology import * from OCC.Geom import * from OCC.Geom2d import * from OCC.GCE2d import * from OCC.BRep import * from OCC.BRepLib import * from OCC.BRepOffsetAPI import * from OCC.TopTools import * from OCC.TopAbs import * from OCC.TopExp import * import math def show_bottle(aRes): display.EraseAll() print dir(display) display.DisplayShape(aRes) def define_points(myWidth, myThickness, myHeight): #Definiranje začetnih točk aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0) aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0) aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0) aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0) aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0) #Definiranje geometrije aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4) aSegment1 = GC_MakeSegment(aPnt1 , aPnt2) aSegment2 = GC_MakeSegment(aPnt4 , aPnt5) #Definiranje topologije aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,aEdge3.Edge()) #Izdelava celotnega profila - mirror xAxis = gp_OX() aTrsf = gp_Trsf() aTrsf.SetMirror(xAxis) aBRepTrsf = BRepBuilderAPI_Transform(aWire.Shape() , aTrsf) aMirroredShape = aBRepTrsf.Shape() aMirroredWire = TopoDS_wire(aMirroredShape) mkWire = BRepBuilderAPI_MakeWire() mkWire.Add(aWire.Wire()) mkWire.Add(aMirroredWire) myWireProfile = mkWire.Wire() # Telo: Iz profila se izdela telo myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) aPrismVec = gp_Vec(0 , 0 , myHeight) myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec) # Telo: Dodamo zaokrožitve (fillet) mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape()) topology_traverser = Topo(myBody.Shape()) for aEdge in topology_traverser.edges(): mkFillet.Add(myThickness / 12. , aEdge) myBody = mkFillet.Shape() #Dodajanje grla na steklenico neckLocation = gp_Pnt(0, 0, myHeight) neckNormal = gp_DZ() neckAx2 = gp_Ax2(neckLocation, neckNormal) myNeckRadius = myThickness / 4 myNeckHeight = myHeight / 10 mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , \ myNeckHeight) myNeck = mkCylinder.Shape(); myBody = BRepAlgoAPI_Fuse(myBody, myNeck) # Izdelava votle steklenice faceToRemove = None zMax = -1; t = Topo(myBody.Shape()) k=1 for aFace in t.faces(): aSurface = BRep_Tool().Surface(aFace) if aSurface.GetObject().IsInstance('Geom_Plane'): aPlane = Handle_Geom_Plane().DownCast(aSurface).GetObject() aPnt = aPlane.Location() aZ = aPnt.Z() if aZ>zMax: faceToRemove = aFace facesToRemove = TopTools_ListOfShape() facesToRemove.Append(faceToRemove) myBody = BRepOffsetAPI_MakeThickSolid(myBody.Shape() , facesToRemove , \ -myThickness/50 , 1.e-3) # Threading : Create Surfaces aCyl1 = Geom_CylindricalSurface(gp_Ax3(neckAx2) , myNeckRadius * 0.99) aCyl2 = Geom_CylindricalSurface(gp_Ax3(neckAx2) , myNeckRadius * 1.05) # Threading : Define 2D Curves aPnt = gp_Pnt2d(2. * 3.141592 , myNeckHeight / 2.) aDir = gp_Dir2d(2. * 3.141592 , myNeckHeight / 4.) aAx2d = gp_Ax2d(aPnt , aDir) aMajor = 2. * 3.141592 aMinor = myNeckHeight / 10. anEllipse1 = Geom2d_Ellipse(aAx2d , aMajor , aMinor) anEllipse2 = Geom2d_Ellipse(aAx2d , aMajor , aMinor / 4) aArc2 = Geom2d_TrimmedCurve(anEllipse1.GetHandle() , 3.141592, 0.) aArc1 = Geom2d_TrimmedCurve(anEllipse2.GetHandle() , 3.141592, 0.) anEllipsePnt2 = anEllipse1.Value(0.) anEllipsePnt1 = anEllipse1.Value(3.141592) aSegment = GCE2d_MakeSegment(anEllipsePnt1 , anEllipsePnt2) # Threading : Build Edges and Wires aEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(aArc1.GetHandle() , aCyl1.GetHandle()) aEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment.Value() , aCyl1.GetHandle()) aEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(aArc2.GetHandle() , aCyl2.GetHandle()) aEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment.Value() , aCyl2.GetHandle()) print dir(aEdge1OnSurf1) threadingWire1 = BRepBuilderAPI_MakeWire(aEdge1OnSurf1.Edge() , aEdge2OnSurf1.Edge()) threadingWire2 = BRepBuilderAPI_MakeWire(aEdge1OnSurf2.Edge() , aEdge2OnSurf2.Edge()) BRepLib().BuildCurves3d(threadingWire1.Wire()) BRepLib().BuildCurves3d(threadingWire2.Wire()) # Create Threading aTool = BRepOffsetAPI_ThruSections(True) aTool.AddWire(threadingWire1.Wire()) aTool.AddWire(threadingWire2.Wire()) aTool.CheckCompatibility(False) myThreading = aTool.Shape() # Izdelava sestava aRes = TopoDS_Compound() aBuilder = BRep_Builder() aBuilder.MakeCompound (aRes) aBuilder.Add (aRes, myBody.Shape()) aBuilder.Add (aRes, myThreading) # Izris oblike show_bottle(aPnt1) def draw_bottle(event=None): # Definiranje razdalj: širina, dolžina, višina myWidth = 50.0 myThickness = 30.0 myHeight = 70.0 # Define Points define_points(myWidth, myThickness, myHeight) if __name__ == '__main__': # OCC.Display.SimpleGui.init_display() returns multiple # values which are assigned here display, start_display, add_menu, add_function_to_menu = \ init_display() draw_bottle() #kličemo podprogram za izris bottle start_display()
Izris CAD kocke
## Izdelava kocke from OCC.Display.SimpleGui import * from OCC.BRepPrimAPI import * from OCC.gp import * from OCC.GC import * from OCC.BRepBuilderAPI import * #from OCC.TopoDS import * display, start_display, add_menu, add_function_to_menu = init_display() #Definiranje točk v prostoru aPnt1 = gp_Pnt(0 , 0 , 0) aPnt2 = gp_Pnt(10 , 0, 0) aPnt3 = gp_Pnt(10 , 10 , 0) aPnt4 = gp_Pnt(0, 10 , 0) #Izdelava segmentov--definiranje geometrije aSegment1 = GC_MakeSegment(aPnt1 , aPnt2) aSegment2 = GC_MakeSegment(aPnt2 , aPnt3) aSegment3 = GC_MakeSegment(aPnt3 , aPnt4) aSegment4 = GC_MakeSegment(aPnt4 , aPnt1) #Izdelava robov -- definiranje topologije aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) aEdge2 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) aEdge3 = BRepBuilderAPI_MakeEdge(aSegment3.Value()) aEdge4 = BRepBuilderAPI_MakeEdge(aSegment4.Value()) #Povezovanje robov v mrežo aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,\ aEdge3.Edge(), aEdge4.Edge()) #Telo: Iz profila se izdela telo myFaceProfile = BRepBuilderAPI_MakeFace(aWire.Wire()) aPrismVec = gp_Vec(0 , 0 , 10) myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec).Shape() display.DisplayShape(myBody) start_display()
Izris CAD prizme
## Izdelava prizme --primer bottle from OCC.Display.SimpleGui import * from OCC.BRepPrimAPI import * from OCC.gp import * from OCC.GC import * from OCC.BRepBuilderAPI import * from OCC.TopoDS import * display, start_display, add_menu, add_function_to_menu = init_display() myWidth = 50.0 myThickness = 30.0 myHeight = 70.0 #Definiranje začetnih točk aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0) aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0) aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0) aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0) aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0) #Izdelava segmentov--definiranje geometrije aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4) aSegment1 = GC_MakeSegment(aPnt1 , aPnt2) aSegment2 = GC_MakeSegment(aPnt4 , aPnt5) #Izdelava robov -- definiranje topologije aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) #Povezovanje robov v mrežo aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,\ aEdge3.Edge()) #Izdelava celotnega profila - mirror xAxis = gp_OX() aTrsf = gp_Trsf() aTrsf.SetMirror(xAxis) aBRepTrsf = BRepBuilderAPI_Transform(aWire.Shape() , aTrsf) aMirroredShape = aBRepTrsf.Shape() aMirroredWire = TopoDS_wire(aMirroredShape) mkWire = BRepBuilderAPI_MakeWire() mkWire.Add(aWire.Wire()) mkWire.Add(aMirroredWire) myWireProfile = mkWire.Wire() #Telo: Iz profila se izdela telo myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) aPrismVec = gp_Vec(0 , 0 , myHeight) myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec).Shape() display.DisplayShape(myBody) start_display()
Povzetek -- KT vaj 12.12.2011
Prikaz enostavnega izvoza STEP formata za eno obliko
# Vključimo knjižnico za izvoz STEP formata from OCC.Utils.DataExchange.STEP import STEPExporter from OCC.BRepPrimAPI import * # Pripravimo enostaven CAD primer za izvoz v STEP format my_box_shape = BRepPrimAPI_MakeBox(50,50,50).Shape() # Obliko my_box_shape izvozimo v STEP format my_step_exporter = STEPExporter("result_export_single.stp") my_step_exporter.add_shape(my_box_shape) my_step_exporter.write_file()
Prikaz enostavnega izvoza STEP formata za več oblik
# Vključimo knjižnico za izvoz STEP formata from OCC.Utils.DataExchange.STEP import STEPExporter from OCC.BRepPrimAPI import * # Pripravimo enostavna CAD primera za izvoz v STEP format my_box_shape = BRepPrimAPI_MakeBox(50,50,50).Shape() my_sphere_shape = BRepPrimAPI_MakeSphere(20).Shape() # Obliki my_box_shape in my_sphere_shape izvozimo v STEP format my_step_exporter = STEPExporter("result_export_multi.stp") my_step_exporter.add_shape(my_box_shape) my_step_exporter.add_shape(my_sphere_shape) #funkcijo ADD uporabimo za dodajanje oblik v STEP format my_step_exporter.write_file()
Uporaba funkcije zaokrožitve, pozicioniranje valja na izbrano mesto, združevanje CAD modelov ter izvoz v STEP format
V naslednjem primeru so prikazane naslednje funkcije:
- zaokrožitve
- pozicioniranje elementa
- združevanje CAD modelov
- enostaven izvoz CAD modela v STEP format
##Copyright 2011 Simon Kulovec (simon.kulovec@lecad.si) ##This file is part of pythonOCC. ## Importanje razlicnih knjiznic # Uporabniski vmesnik GUI from OCC.Display.SimpleGui import * # OpenCascade from OCC.gp import * from OCC.TopoDS import * from OCC.GC import * from OCC.BRepBuilderAPI import * from OCC.BRepPrimAPI import * from OCC.BRepFilletAPI import * from OCC.BRepAlgoAPI import * from OCC.Utils.Topology import * from OCC.BRep import * from OCC.Utils.DataExchange.STEP import STEPExporter # OCC.Display.SimpleGui.init_display() returns multiple # values which are assigned here display, start_display, add_menu, add_function_to_menu = \ init_display() # Definiranje spremenljivk myWidth = 50.0 myThickness = 30.0 myHeight = 70.0 # Definiranje zacetnih tock aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0) aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0) aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0) aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0) aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0) # Definiranje geometrije aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4) aSegment1 = GC_MakeSegment(aPnt1 , aPnt2) aSegment2 = GC_MakeSegment(aPnt4 , aPnt5) # Definiranje topologije aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,\ aEdge3.Edge()) # Izdelava celotnega profila - mirror xAxis = gp_OX() aTrsf = gp_Trsf() aTrsf.SetMirror(xAxis) aBRepTrsf = BRepBuilderAPI_Transform(aWire.Shape() , aTrsf) aMirroredShape = aBRepTrsf.Shape() aMirroredWire = TopoDS_wire(aMirroredShape) mkWire = BRepBuilderAPI_MakeWire() mkWire.Add(aWire.Wire()) mkWire.Add(aMirroredWire) myWireProfile = mkWire.Wire() # Telo: Iz profila se izdela telo myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) aPrismVec = gp_Vec(0 , 0 , myHeight) myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec) # Telo: Dodamo zaokrozitve (fillet) mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape()) topology_traverser = Topo(myBody.Shape()) for aEdge in topology_traverser.edges(): mkFillet.Add(myThickness / 12. , aEdge) myBody = mkFillet.Shape() # Dodajanje grla na steklenico (valj) neckLocation = gp_Pnt(0, 0, myHeight) #Določitev lokacije valja neckNormal = gp_DZ() #smer normale, v katero bomo valj izvlekli neckAx2 = gp_Ax2(neckLocation, neckNormal) myNeckRadius = myThickness / 4 #radij valja myNeckHeight = myHeight / 10 # višina valja mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , \ myNeckHeight) myNeck = mkCylinder.Shape(); myBody = BRepAlgoAPI_Fuse(myBody, myNeck) #dodajanje valja k obliki myBody # Izdelava sestava aRes = TopoDS_Compound() #Določitev spremenljivke za sestav aBuilder = BRep_Builder() aBuilder.MakeCompound (aRes) aBuilder.Add (aRes, myBody.Shape()) #Dodajanje različnih oblik v sestav aRes # Export to STEP () my_step_exporter = STEPExporter("export_step_file.stp") #Določevanje imena STEP file.a my_step_exporter.add_shape(aRes) #Dodajanje oblike v STEP file my_step_exporter.write_file() # Izris oblike display.EraseAll() print dir(display) display.DisplayShape(aRes) start_display()
Attachments (11)
-
boolove-operacije.svg (23.4 KB) - added by 12 years ago.
Boolove operacije
-
points-solid.svg (49.9 KB) - added by 12 years ago.
Dodajanje slike za izdelavo solid iz točk
-
3Dprimitives.png (16.0 KB) - added by 12 years ago.
3Dprimitives
-
VisualizationOfGeometryWithUtilisingpythonOCC.pdf (1.3 MB) - added by 12 years ago.
Vizualizacija s PythonOCC
-
modalg.pdf (728.6 KB) - added by 11 years ago.
Modelling algorithms za OpenCASCADE 6.6
-
modata.pdf (573.0 KB) - added by 11 years ago.
Modeling Data
- qtDisplay.py (9.9 KB) - added by 9 years ago.
-
bottle.png (68.3 KB) - added by 9 years ago.
"bottle" primer - slikovni prikaz
- edge_primer.PNG (19.9 KB) - added by 8 years ago.
- prerezana_piramida.PNG (26.8 KB) - added by 8 years ago.
- torus_webgl.PNG (348.8 KB) - added by 8 years ago.