This is a snippet of code, which I use to generate a rocky asteroid. I am putting it here to show the technique before it gets too complex and obscured.
The key point is to generate a spherical mesh and use the coordinates to seed the randomiser, then to extract a random number and use that to perturb the coordinates and at the same time generate shading for the valleys.
This is ideal for use with recursively generated facets because all the irregular pieces must fit together! Using the spherepoint vertex product to seed the RANDOMIZE function, ensures this happens.
SUB midquad (a AS vector3dv,b AS vector3dv , c AS vector3dv, d AS vector3dv, BYVAL s AS SINGLE , n AS vector3dv)
s=s/3
n.x=(a.x + b.x + c.x + d.x)*s
n.y=(a.y + b.y + c.y + d.y)*s
n.z=(a.z + b.z + c.z + d.z)*s
END SUB
SUB spherepoint(ab AS vector3dv)
LOCAL p AS DOUBLE ' sphere point factor
p=1/SQR(ab.x*ab.x + ab.y*ab.y + ab.z*ab.z)
' raise this vector to the sphere point
ab.x=ab.x*p
ab.y=ab.y*p
ab.z=ab.z*p
END SUB
SUB perturb(m AS SINGLE,v AS vector3dv,c AS vector3dv,r AS vector3dv)
RANDOMIZE v.x*11+v.y*12+v.z*13
c.x=RND: r.x=v.x*(1+c.x*m)
c.y=RND: r.y=v.y*(1+c.y*m)
c.z=RND: r.z=v.z*(1+c.z*m)
END SUB
SUB geomid(a AS vector3dv, b AS vector3dv, ab AS vector3dv)
LOCAL c AS vector3dv
ab.x=(a.x + b.x)*0.5
ab.y=(a.y + b.y)*0.5
ab.z=(a.z + b.z)*0.5
spherepoint ab
perturb 0.05,ab,c,ab
END SUB
SUB chvertex3dv(v AS vector3dv)
LOCAL c,r AS vector3dv
LOCAL cc AS SINGLE
perturb 0.03,v,c,r
cc=(c.x+c.y+c.z)*0.333333
glcolor3f cc,cc,cc ' shading without using normals
glvertex3dv r.x
END SUB
SUB quado(a AS vector3dv, b AS vector3dv , c AS vector3dv, d AS vector3dv, BYVAL r AS LONG)
DECR r ' recursive
IF r<0 THEN
'plot triangle
LOCAL n,m,v,w AS vector3dv
LOCAL nn,g AS SINGLE
midquad a,b,d,c,4,n
midquad a,b,d,c,1,m
g=0.3
'g=0
nn=0.5
glbegin GL_QUADS
glnormal3dv n.x
gltexcoord2f 0+RND*.5, .75-RND*0.2
chvertex3dv a
gltexcoord2f 0+RND*.4, .25+RND*0.1
chvertex3dv b
gltexcoord2f 1-RND*.2, .25+RND*0.15
chvertex3dv d
gltexcoord2f 1-RND*.3, .75-RND*.25
chvertex3dv c
glend
EXIT SUB
END IF
LOCAL ab,bc,bd,ec,ca AS vector3dv
geomid a,b,ab
geomid b,c,bc
geomid b,d,bd
geomid d,c,ec
geomid c,a,ca
quado a,ab,ca,bc,r
quado ab,b,bc,bd,r
quado bc,bd,ec,d,r
quado ca,bc,c,ec,r
END SUB
SUB quadosphere4(BYVAL n AS LONG) ' OCTAHEDRAL BASE
'n=3 ' yields 8*4^n quad facets
'
LOCAL v1,v2,v3,v4,v5,v6 AS vector3dv
'Octahedral coordinates
v1.x=0 :v1.y=1 :v1.z=0
v2.x=-1:v2.y=0 :v2.z=0
v3.x=0 :v3.y=0 :v3.z=1
v4.x=1 :v4.y=0 :v4.z=0
v5.x=0 :v5.y=0 :v5.z=-1
v6.x=0 :v6.y=-1:v6.z=0
' generate recursive diamond facets (paired triangles)
' NB: these diamond facets are not flat (coplanar)
quado v1,v2,v3,v6,n
quado v1,v3,v4,v6,n
quado v1,v4,v5,v6,n
quado v1,v5,v2,v6,n
END SUB
SUB quadosphere6(BYVAL n AS LONG) ' CUBIC BASE
'n=3 ' yields 6*4^n quad facets
'
LOCAL v1,v2,v3,v4,v5,v6,v7,v8 AS vector3dv
LOCAL s AS SINGLE
s=1/SQR(3)
'cube coordinates
v1.x=-s : v1.y= s : v1.z= s
v2.x=-s : v2.y=-s : v2.z= s
v3.x= s : v3.y= s : v3.z= s
v4.x= s : v4.y=-s : v4.z= s
'--------------------------
v5.x= s : v5.y= s : v5.z=-s
v6.x= s : v6.y=-s : v6.z=-s
v7.x=-s : v7.y= s : v7.z=-s
v8.x=-s : v8.y=-s : v8.z=-s
' generate recursive diamond facets (paired triangles)
' NB: these diamond facets are not flat (coplanar)
quado v1,v2,v3,v4,n
quado v3,v4,v5,v6,n
quado v5,v6,v7,v8,n
quado v7,v8,v1,v2,n
quado v1,v3,v7,v5,n
quado v2,v4,v8,v6,n
END SUB
SUB quadosphere10(BYVAL n AS LONG) ' ICOSAHEDRAL BASE
'n=3 ' yields 10*4^n quad facets
'
LOCAL v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12 AS vector3dv
LOCAL a,s,c,p AS SINGLE
a=ATN(2):s=SIN(a):c=COS(a):p=ATN(1)*8/5
'icos vertex coordinates
'--------------------------------------------------
v1.x = 0 : v1.y= 1 : v1.z = 0
v2.x = 0 : v2.y= c : v2.z = s
v3.x = SIN(p )*s : v3.y= c : v3.z = COS(p )*s
v4.x = SIN(p*2)*s : v4.y= c : v4.z = COS(p*2)*s
v5.x = SIN(p*3)*s : v5.y= c : v5.z = COS(p*3)*s
v6.x = SIN(p*4)*s : v6.y= c : v6.z = COS(p*4)*s
'--------------------------------------------------
v7.x = SIN(p*0.5)*s : v7.y = -c : v7.z = COS(p*0.5)*s
v8.x = SIN(p*1.5)*s : v8.y = -c : v8.z = COS(p*1.5)*s
v9.x = SIN(p*2.5)*s : v9.y = -c : v9.z = COS(p*2.5)*s
v10.x= SIN(p*3.5)*s : v10.y= -c : v10.z= COS(p*3.5)*s
v11.x= SIN(p*4.5)*s : v11.y= -c : v11.z= COS(p*4.5)*s
v12.x= 0 : v12.y= -1 : v12.z= 0
'
' generate recursive diamond facets (paired triangles)
' NB: these diamond facets are not flat (coplanar)
quado v1 ,v2 ,v3 ,v7 ,n
quado v1 ,v3 ,v4 ,v8 ,n
quado v1 ,v4 ,v5 ,v9 ,n
quado v1 ,v5 ,v6 ,v10,n
quado v1 ,v6 ,v2 ,v11,n
'----------------------
quado v12,v8 ,v7 ,v3 ,n
quado v12,v9 ,v8 ,v4 ,n
quado v12,v10,v9 ,v5 ,n
quado v12,v11,v10,v6 ,n
quado v12,v7 ,v11,v2 ,n
END SUB
SUB quadosphere(BYVAL n AS LONG)
quadosphere10 n
END SUB
Thanks Charles,
looks interesting.
What does "midquad" ( not included ) do ?
Thanks,
Petr
Oops! Sorry Petr, midquad simply calculates a midface normal. I have put it in at the top of the code.
I am building a library to hold these shapes, to be called geoometrica.inc.
This quadosphere is based on the octagon but the code can be used with cubes, icosahedra and 60 face polyhedra. - Anything that can be arranged in triangle pairs. These will give increasingly improved vertex distribution.
Getting into creations that can be generated by code is really cool stuff Charles. Especially when those creations could be huge amounts of data otherwise to attach.
Thanks for the code examples!
Adding CUBIC and ICOSAHEDRAL to the base geometries:
I've updated the code at the start of the thread, adding a PERTURB function.
SUB quadosphere6(BYVAL n AS LONG) ' CUBIC BASE
'n=3 ' yields 6*4^n quad facets
'
LOCAL v1,v2,v3,v4,v5,v6,v7,v8 AS vector3dv
LOCAL s AS SINGLE
s=1/SQR(3)
'cube coordinates
v1.x=-s : v1.y= s : v1.z= s
v2.x=-s : v2.y=-s : v2.z= s
v3.x= s : v3.y= s : v3.z= s
v4.x= s : v4.y=-s : v4.z= s
'--------------------------
v5.x= s : v5.y= s : v5.z=-s
v6.x= s : v6.y=-s : v6.z=-s
v7.x=-s : v7.y= s : v7.z=-s
v8.x=-s : v8.y=-s : v8.z=-s
' generate recursive diamond facets (paired triangles)
' NB: these diamond facets are not flat (coplanar)
quado v1,v2,v3,v4,n
quado v3,v4,v5,v6,n
quado v5,v6,v7,v8,n
quado v7,v8,v1,v2,n
quado v1,v3,v7,v5,n
quado v2,v4,v8,v6,n
END SUB
SUB quadosphere10(BYVAL n AS LONG) ' ICOSAHEDRAL BASE
'n=3 ' yields 10*4^n quad facets
'
LOCAL v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12 AS vector3dv
LOCAL a,s,c,p AS SINGLE
a=ATN(2):s=SIN(a):c=COS(a):p=ATN(1)*8/5
'icos vertex coordinates
'--------------------------------------------------
v1.x = 0 : v1.y= 1 : v1.z = 0
v2.x = 0 : v2.y= c : v2.z = s
v3.x = SIN(p )*s : v3.y= c : v3.z = COS(p )*s
v4.x = SIN(p*2)*s : v4.y= c : v4.z = COS(p*2)*s
v5.x = SIN(p*3)*s : v5.y= c : v5.z = COS(p*3)*s
v6.x = SIN(p*4)*s : v6.y= c : v6.z = COS(p*4)*s
'--------------------------------------------------
v7.x = SIN(p*0.5)*s : v7.y = -c : v7.z = COS(p*0.5)*s
v8.x = SIN(p*1.5)*s : v8.y = -c : v8.z = COS(p*1.5)*s
v9.x = SIN(p*2.5)*s : v9.y = -c : v9.z = COS(p*2.5)*s
v10.x= SIN(p*3.5)*s : v10.y= -c : v10.z= COS(p*3.5)*s
v11.x= SIN(p*4.5)*s : v11.y= -c : v11.z= COS(p*4.5)*s
v12.x= 0 : v12.y= -1 : v12.z= 0
'
' generate recursive diamond facets (paired triangles)
' NB: these diamond facets are not flat (coplanar)
quado v1 ,v2 ,v3 ,v7 ,n
quado v1 ,v3 ,v4 ,v8 ,n
quado v1 ,v4 ,v5 ,v9 ,n
quado v1 ,v5 ,v6 ,v10,n
quado v1 ,v6 ,v2 ,v11,n
'----------------------
quado v12,v8 ,v7 ,v3 ,n
quado v12,v9 ,v8 ,v4 ,n
quado v12,v10,v9 ,v5 ,n
quado v12,v11,v10,v6 ,n
quado v12,v7 ,v11,v2 ,n
END SUB
SUB quadosphere(BYVAL n AS LONG)
quadosphere10 n
END SUB