Here is some code that show the bug: the bottom image is ok, the top is inverted! The problem is in Sphere:setHeight(). Sorry if the code is messy, but i started from my prog and removed 95% of it: last time i started from scratch to recreate a bug, i couldn’t reproduce it…
--# Main
-- project "sphere" JMV38
displayMode(FULLSCREEN)
function setup()
url2 = "http://www.jmv38.net23.net/images/earthHeight.jpg"
url1 = "http://www.jmv38.net23.net/images/earthDay.jpg"
local sunDir = vec3(-1,0.3,0)
local color0 = color(255, 255, 255, 255)
planet1 = Sphere({
nx = 80, ny = 40 , -- mesh definition
c1 = color0 , c2 = color0 , -- mesh colors
cx=-200, cy=100, cz=-10 , -- sphere center
height=200, width=400, -- flat image size
--r = 100 , -- radius of the sphere
url = url1, -- texture image url
urlHeight = url2, -- height image
heightFactor = 20,
showBug = true,
})
planet2 = Sphere({
nx = 80, ny = 40 , -- mesh definition
c1 = color0 , c2 = color0 , -- mesh colors
cx=-200, cy=-300, cz=-10 , -- sphere center
height=200, width=400, -- flat image size
--r = 100 , -- radius of the sphere
url = url1, -- texture image url
urlHeight = url2, -- height image
heightFactor = 20,
showBug = false,
})
end
function draw()
perspective(45)
camera(0,0,1000, 0,0,0, 0,1,0)
background(14, 14, 14, 255) -- clean background
planet1:draw()
planet2:draw()
end
--# Sphere
Sphere = class()
function Sphere:init(input)
self.showBug = input.showBug
-- spatial position
self.pos = input.pos or vec3(0,0,0)
-- angular position, defined by angles around x,y,z axis
self.angles = input.angles or vec3(0,0,0)
-- spatial position of sphere
self.cx = input.cx or 0
self.cy = input.cy or 0
self.cz = input.cz or 0
-- angular position of sphere, defined by angles around x,y,z axis
self.ax = input.ax or 0
self.ay = input.ay or 0
self.az = input.az or 0
-- size
self.width = input.width
self.height = input.height
-- mesh definition
self.nx = input.nx -- number of triangles in x
self.ny = input.ny -- and in y
self.c1 = input.c1 -- 2 color() objects, to see the triangles
self.c2 = input.c2
self.optimized = input.meshOptimize -- boolean
-- sphere decoration
self.url = input.url -- texture as a url (text)
self.urlHeight = input.urlHeight
self.heightFactor = input.heightFactor or 20
-- create flat mesh and colors
local vertices,colors,tc = {},{},{}
tc,colors = self:simpleMesh({ nx=self.nx, ny=self.ny, c1=self.c1, c2=self.c2 })
-- give a size to the mesh
if self.width and self.height then
vertices = self:flat({tc=tc, width=self.width, height=self.height})
end
-- create the mesh itself
self.tc = tc
self.ms = mesh()
self.ms.vertices = vertices
self.ms.colors = colors
self.ms.texCoords = tc
-- add the texture from internet
if self.url then
self:load( self.url ) -- this will not be instantaneous!
end
-- add height map
if self.urlHeight then
self:loadHeightMap(self.urlHeight)
end
end
function Sphere:flat(args)
local tc, w, h = args.tc, args.width, args.height
local vertices = {}
local i,v,x,y,z
for i,v in ipairs(tc) do
x,y,z = v[1]*w, v[2]*h, 0
vertices[i] = vec3(x,y,z)
end
return vertices
end
function Sphere:simpleMesh(input)
-- create the mesh tables
local vertices = {}
local colors = {}
local texCoords = {}
--local w,h = img.width/10, img.height/10
local k = 0
local s = 1
-- create a rectangular set of triangles
local x,y
local nx,ny = input.nx,input.ny
local opt = input.opt
local sx, sy = 1/nx, 1/ny
local color1 = input.c1
local color2 = input.c2
local center = vec3(1,0.5,0)
for y=0,ny-1 do
for x=0,nx-1 do
vertices[k+1] = vec2( sx*x , sy*y )
vertices[k+2] = vec2( sx*(x+1), sy*y )
vertices[k+3] = vec2( sx*(x+1), sy*(y+1))
vertices[k+4] = vec2( sx*x , sy*y )
vertices[k+5] = vec2( sx*x , sy*(y+1))
vertices[k+6] = vec2( sx*(x+1), sy*(y+1))
colors[k+1] = color1
colors[k+2] = color1
colors[k+3] = color1
colors[k+4] = color2
colors[k+5] = color2
colors[k+6] = color2
k = k + 6
end
end
return vertices,colors
end
function Sphere:setHeight(input)
-- change each vector length according to heightmap
local verts = input.verts
-- local tc = input.tc
local hmap = input.heightmap
local w,h = self.width,self.height
local s = self.radius
local z,x,y,r,g,b,a,vx,vy,vz,cx,cy
local tc = {}
-- this his here i trigger the bug ###################################
if self.showBug then tc = self.ms.texCoords
else tc = self.tc end
for i,v in ipairs(tc) do
cx,cy = v.x , v.y
x,y = math.floor(cx * w) , math.floor(cy * h)
if x<1 then x=1 end
if x>w then x=w end
if y<1 then y=1 end
if y>h then y=h end
r,g,b,a = hmap:get(x,y)
z = g/255*self.heightFactor
verts[i] = vec3(x,y,z)
end
return verts
end
function Sphere:loadHeightMap(url)
http.request(url,
function(theImage, status, head)
self:setHeightMap(theImage, status, head)
end
)
end
function Sphere:setHeightMap(theImage, status, head)
self.ms.vertices = self:setHeight({
verts = self.ms.vertices,
tc = self.ms.texCoords,
heightmap = theImage,
})
end
function Sphere:load(url)
-- map = nil
http.request(url,
function(theImage, status, head)
self:setTexture(theImage, status, head)
end
)
end
function Sphere:setTexture(theImage, status, head)
self.texture = theImage
self.ms.texture = theImage
end
function Sphere:draw()
local s
pushMatrix()
pushStyle()
translate(self.cx,self.cy,self.cz)
self.ms:draw()
popStyle()
popMatrix()
end