%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2008-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %%%------------------------------------------------------------------- %%% File : wx_opengl_SUITE.erl %%% Author : Dan Gudmundsson <dan.gudmundsson@ericsson.com> %%% Description : Test opengl basics, i.e. functions can be loaded, glu works. %%% Created : 3 Nov 2008 by Dan Gudmundsson <dan.gudmundsson@ericsson.com> %%%------------------------------------------------------------------- -module(wx_opengl_SUITE). -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). -compile(export_all). -include("wx_test_lib.hrl"). -include_lib("wx/include/gl.hrl"). %% Initialization functions. init_per_suite(Config) -> case wx_test_lib:init_per_suite(Config) of Skipped = {skipped, _} -> Skipped; Config2 -> case wx_test_lib:user_available(Config2) of true -> Config2; false -> {skipped, "Ignoring opengl tests: run manually"} end end. end_per_suite(Config) -> wx_test_lib:end_per_suite(Config). init_per_testcase(Func,Config) -> wx_test_lib:init_per_testcase(Func,Config). end_per_testcase(Func,Config) -> wx_test_lib:end_per_testcase(Func,Config). %% SUITE specification suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [canvas, glu_tesselation]. groups() -> []. init_per_group(_GroupName, Config) -> Config. end_per_group(_GroupName, Config) -> Config. %% The test cases -define(VS, {{ 0.5, 0.5, -0.5}, %1 { 0.5, -0.5, -0.5}, %2 {-0.5, -0.5, -0.5}, {-0.5, 0.5, -0.5}, %4 {-0.5, 0.5, 0.5}, { 0.5, 0.5, 0.5}, %6 { 0.5, -0.5, 0.5}, {-0.5, -0.5, 0.5}}).%8 -define(FACES, %% Faces Normal [{{1,2,3,4},{0,0,-1} }, % {{3,8,5,4},{-1,0,0}}, % {{1,6,7,2},{1,0,0} }, % {{6,5,8,7},{0,0,1} }, % {{6,1,4,5},{0,1,0} }, % {{7,8,3,2},{0,-1,0}}]). %% Test we can create a glCanvas and that functions are loaded dynamicly canvas(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); canvas(Config) -> WX = ?mr(wx_ref, wx:new()), Frame = wxFrame:new(WX,1,"Hello 3D-World",[]), Attrs = [{attribList, [?WX_GL_RGBA,?WX_GL_DOUBLEBUFFER,0]}], Canvas = ?mt(wxGLCanvas, wxGLCanvas:new(Frame, Attrs)), ?m(true, wxWindow:show(Frame)), ?m(false, wx:is_null(wxGLCanvas:getContext(Canvas))), ?m({'EXIT', {{error, no_gl_context,_},_}}, gl:getString(?GL_VENDOR)), ?m(ok, wxGLCanvas:setCurrent(Canvas)), io:format("Vendor: ~s~n", [gl:getString(?GL_VENDOR)]), io:format("Renderer: ~s~n", [gl:getString(?GL_RENDERER)]), io:format("Version: ~s~n", [gl:getString(?GL_VERSION)]), {W,H} = ?m({_,_}, wxWindow:getClientSize(Canvas)), gl:viewport(0,0,W,H), gl:matrixMode(?GL_PROJECTION), gl:loadIdentity(), %%gl:frustum( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 ), gl:ortho( -2.0, 2.0, -2.0*H/W, 2.0*H/W, -20.0, 20.0), gl:matrixMode(?GL_MODELVIEW), gl:loadIdentity(), gl:enable(?GL_DEPTH_TEST), gl:depthFunc(?GL_LESS), {R,G,B,_} = wxWindow:getBackgroundColour(Frame), gl:clearColor(R/255,B/255,G/255,1.0), Data = {?FACES,?VS}, drawBox(0, Data), ?m(ok, wxGLCanvas:swapBuffers(Canvas)), ?m([], flush()), Env = wx:get_env(), Tester = self(), spawn_link(fun() -> wx:set_env(Env), ?m(ok, wxGLCanvas:setCurrent(Canvas)), ?m(ok, drawBox(1, Data)), ?m(ok, wxGLCanvas:swapBuffers(Canvas)), Tester ! works, %% This may fail when window is deleted catch draw_loop(2,Data,Canvas) end), ?m_receive(works), ?m([], flush()), io:format("Undef func ~p ~n", [catch gl:uniform1d(2, 0.75)]), timer:sleep(500), ?m([], flush()), wx_test_lib:wx_destroy(Frame, Config). flush() -> flush([]). flush(Collected) -> receive Msg -> flush([Msg|Collected]) after 1 -> lists:reverse(Collected) end. draw_loop(Deg,Data,Canvas) -> timer:sleep(15), drawBox(Deg,Data), ?m(ok, wxGLCanvas:swapBuffers(Canvas)), draw_loop(Deg+1, Data,Canvas). drawBox(Deg,{Fs,Vs}) -> gl:matrixMode(?GL_MODELVIEW), gl:loadIdentity(), gl:rotatef(Deg, 0.0, 1.0, 0.0), gl:rotatef(20, 1.0, 0.0, 1.0), gl:clear(?GL_COLOR_BUFFER_BIT bor ?GL_DEPTH_BUFFER_BIT), gl:'begin'(?GL_QUADS), lists:foreach(fun(Face) -> drawFace(Face,Vs) end, Fs), gl:'end'(). drawFace({{V1,V2,V3,V4},N={N1,N2,N3}}, Cube) -> gl:normal3fv(N), gl:color3f(abs(N1),abs(N2),abs(N3)), gl:texCoord2f(0.0, 1.0), gl:vertex3fv(element(V1, Cube)), gl:texCoord2f(0.0, 0.0), gl:vertex3fv(element(V2, Cube)), gl:texCoord2f(1.0, 0.0), gl:vertex3fv(element(V3, Cube)), gl:texCoord2f(1.0, 1.0), gl:vertex3fv(element(V4, Cube)). glu_tesselation(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); glu_tesselation(Config) -> WX = ?mr(wx_ref, wx:new()), Frame = wxFrame:new(WX,1,"Hello 3D-World",[]), Attrs = [{attribList, [?WX_GL_RGBA,?WX_GL_DOUBLEBUFFER,0]}], Canvas = ?mt(wxGLCanvas, wxGLCanvas:new(Frame, Attrs)), ?m(true, wxWindow:show(Frame)), ?m(ok, wxGLCanvas:setCurrent(Canvas)), {RL1,RB1} = ?m({_,_}, glu:tesselate({0,0,1}, [{-1,0,0},{1,0,0},{0,1,0}])), ?m(3, length(RL1)), ?m(8*3*3, size(RB1)), {RL2,RB2} = ?m({_,_}, glu:tesselate({0,0,1}, [{-1,0,0},{1,0,0},{1,1,0},{-1,1,0}])), ?m(6, length(RL2)), ?m(8*3*4, size(RB2)), {RL3,RB3} = ?m({_,_}, glu:tesselate({0,0,1}, [{-1,0,0},{1,0,0},{1,1,0}, {-1,1,0},{-5,0.5,0}])), ?m(9, length(RL3)), ?m(8*3*5, size(RB3)), wx_test_lib:wx_destroy(Frame, Config).