Draw a model from actor

This method should be refined by subclasses as the default implementation is a no-op.

This method is called on many materials for many actor and model at each frame. It is expected to use a GLProgram and call an equivalent to glDrawArrays. However, it should not call glClear nor GamnitDisplay::flip.

Property definitions

gamnit $ Material :: draw
	# Draw a `model` from `actor`
	#
	# This method should be refined by subclasses as the default implementation is a no-op.
	#
	# This method is called on many materials for many `actor` and `model` at each frame.
	# It is expected to use a `GLProgram` and call an equivalent to `glDrawArrays`.
	# However, it should not call `glClear` nor `GamnitDisplay::flip`.
	fun draw(actor: Actor, model: LeafModel, camera: Camera) do end
lib/gamnit/depth/depth_core.nit:164,2--171,64

gamnit $ SmoothMaterial :: draw
	redef fun draw(actor, model, camera)
	do
		var program = app.blinn_phong_program
		program.use
		program.mvp.uniform camera.mvp_matrix

		var mesh = model.mesh

		# Actor specs
		glDisableVertexAttribArray program.translation.location
		glDisableVertexAttribArray program.scale.location

		program.translation.uniform(actor.center.x, actor.center.y, actor.center.z, 0.0)
		program.scale.uniform actor.scale
		program.alpha.uniform actor.alpha
		program.rotation = new Matrix.gamnit_euler_rotation(actor.pitch, actor.yaw, actor.roll)

		# From mesh
		program.coord.array_enabled = true
		program.coord.array(mesh.vertices, 3)

		program.normal.array_enabled = true
		program.normal.array(mesh.normals, 3)

		# No textures
		program.use_map_ambient.uniform false
		program.use_map_diffuse.uniform false
		program.use_map_specular.uniform false
		program.tex_coord.array_enabled = false

		# Camera
		program.camera.uniform(camera.position.x, camera.position.y, camera.position.z)

		# Colors from the material
		program.ambient_color.uniform(ambient_color[0], ambient_color[1],
		                              ambient_color[2], ambient_color[3])
		program.diffuse_color.uniform(diffuse_color[0], diffuse_color[1],
		                              diffuse_color[2], diffuse_color[3])
		program.specular_color.uniform(specular_color[0], specular_color[1],
		                               specular_color[2], specular_color[3])

		setup_lights(camera, program)

		# Execute draw
		if mesh.indices.is_empty then
			glDrawArrays(mesh.draw_mode, 0, mesh.vertices.length/3)
		else
			glDrawElements(mesh.draw_mode, mesh.indices.length, gl_UNSIGNED_SHORT, mesh.indices_c.native_array)
		end

		assert glGetError == gl_NO_ERROR
	end
lib/gamnit/depth/more_materials.nit:50,2--101,4

gamnit $ NormalsMaterial :: draw
	redef fun draw(actor, model, camera)
	do
		var program = app.normals_program
		program.use
		program.mvp.uniform camera.mvp_matrix

		var mesh = model.mesh

		# TODO apply normal map

		program.translation.uniform(actor.center.x, actor.center.y, actor.center.z, 0.0)
		program.scale.uniform actor.scale

		program.tex_coord.array_enabled = true
		program.tex_coord.array(mesh.texture_coords, 2)

		program.coord.array_enabled = true
		program.coord.array(mesh.vertices, 3)

		program.rotation = new Matrix.gamnit_euler_rotation(actor.pitch, actor.yaw, actor.roll)

		program.normal.array_enabled = true
		program.normal.array(mesh.normals, 3)

		if mesh.indices.is_empty then
			glDrawArrays(mesh.draw_mode, 0, mesh.vertices.length/3)
		else
			glDrawElements(mesh.draw_mode, mesh.indices.length, gl_UNSIGNED_SHORT, mesh.indices_c.native_array)
		end
	end
lib/gamnit/depth/more_materials.nit:282,2--311,4

gamnit $ TexturedMaterial :: draw
	redef fun draw(actor, model, camera)
	do
		var mesh = model.mesh

		var program = app.blinn_phong_program
		program.use

		# One of the textures used, if any
		var sample_used_texture = null

		var texture = ambient_texture
		if texture != null then
			glActiveTexture gl_TEXTURE0
			glBindTexture(gl_TEXTURE_2D, texture.gl_texture)
			program.use_map_ambient.uniform true
			program.map_ambient.uniform 0
			sample_used_texture = texture
		else
			program.use_map_ambient.uniform false
		end

		texture = diffuse_texture
		if texture != null then
			glActiveTexture gl_TEXTURE1
			glBindTexture(gl_TEXTURE_2D, texture.gl_texture)
			program.use_map_diffuse.uniform true
			program.map_diffuse.uniform 1
			sample_used_texture = texture
		else
			program.use_map_diffuse.uniform false
		end

		texture = specular_texture
		if texture != null then
			glActiveTexture gl_TEXTURE2
			glBindTexture(gl_TEXTURE_2D, texture.gl_texture)
			program.use_map_specular.uniform true
			program.map_specular.uniform 2
			sample_used_texture = texture
		else
			program.use_map_specular.uniform false
		end

		texture = normals_texture
		if texture != null then
			glActiveTexture gl_TEXTURE3
			glBindTexture(gl_TEXTURE_2D, texture.gl_texture)
			program.use_map_bump.uniform true
			program.map_bump.uniform 3
			sample_used_texture = texture
		else
			program.use_map_bump.uniform false
		end

		glDisableVertexAttribArray program.translation.location
		glDisableVertexAttribArray program.scale.location

		program.mvp.uniform camera.mvp_matrix
		program.translation.uniform(actor.center.x, actor.center.y, actor.center.z, 0.0)
		program.scale.uniform actor.scale
		program.alpha.uniform actor.alpha

		# If using a texture, set `texture_coords`
		program.tex_coord.array_enabled = sample_used_texture != null
		if sample_used_texture != null then
			if sample_used_texture isa RootTexture then
				# Coordinates are directly valid
				program.tex_coord.array(mesh.texture_coords, 2)
			else
				# Correlate texture coordinates from the substexture and the mesh.
				# This is slow, but should be cached on the GPU.
				var xa = sample_used_texture.offset_left
				var xd = sample_used_texture.offset_right - xa
				var ya = sample_used_texture.offset_top
				var yd = sample_used_texture.offset_bottom - ya

				var tex_coords = new Array[Float].with_capacity(mesh.texture_coords.length)
				for i in [0..mesh.texture_coords.length/2[ do
					tex_coords[i*2]   = xa + xd * mesh.texture_coords[i*2]
					tex_coords[i*2+1] = 1.0 - (ya + yd * mesh.texture_coords[i*2+1])
				end

				program.tex_coord.array(tex_coords, 2)
			end
		end

		program.coord.array_enabled = true
		program.coord.array(mesh.vertices, 3)

		program.rotation = new Matrix.gamnit_euler_rotation(actor.pitch, actor.yaw, actor.roll)

		program.ambient_color.uniform(ambient_color[0], ambient_color[1],
		                              ambient_color[2], ambient_color[3])
		program.diffuse_color.uniform(diffuse_color[0], diffuse_color[1],
		                              diffuse_color[2], diffuse_color[3])
		program.specular_color.uniform(specular_color[0], specular_color[1],
		                               specular_color[2], specular_color[3])

		program.normal.array_enabled = true
		program.normal.array(mesh.normals, 3)

		# Light
		setup_lights(camera, program)

		# Camera
		program.camera.uniform(camera.position.x, camera.position.y, camera.position.z)

		if mesh.indices.is_empty then
			glDrawArrays(mesh.draw_mode, 0, mesh.vertices.length/3)
		else
			glDrawElements(mesh.draw_mode, mesh.indices.length, gl_UNSIGNED_SHORT, mesh.indices_c.native_array)
		end
	end
lib/gamnit/depth/more_materials.nit:160,2--272,4