diff options
Diffstat (limited to 'test')
86 files changed, 5077 insertions, 0 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..2618698 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,13 @@ +# Compile flags as defined in global CMakeLists +set(CMAKE_CXX_FLAGS "${COLOBOT_CXX_FLAGS} ${MXE_CFLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE ${COLOBOT_CXX_FLAGS_RELEASE}) +set(CMAKE_CXX_FLAGS_DEBUG ${COLOBOT_CXX_FLAGS_DEBUG}) + +# CBot utils +add_subdirectory(cbot) + +# Unit tests +add_subdirectory(unit) + +# Test environments +add_subdirectory(envs) diff --git a/test/cbot/CBot_console/CBotConsole.cpp b/test/cbot/CBot_console/CBotConsole.cpp new file mode 100644 index 0000000..e9209d3 --- /dev/null +++ b/test/cbot/CBot_console/CBotConsole.cpp @@ -0,0 +1,175 @@ +/* + * CBotConsole.cpp + * + * Created on: 08-08-2012 + * Author: michal + */ + +#include "CBotConsole.h" +#include "CClass.h" +#include <ctime> +#include <iostream> + +CBotConsole::CBotConsole() { + // TODO Auto-generated constructor stub + m_pProg = NULL; + m_threadinfo.m_bRun = false; + m_code = 0; + +} + +CBotConsole::~CBotConsole() { + // TODO Auto-generated destructor stub +} + +uint ThreadProc(ThreadInfo *info) +{ + time_t t0,t1; + time(&t0); + + int Cpt = 0; + + info->m_pProg->Start("LaCommande"); + while ( !info->m_bStop && !info->m_pProg->Run() ) + { +#if 0 + const char* FunctionName; + const char* FN; + int start, end; + + info->m_pProg->GetRunPos(FunctionName, start, end); + + if ( FunctionName != NULL ) + { + info->m_pEditx->SetSel(start, end); + + char buffer[200]; + sprintf( buffer, "step %s, %d, %d",FunctionName, start, end); + AfxMessageBox( buffer ); + + int level = 0; + do + { + CBotVar* t = info->m_pProg->GetStackVars(FN, level--); + if ( FN != FunctionName ) break; + if ( t != NULL ) + { + CString s ; + while ( t != NULL ) + { + if (s.IsEmpty()) s+= "Stack -> "; + else s+= " , "; + s += t->GetValString(); + t = t->GetNext(); + } + AfxMessageBox(s); + } + } while (TRUE); + } +#endif + Cpt++; + if ( Cpt%50 == 0 ) std::cout << "."; + } + + if ( info->m_bStop ) + { + std::cout << "\nInterrupt\n"; + } + else if (info->m_pProg->GetError() == 0) + { + time(&t1); + double prog_time = difftime(t0,t1); + + char buffer[200]; + sprintf( buffer, "\nExecution terminated in %f seconds.\nInterrupted %d time(s).\n", + prog_time, Cpt); + + std::cout << buffer; + } + +// info->m_pWndMessage->SendMessage(WM_ENDPROG, 0, 0) ; + return 0 ; +} + +long CBotConsole::EndProg() +{ + m_threadinfo.m_bRun = false; + + if (m_pProg->GetError(m_code, m_start, m_end)) + { + CBotString TextError; + TextError = CBotProgram::GetErrorText(m_code); + std::cout << TextError; + return 1; + } + delete m_pProg; + m_pProg = NULL; + + return 0 ; +} + + +void CBotConsole::OnOK() +{ + m_code = 0; + + std::string Commande; + std::cin >> Commande; + + std::string s = "void LaCommande() { " + Commande + " ;}"; + m_pProg = new CBotProgram(); + CBotStringArray liste; + m_pProg->Compile(s.c_str(), liste); + + int err, start, end; + if ( m_pProg->GetError(err, start, end) ) + { + CBotString TextError; + TextError = CBotProgram::GetErrorText(err); + std::cout << TextError; + return; + } + + std::cout << "\n" + Commande + " ->\n"; + +// m_Edit2.SetWindowText(""); +// m_Edit1.SetFocus(); +// m_Edit2.EnableWindow(FALSE); +// m_cOK.EnableWindow(FALSE); + + // lance un processus paralèle pour l'exécution +// m_threadinfo.m_pWndMessage = this ; + +// m_threadinfo.m_pEdit1 = &m_Edit1; +// m_threadinfo.m_pEditx = m_pEditx; + m_threadinfo.m_pProg = m_pProg; + m_threadinfo.m_bStop = false; + m_threadinfo.m_bRun = true; + + ThreadProc(&m_threadinfo); + +// here program starts +// AfxBeginThread((AFX_THREADPROC)ThreadProc, &m_threadinfo) ; +} + +void CBotConsole::OnCancel() +{ + m_threadinfo.m_bStop = true ; +} + +bool CBotConsole::OnInitDialog() +{ +// CDialog::OnInitDialog(); + + std::cout << "Following functions are availible:\n"; + for ( int i = 0; i < m_pListe->GetSize(); i++ ) + { + CBotString x = (*m_pListe)[i] + CBotString("\n"); + std::cout << x; + } + std::cout << "Enter a command:\n"; + + + return true; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/test/cbot/CBot_console/CBotConsole.h b/test/cbot/CBot_console/CBotConsole.h new file mode 100644 index 0000000..a155399 --- /dev/null +++ b/test/cbot/CBot_console/CBotConsole.h @@ -0,0 +1,44 @@ +/* + * CBotConsole.h + * + * Created on: 08-08-2012 + * Author: michal + */ + +#ifndef CBOTCONSOLE_H_ +#define CBOTCONSOLE_H_ +#include "CClass.h" + +struct ThreadInfo +{ +// CEdit* m_pEdit1 ; +// CEdit* m_pEditx ; + CBotProgram* m_pProg; +// CWnd* m_pWndMessage; + bool m_bStop; + bool m_bRun; +}; + +class CBotConsole { + +public: + CBotConsole(); + virtual ~CBotConsole(); + +// CEdit m_Edit1; + + CBotProgram* m_pProg; + ThreadInfo m_threadinfo; + + CBotStringArray* m_pListe; + int m_code, m_start, m_end; +// CEdit* m_pEditx; + + // Implementation + void OnOK(); + void OnCancel(); + bool OnInitDialog(); + long EndProg() ; +}; + +#endif /* CBOTCONSOLE_H_ */ diff --git a/test/cbot/CBot_console/CBotDoc.cpp b/test/cbot/CBot_console/CBotDoc.cpp new file mode 100644 index 0000000..1c694c9 --- /dev/null +++ b/test/cbot/CBot_console/CBotDoc.cpp @@ -0,0 +1,122 @@ +/* + * CBotDoc.cpp + * + * Created on: 08-08-2012 + * Author: michal + */ +#include "CBotDoc.h" +#include "CBotConsole.h" +#include <iostream> + +CBotDoc::CBotDoc(std::string s) { + // TODO Auto-generated constructor stub + // TODO set m_DocText +// m_pEdit = NULL; + m_pProg = NULL; +// m_bModified = FALSE; + m_DocText = s; + std::cout << s << std::endl; +// std::cout << "Enter to continue..." << std::endl; +// getchar(); +} + +CBotDoc::~CBotDoc() { + +// delete m_pEdit; + delete m_pProg; +} + + +//static bool test = false; + +void CBotDoc::OnRun() +{ + +// m_pEdit->GetWindowText(m_DocText); + CBotString s; + + std::string TextError; + int code, start, end; + + if ( m_pProg == NULL ) m_pProg = new CBotProgram(); + + if (!m_pProg->Compile(m_DocText.c_str(), m_Liste, NULL)) + { + m_pProg->GetError(code, start, end); + delete m_pProg; + m_pProg = NULL; + + TextError = CBotProgram::GetErrorText( code ); + std::cout << TextError << std::endl; + return; + } + + if( m_Liste.GetSize() == 0 ) + { + std::cout << "No function marked \"extern\" !\n"; + return; + } + + for ( int i = 0; i < m_Liste.GetSize(); i++ ) + { + int start, stop; + m_pProg->GetPosition(m_Liste[i], start, stop, GetPosNom, GetPosParam); + CBotString s(m_DocText.substr( start, stop-start ).c_str()); + m_Liste[i] = s; + } +// TODO + CBotConsole dlg; + dlg.m_pListe = &m_Liste; +// dlg.m_pEditx = m_pEdit; + + dlg.OnInitDialog(); + dlg.OnOK(); + dlg.EndProg(); +// if ( dlg.m_code>0 ) +// { +// std::string TextError; +// +// TextError = m_pProg->GetErrorText( dlg.m_code ); +// +// std::cout <<TextError; +// } + + return; +} + +bool CBotDoc::Compile() +{ +// m_pEdit->GetWindowText(m_DocText); + + std::string TextError; + int code, start, end; + + if ( m_pProg == NULL ) m_pProg = new CBotProgram(); + + char buffer[100]; + strcpy(buffer, "a pointer move to see"); + + if (!m_pProg->Compile(m_DocText.c_str(), m_Liste, static_cast<void*>(buffer))) + { + m_pProg->GetError(code, start, end); + delete m_pProg; + m_pProg = NULL; + +// m_pEdit->SetSel( start, end ); +// m_pEdit->SetFocus(); // higlights part of problem + + TextError = CBotProgram::GetErrorText( code ); + std::cout << TextError ; + + return false; + } + +// if ( m_pProg->GetPosition( "TheTest", start, end) ) +// { +// m_pEdit->SetSel( start, end ); +// m_pEdit->SetFocus(); // higlights part of problem +// } + +// m_bModified = FALSE; + return true; +} diff --git a/test/cbot/CBot_console/CBotDoc.h b/test/cbot/CBot_console/CBotDoc.h new file mode 100644 index 0000000..c0a3e1d --- /dev/null +++ b/test/cbot/CBot_console/CBotDoc.h @@ -0,0 +1,39 @@ +/* + * CBotDoc.h + * + * Created on: 08-08-2012 + * Author: michal + */ + +#pragma once +#ifndef CBOTDOC_H_ +#define CBOTDOC_H_ + +#include "CClass.h" +#include <string> + +class CBotDoc { + +public: + CBotDoc(std::string); + virtual ~CBotDoc(); + +// CEdit* m_pEdit; // to memorize the text, and display + CBotProgram* m_pProg; // the compiled program + std::string m_DocText; + CBotStringArray m_Liste; + +// Operations + + bool Compile(); + +// virtual bool OnNewDocument(); + + void OnRun(); + void OnChangeEdit1(); + void OnTest(); + +}; + + +#endif /* CBOTDOC_H_ */ diff --git a/test/cbot/CBot_console/CClass.cpp b/test/cbot/CBot_console/CClass.cpp new file mode 100644 index 0000000..9b7c842 --- /dev/null +++ b/test/cbot/CBot_console/CClass.cpp @@ -0,0 +1,97 @@ +#include "CClass.h" + +#include "routines.cpp" + +void rMajObject( CBotVar* pThis, void* pUser ) +{ + if (!pThis->IsElemOfClass("object")) + return ; + CBotVar* pPos = pThis->GetItem("position"); + CBotVar* pX = pPos->GetItem("x"); + CBotVar* pY = pPos->GetItem("y"); + CBotVar* pZ = pPos->GetItem("z"); +// CBotVar* pPt = pThis->GetItem("transport"); + + CBotString p = pX->GetValString(); + +// pX->SetValFloat( pUser == (void*)1 ? (float)12.5 : (float)44.4 ); + pZ->SetValFloat( (float)0 ); + pY->SetValFloat( (float)-3.33 ); + pX->SetValFloat( pX->GetValFloat() + 10 ) ; + +// pX = pThis->GetItem( "xx" ); +// pX->SetValFloat( (float)22 ); + + // crée une instance sur une classe object +// CBotVar* pAutre = CBotVar::Create("autre", CBotTypClass, "object"); +// pAutre->SetUserPtr( (void*)3 ); +// pPt->SetPointer( pAutre ); +// pPt->SetPointer( NULL ); +// delete pAutre; +}; + +CClass::CClass() +{ + m_pClassPoint= NULL; +} + +bool CClass::InitInstance() +{ +////////////////////////////////////////////// +// défini les mots clefs supplémentaires +// ------------------------------------------- + + CBotProgram::Init(); + +////////////////////////////////////////////// +// défini les fonctions "show()" et "print()" +// ------------------------------------------- + + //CBotProgram::AddFunction("show", rShow, cShow); + CBotProgram::AddFunction("print", rPrint, cPrint); + CBotProgram::AddFunction("println", rPrintLn, cPrint); + + +/////////////////////////////////// +// définie la classe globale CPoint +// -------------------------------- + + m_pClassPoint = new CBotClass("CPoint", NULL); + // ajoute le composant ".x" + m_pClassPoint->AddItem("x", CBotTypFloat); + // ajoute le composant ".y" + m_pClassPoint->AddItem("y", CBotTypFloat); + + // ajoute le constructeur pour cette classe + m_pClassPoint->AddFunction("CPoint", rCPoint, cCPoint); + + m_pClassPointIntr = new CBotClass("point", NULL, true); + // ajoute le composant ".x" + m_pClassPointIntr->AddItem("x", CBotTypFloat); + // ajoute le composant ".y" + m_pClassPointIntr->AddItem("y", CBotTypFloat); + // ajoute le composant ".z" + m_pClassPointIntr->AddItem("z", CBotTypFloat); + + // ajoute le constructeur pour cette classe + m_pClassPointIntr->AddFunction("point", rCPoint, cCPoint); + + // défini la classe "object" + CBotClass* pClassObject = new CBotClass( "object", NULL ) ; + pClassObject->AddItem( "xx", CBotTypFloat ); + pClassObject->AddItem( "position", CBotTypResult( CBotTypIntrinsic, "point" ) ); + pClassObject->AddItem( "transport", CBotTypResult( CBotTypPointer, "object" ) ); + pClassObject->AddUpdateFunc( rMajObject ); + + InitClassFILE(); + + return true; +} + +void CClass::ExitInstance() +{ + delete m_pFuncFile; + + CBotProgram::Free(); + +} diff --git a/test/cbot/CBot_console/CClass.h b/test/cbot/CBot_console/CClass.h new file mode 100644 index 0000000..da2c46c --- /dev/null +++ b/test/cbot/CBot_console/CClass.h @@ -0,0 +1,18 @@ +#pragma once + +#include <CBot/CBot.h> +#include <string> + +extern std::string s; + +class CClass +{ +public: + CClass(); + + CBotClass* m_pClassPoint; + CBotClass* m_pClassPointIntr; + + bool InitInstance(); + void ExitInstance(); +}; diff --git a/test/cbot/CBot_console/CMakeLists.txt b/test/cbot/CBot_console/CMakeLists.txt new file mode 100644 index 0000000..5016a77 --- /dev/null +++ b/test/cbot/CBot_console/CMakeLists.txt @@ -0,0 +1,16 @@ +set(SOURCES +CClass.cpp +main.cpp +CBotDoc.cpp +CBotConsole.cpp +) + +set(LIBS +CBot +) + +include_directories(${colobot_SOURCE_DIR}/src) + +add_executable(CBot_console ${SOURCES}) + +target_link_libraries(CBot_console ${LIBS}) diff --git a/test/cbot/CBot_console/main.cpp b/test/cbot/CBot_console/main.cpp new file mode 100644 index 0000000..a2d3668 --- /dev/null +++ b/test/cbot/CBot_console/main.cpp @@ -0,0 +1,45 @@ +#include "CClass.h" +#include "CBotDoc.h" +#include <iostream> + + +#include <fstream> + +std::string str; + +// routine to update the instance of the class Bot common + +int main(int argc, char* argv[]) +{ + CClass newclass; + CBotDoc *botdoc; + if (argc != 2) + { + std::cout << "Usage: "<<argv[0] << " <filename>" << std::endl; + return 0; + } + + std::ifstream in(argv[1]); + std::cout << argv[1] << std::endl; + if (!in.good()) + { + std::cout << "Oh no, error!" << std::endl; + return 1; + } + + std::string contents((std::istreambuf_iterator<char>(in)), + std::istreambuf_iterator<char>()); + str = contents; + + if(!newclass.InitInstance()) + { + std::cerr << "Initialization not complete!" << std::endl; + return 1; + } + + botdoc = new CBotDoc(str); +// std::cout << "Hello CBot!" << std::endl << s; + botdoc->OnRun(); + delete botdoc; + newclass.ExitInstance(); +} diff --git a/test/cbot/CBot_console/routines.cpp b/test/cbot/CBot_console/routines.cpp new file mode 100644 index 0000000..8b8a1d4 --- /dev/null +++ b/test/cbot/CBot_console/routines.cpp @@ -0,0 +1,141 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +//////////////////////////////////////////////////////////////////// +// routine show() +// utilisable depuis le programme écrit en CBot + + +#include <iostream> +#include <string> +#include "CBot/ClassFILE.cpp" +//std::string s; +/* +// execution +bool rShow( CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser ) +{ + string::string s; + + while ( pVar != NULL ) + { + string::string ss; + + ss.LoadString( TX_TYPENAMES + pVar->GetType() ); + s += ss + " "; + + ss = pVar->GetName(); + if (ss.IsEmpty()) ss = "<sans nom>"; + s += ss + " = "; + + s += pVar->GetValString(); + s += "\n"; + pVar = pVar->GetNext(); + } + + AfxMessageBox(s, MB_OK|MB_ICONINFORMATION); + + return TRUE; // pas d'interruption +} + +CBotTypResult cShow( CBotVar* &pVar, void* pUser) +{ + if ( pVar == NULL ) return CBotTypResult(5028); + return CBotTypResult(0); // tous paramètres acceptés, void en retour +} + +*/ + +//////////////////////////////////////////////////////////////////// +// routine print() +// utilisable depuis le programme écrit en CBot + +// exécution + +bool rPrintLn( CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser ) +{ + std::string s; + while ( pVar != NULL ) + { + if ( !s.empty() ) s += " "; + s += pVar->GetValString(); + pVar = pVar->GetNext(); + } + s += "\n"; + + std::cout << s; + return true; // pas d'interruption +} + +bool rPrint( CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser ) +{ + std::string s; + while ( pVar != NULL ) + { + if ( !s.empty() ) s += " "; + s += pVar->GetValString(); + pVar = pVar->GetNext(); + } + s += " "; + std::cout << s; + return true; // pas d'interruption +} + +CBotTypResult cPrint( CBotVar* &pVar, void* pUser) +{ + return CBotTypResult(0); // tous paramètres acceptés, un entier en retour +} + + +////////////////////////////////////////////////////////////////// +// class CPoint pour essayer + +// exécution +bool rCPoint( CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception ) +{ + if ( pVar == NULL )return true; // constructor with no parameters is ok + + CBotVar* pX = pThis->GetItem("x"); + pX->SetValFloat( pVar->GetValFloat() ); + pVar = pVar->GetNext(); + + CBotVar* pY = pThis->GetItem("y"); + pY->SetValFloat( pVar->GetValFloat() ); + pVar = pVar->GetNext(); + + return true; // pas d'interruption +} + +CBotTypResult cCPoint( CBotVar* pThis, CBotVar* &pVar) +{ + // ok if no parameters! + if ( pVar == NULL ) return CBotTypResult(0); + + // numeric type of parameter please + if ( pVar->GetType() > CBotTypDouble ) return CBotTypResult(5011); + pVar = pVar->GetNext(); + + // there must be a second parameter + if ( pVar == NULL ) return 5028; + // also numeric + if ( pVar->GetType() > CBotTypDouble )return CBotTypResult(5011); + pVar = pVar->GetNext(); + + // and not more than 2 parameters please + if ( pVar != NULL ) return CBotTypResult(5026); + + return CBotTypResult(0); // This function returns void +} + diff --git a/test/cbot/CMakeLists.txt b/test/cbot/CMakeLists.txt new file mode 100644 index 0000000..e864ed5 --- /dev/null +++ b/test/cbot/CMakeLists.txt @@ -0,0 +1,2 @@ +# CBot console interpreter +add_subdirectory(CBot_console) diff --git a/test/cbot/scenarios/B.txt b/test/cbot/scenarios/B.txt new file mode 100644 index 0000000..53715f8 --- /dev/null +++ b/test/cbot/scenarios/B.txt @@ -0,0 +1,18 @@ +
+ float [ ] TEST2 ( int [ ] param )
+ {
+ float [ ] z;
+ for ( int i = 0 ; i < sizeof( param ) ; i++ ) try { z [i] = param [i] / 3; }
+ return z;
+ }
+
+extern public void T()
+{
+ int a [4];
+ for ( int i = 0 ; i < 3 ; i++ ) a[i] = 4*i;
+ a [2] = 22;
+
+ float [] b ;
+ b = TEST2 ( a ) ;
+ show ( a, b );
+}
diff --git a/test/cbot/scenarios/BUG2.txt b/test/cbot/scenarios/BUG2.txt new file mode 100644 index 0000000..44de05a --- /dev/null +++ b/test/cbot/scenarios/BUG2.txt @@ -0,0 +1,107 @@ +object object :: TT ( int n )
+{
+ object XX = radar();
+ if ( n == 0 ) return null;
+
+ while ( null == XX ) XX = radar();
+ return XX;
+}
+
+extern void object::Attack( )
+{
+ show ( TT ( 0 ) ) ;
+ show ( TT ( 1 ) ) ;
+ return;
+
+ int list[];
+ int i;
+ object p;
+ float dist, prox;
+ point dest;
+ boolean advance = true;
+
+ TEST(0); // ne stoppe pas si erreur
+// while ( F () != 0 ) F(1);
+
+ i = 0;
+ list[i++] = WingedGrabber;
+ list[i++] = TrackedGrabber;
+ list[i++] = WheeledGrabber;
+ list[i++] = LeggedGrabber;
+ list[i++] = WingedShooter;
+ list[i++] = TrackedShooter;
+ list[i++] = WheeledShooter;
+ list[i++] = LeggedShooter;
+ list[i++] = WingedOrgaShooter;
+ list[i++] = TrackedOrgaShooter;
+ list[i++] = WheeledOrgaShooter;
+ list[i++] = LeggedOrgaShooter;
+ list[i++] = WingedSniffer;
+ list[i++] = TrackedSniffer;
+ list[i++] = WheeledSniffer;
+ list[i++] = LeggedSniffer;
+ list[i++] = Thumper;
+ list[i++] = PhazerShooter;
+ list[i++] = Recycler;
+ list[i++] = Shielder;
+ list[i++] = Subber;
+ list[i++] = Me;
+ list[i++] = 3333;
+ list[i++] = 3334;
+ list[i++] = 3335;
+ list[i++] = 3336;
+ list[i++] = 3337;
+ list[i++] = 3338;
+ list[i++] = 3339;
+ list[i++] = 3331;
+ list[i++] = 3332;
+ list[i++] = 3330;
+ list[i++] = 1111;
+ list[i++] = 1112;
+
+ F(F(0));
+
+ while ( true )
+ {
+ p = radar(list, 0, 360, 0, 1000);
+ if ( p == null )
+ {
+ F(2);
+ }
+ else
+ {
+ dist = F(p.position, position);
+ if ( dist <= 40 && !advance )
+ {
+ fire(p.position);
+ advance = true;
+ }
+ else
+ {
+//? if ( RetBaseDistance() > 20 )
+ {
+ prox = dist-(5+F()*5);
+ if ( prox < 5 ) prox = 5;
+ dest.x = (position.x-p.position.x)*prox/dist + p.position.x;
+ dest.y = (position.y-p.position.y)*prox/dist + p.position.y;
+ dest.z = (position.z-p.position.z)*prox/dist + p.position.z;
+ goto(dest);
+ advance = false;
+ }
+ }
+ }
+ }
+}
+
+// Calcule la distance jusqu'à la base.
+
+float object::RetBaseDistance()
+{
+ object p;
+ float dist;
+
+ p = radar(4444, 0, 360, 0, 1000);
+ if ( p == null ) return 1000;
+ dist = F(p.position, position);
+ return dist;
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/Deleted.txt b/test/cbot/scenarios/Deleted.txt new file mode 100644 index 0000000..469a624 --- /dev/null +++ b/test/cbot/scenarios/Deleted.txt @@ -0,0 +1,23 @@ +public extern void object :: ESSAI()
+{
+ while(true)
+ {
+ if ( true )
+ {
+ goto(12);
+ break;
+ }
+ }
+ object x = null ;
+
+ while ( x == null ) x = radar();
+
+ show ( x.position ) ;
+
+ TEST(5, x);
+
+ if ( x == null ) show ( "DELETED" );
+
+ show ( x.position ) ;
+
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/MaClass.txt b/test/cbot/scenarios/MaClass.txt new file mode 100644 index 0000000..ac472b4 --- /dev/null +++ b/test/cbot/scenarios/MaClass.txt @@ -0,0 +1,16 @@ +
+class MaClass
+{
+ int a = 1 ;
+ MaClass pointeur ;
+ MaClass next = null ;
+ CPoint autre = new CPoint( 1 , 1 ) ;
+}
+
+extern public void Test ( )
+{
+ MaClass x () ;
+ x.next = new MaClass ( ) ;
+ println ( x ) ;
+}
+
diff --git a/test/cbot/scenarios/Mc2.txt b/test/cbot/scenarios/Mc2.txt new file mode 100644 index 0000000..172c259 --- /dev/null +++ b/test/cbot/scenarios/Mc2.txt @@ -0,0 +1,4 @@ +class MaClass
+{
+ int t = 12;
+}
diff --git a/test/cbot/scenarios/Mon fichier.txt b/test/cbot/scenarios/Mon fichier.txt new file mode 100644 index 0000000..6b35bf8 --- /dev/null +++ b/test/cbot/scenarios/Mon fichier.txt @@ -0,0 +1,2 @@ +Voici encore du texte
+et une seconde ligne
diff --git a/test/cbot/scenarios/Nop.txt b/test/cbot/scenarios/Nop.txt new file mode 100644 index 0000000..6a66f6f --- /dev/null +++ b/test/cbot/scenarios/Nop.txt @@ -0,0 +1,4 @@ +public extern void Nop()
+{
+ while ( true ) {}
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/POS.txt b/test/cbot/scenarios/POS.txt new file mode 100644 index 0000000..688e4fb --- /dev/null +++ b/test/cbot/scenarios/POS.txt @@ -0,0 +1,14 @@ +void object :: T ( )
+{
+ show ( position ) ;
+}
+
+public extern void object :: POS()
+{
+ for ( int i = 0; i < 10 ; i++ )
+ {
+ if ( i == 2 ) TEST ( 12 ) ;
+// show ( position );
+ T ( ) ;
+ }
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/T.txt b/test/cbot/scenarios/T.txt new file mode 100644 index 0000000..50a792b --- /dev/null +++ b/test/cbot/scenarios/T.txt @@ -0,0 +1,4 @@ +public extern int T ( float n )
+{
+ return n * 1.1;
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/TESTALL.txt b/test/cbot/scenarios/TESTALL.txt new file mode 100644 index 0000000..82247a0 --- /dev/null +++ b/test/cbot/scenarios/TESTALL.txt @@ -0,0 +1,161 @@ +int T ( int z )
+{
+ return 45 + z ;
+}
+
+class toto
+{
+ int val = 3 ;
+ int x = 3 * 3 ;
+ void toto( int n )
+ { val = n + 3 ; }
+ int retval ( int param )
+ { int r = val + param + x ;
+ val = param ;
+ return r ; }
+}
+
+public extern void object :: Chose( )
+{
+ int z [ 6 ];
+ for ( int i = 0 ; i < 6 ; ) z [ i++ ] = 3 - i ;
+ show ( z ) ;
+ return;
+
+ // test des tableaux
+ int [ ] a [ 3 ] ;
+// a = null;
+ if ( a == null ) show ( "NULL" );
+
+ a [ 2 / 2 ] [ 2 ]= 5 ;
+ int [ ] b ; b = a [1] ;
+ b [ 0 ] = -4;
+ a [ 4 / 2 ] [ 1 ]= 1 ;
+ show ( a , b ) ;
+ return ;
+ {
+ toto chose = new toto (5 ) ;
+ toto truc = chose ;
+ show ( chose, chose.retval( 100 ) ,
+ truc, truc.retval (40 ) ) ;
+
+ return;
+ }
+ {
+ point A = new
+ point ( 4 * 4 , 2 ) ;
+ show ( A ) ;
+ return;
+ }
+ {
+ show ( T ( 1 ) , T ( 3.7 ) ) ;
+ return;
+ }
+
+ {
+ point A ( 3, 4 ) ,
+ B = A ;
+
+ int n = -4;
+ show ( n );
+
+ show ( A, B ) ;
+
+ boolean a = false;
+ boolean b = a or true;
+ if ( not a and b ) ;
+ return;
+ }
+ {
+ // test try
+ float x = nan ; int z = 0 ;
+ try {
+// throw ( 3 * 4 + 33 ) ;
+ int zz ; goto ( 12 ) ; z = 1 ; z = 0 / 0 ; z = 2 ;
+ }
+ catch ( 45 + 0 * 6000 )
+ {
+ show( "Exception 6000", z ) ;
+ }
+ catch ( x == 0 ) { show( "x nul" ) ; }
+ finally { show ( "fini" ) ; }
+ show ( "continue" );
+ return;
+ }
+ {
+ // test des if
+ int a = 3;
+ if ( a == 3 ) show ( "33");
+ else show ( "44");
+ if ( a != 3 ) show ( "333");
+ else show ( "444");
+ return;
+ }
+ {
+ int a = 0;
+ // test break
+un:
+ while ( true )
+ {
+deux:
+ while ( true )
+ {
+ a++;
+ if ( a == 2 ) continue;
+ if ( a == 3 ) break deux;
+ show ( a ) ;
+ if ( a == 5 ) break un;
+ }
+ show ( "DEUX" );
+ }
+ return;
+ }
+ {
+ // test switch
+ int a = 0;
+
+ switch ( a )
+ {
+ case 1 : show( "un" ) ; break;
+ case 2 : show( "deux" ) ; // break;
+ case 3 : show( "trois" ) ; break;
+ case 4 : show( "quatre" ) ; // break;
+ default : show( "par défaut" ) ;
+ }
+ return;
+ }
+ {
+ // test boucle while
+ float z = 3.3;
+ while ( z > 0 )
+ { show ( z-- ) ; }
+ return;
+ }
+
+ {
+ // test boucle do
+ float y = 3.3;
+ do { int x = 0; show(y); y++; } while ( y < 7 ) ;
+ return;
+ }
+ // test boucle for
+ int j = -7; show ( j );
+ for ( int ii = 3, j = 31; ii < 6 ; ++ii, j = j -3 )
+ {
+ j = 10 * j;
+ show ( ii, j );
+ }
+ return;
+{
+ // déclarations de variables
+ int a; int b = 3; int c = 4*b, d = 1, e;
+ float x; float y = 3.3; float z = y / 2, u = 1, v;
+ boolean t; boolean tt = true or false; boolean ttt = false, tttt = true, t5;
+ string s; string ss = "hello"; string s2 = ss + " plus", s3 = "s3", s4;
+
+ show( b, c, d );
+ show( y, z, u );
+ show( tt, ttt, tttt );
+ show( ss, s2, s3 );
+}
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/TestCB1.txt b/test/cbot/scenarios/TestCB1.txt new file mode 100644 index 0000000..516db47 --- /dev/null +++ b/test/cbot/scenarios/TestCB1.txt @@ -0,0 +1,18 @@ +extern public void toto()
+{
+ print( "hello" ) ;
+ print( fac(5) );
+ print( t() ) ;
+}
+
+public int fac(int n)
+{
+ if ( n<2 ) return 1;
+ return n * fac(n-1);
+}
+
+point t()
+{
+ point a(1,2);
+ return a;
+}
diff --git a/test/cbot/scenarios/TestCBot1.txt b/test/cbot/scenarios/TestCBot1.txt new file mode 100644 index 0000000..d27b4f8 --- /dev/null +++ b/test/cbot/scenarios/TestCBot1.txt @@ -0,0 +1,27 @@ +
+class CPoint2
+{
+ float x, y;
+ void CPoint2(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+}
+
+public extern void T ( )
+{
+ CPoint2 X( 12, 33 ), Y ( -4, 4/3 );
+ print ( X, Y ) ;
+}
+
+public extern void Hello ( )
+
+{
+ println ( "Hello" );
+}
+
+public extern void test ( int n )
+{
+ for ( int i = n; i>0 ; i--) print (i);
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/TestCBot3.txt b/test/cbot/scenarios/TestCBot3.txt new file mode 100644 index 0000000..b915f96 --- /dev/null +++ b/test/cbot/scenarios/TestCBot3.txt @@ -0,0 +1,24 @@ +public extern void Test ()
+{
+ for ( int x = 100000; x>0 ; x-- ) { }
+}
+
+float MaRoutine( CPoint A, CPoint B )
+{
+ A.x -= B.x ; // distance en x
+ A.y -= B.y ; // distance en y
+ A.x *= A.x; // carré de la distance
+ A.y += A.y; // carré de la distance
+ println ( A, B ) ;
+ return ( A.x + A.y ) ;
+}
+
+public extern void TestAB ( )
+{
+ CPoint A(3, 5) ;
+ CPoint B(4, -2);
+ println ( A, B ) ;
+ MaRoutine( A, B ) ;
+ println ( A, B ) ;
+}
+
diff --git a/test/cbot/scenarios/TestNull.txt b/test/cbot/scenarios/TestNull.txt new file mode 100644 index 0000000..f447245 --- /dev/null +++ b/test/cbot/scenarios/TestNull.txt @@ -0,0 +1,15 @@ +extern public void TestNull ()
+{
+ CPoint pointeur = null;
+
+ try {
+ pointeur.x = 4; }
+ catch ( 6007 ) {}
+
+ pointeur = new CPoint(1,2);
+
+ print ( pointeur.x, pointeur.y,
+ pointeur );
+
+ pointeur.x = 5;
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/TestRestoreState.txt b/test/cbot/scenarios/TestRestoreState.txt new file mode 100644 index 0000000..1e49e37 --- /dev/null +++ b/test/cbot/scenarios/TestRestoreState.txt @@ -0,0 +1,67 @@ +// routine de Daniel qui plante après RestoreState
+
+extern void object::Attack( )
+{
+ int list[], i;
+ object p;
+ float dist, prox;
+ point nav1, nav2, dest;
+ boolean advance = true;
+
+ i = 0;
+ list[i++] = WingedGrabber;
+ list[i++] = TrackedGrabber;
+ list[i++] = WheeledGrabber;
+ list[i++] = LeggedGrabber;
+ list[i++] = WingedShooter;
+ list[i++] = TrackedShooter;
+ list[i++] = WheeledShooter;
+ list[i++] = LeggedShooter;
+ list[i++] = WingedOrgaShooter;
+ list[i++] = TrackedOrgaShooter;
+ list[i++] = WheeledOrgaShooter;
+ list[i++] = LeggedOrgaShooter;
+ list[i++] = WingedSniffer;
+ list[i++] = TrackedSniffer;
+ list[i++] = WheeledSniffer;
+ list[i++] = LeggedSniffer;
+ list[i++] = Thumper;
+ list[i++] = PhazerShooter;
+ list[i++] = Recycler;
+ list[i++] = Shielder;
+ list[i++] = Subber;
+ list[i++] = Me;
+
+ nav1.x = 1;//cmdline(0);
+ nav1.y = 1;//cmdline(1);
+ nav2.x = 2;//cmdline(2);
+ nav2.y = 2;//cmdline(3);
+
+ while ( true )
+ {
+ while ( true )
+ {
+ // ennemi à proximité ?
+ p = radar(list, 0, 360, 0, 40);
+ if ( p == null ) break;
+ // lui tire dessus
+ fire(p.position);
+ }
+
+ // se promène vers le point A
+ goto(nav1);
+
+ while ( true )
+ {
+ // ennemi à proximité ?
+ p = radar(list, 0, 360, 0, 40);
+ if ( p == null ) break;
+ // lui tire dessus
+ fire(p.position);
+ }
+
+ // se promène vers le point B
+ goto(nav2);
+ }
+}
+
diff --git a/test/cbot/scenarios/TestStatic.txt b/test/cbot/scenarios/TestStatic.txt new file mode 100644 index 0000000..f501aa5 --- /dev/null +++ b/test/cbot/scenarios/TestStatic.txt @@ -0,0 +1,31 @@ +class ESSAI
+{
+ int x = 0;
+ static int nb = 3;
+ static int [ ] array ;
+
+ void Put( int val)
+ {
+show(nb);
+ array[ nb ] = val;
+// this.nb++;
+ this.nb = this.nb + 1;
+show(nb, array);
+ }
+ int Get( )
+ {
+ nb--;
+show("out", nb, array);
+ return array[ nb ] ;
+ }
+}
+
+extern public void T()
+{
+ ESSAI t1 ( ) ;
+ ESSAI t2 ( ) ;
+ t1.nb++;
+ t1.Put( 11 ); t1.Put( 12 ); t2.Put( 13 );
+
+ show ( t1.Get(), t2.Get(), t2.Get() ) ;
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/TestStr.txt b/test/cbot/scenarios/TestStr.txt new file mode 100644 index 0000000..683ec1b --- /dev/null +++ b/test/cbot/scenarios/TestStr.txt @@ -0,0 +1,17 @@ +extern public void TSTR()
+{
+ string s = "C'est un essai";
+
+ print ( s, strlen(s), strleft(s, 3), strright(s,3), strmid(s, 2), strmid(s,2,3), strfind(s, "un"), strfind(s, "sdgfld") );
+
+ show ( strupper(s), strlower(s) );
+
+ s = "123.45" ;
+ print ( strval(s) );
+
+
+ string sub = strright("abcdef", 2); // sub vaut "ef###", # étant un caractère bizarre quelconque
+ show (sub);
+ int pos = strfind("abcdef", "xy"); // pos vaut -1. Pourquoi pas nan ?
+ show(pos);
+}
diff --git a/test/cbot/scenarios/Z.txt b/test/cbot/scenarios/Z.txt new file mode 100644 index 0000000..714119b --- /dev/null +++ b/test/cbot/scenarios/Z.txt @@ -0,0 +1,14 @@ +public extern void tp()
+{
+ int a [4], b[];
+ a [ 0 ] = 8 ;
+
+ b = T ( a ) ;
+ show ( a, b );
+}
+
+int[] T ( int[] Z )
+{
+ for ( int i = 0; i < 4 ; i++ ) Z[ i ] = i * i ;
+ return Z;
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/a.txt b/test/cbot/scenarios/a.txt new file mode 100644 index 0000000..6107342 --- /dev/null +++ b/test/cbot/scenarios/a.txt @@ -0,0 +1,312 @@ +object radarGuepe(point orig, float dist)
+{
+ int i;
+ object pr, r;
+ float mindist;
+
+ i = 0;
+ mindist = 1000;
+ while (i<30)
+ {
+ pr = radar(i);
+ if (pr != null)
+ {
+
+ if (F(orig, pr.position) < mindist and pr.category == AlienWasp and pr.altitude > 3)
+ {
+ mindist = distance(orig, pr.position);
+ r = pr;
+ }
+ }
+ i = i+1;
+ }
+ if (mindist < dist) return(r); else return(null);
+}
+
+
+class Guepe
+{
+
+ point pos;
+
+
+ void cherche(point orig, float dist)
+ {
+ object p;
+ point o;
+
+ p = radarGuepe(orig, dist);
+ while (p == null)
+ {
+ wait(0.1);
+ p = radarGuepe(orig, dist);
+ }
+
+ pos.x = p.position.x;
+ pos.y = p.position.y;
+ pos.z = p.position.z;
+
+ //o = p.position;
+ //wait(0.1);
+
+ //vitessex = (p.position.x - o.x)/0.1;
+ //vitessey = (p.position.y - o.y)/0.1;
+ //vitessez = (p.position.z - o.z)/0.1;
+
+ }
+
+
+ void tire(point orig, float orient)
+ {
+ //float t = 3; //temps d'anticipation
+ float angle;
+ point cible;
+
+ cible.x = pos.x;// + t*vitessex;
+ cible.y = pos.y;// + t*vitessey;
+ cible.z = pos.z;// + t*vitessez;
+
+ if (cible.x == 0) angle = 90; else
+ angle = atan(cible.y / cible.x);
+ if (cible.x < 0) angle = angle + 180;
+ angle = angle - orient;
+ if (angle > 180) angle = angle - 360;
+ if (angle < -180) angle = angle + 360;
+ turn(angle);
+
+ angle = atan((cible.z-orig.z) / distance2d(orig, cible));
+ aim(angle);
+
+ fire(0.1);
+
+ }
+}
+
+extern void object::Fourmi6()
+{
+ //fps(1000);
+ Guepe guepe = new Guepe();
+
+ while (true)
+ {
+ guepe.cherche(position, 50);
+
+ guepe.tire(position, orientation);
+ }
+}
+object radarGuepe(point orig, float dist) +{ + int i; + object pr, r; + float mindist; + + i = 0; + mindist = 1000; + while (i<30) + { + pr = radar(i); + if (pr != null) + { + + if (F(orig, pr.position) < mindist and pr.category == AlienWasp and pr.altitude > 3) + { + mindist = distance(orig, pr.position); + r = pr; + } + } + i = i+1; + } + if (mindist < dist) return(r); else return(null); +} + + +class Guepe +{ + + point pos; + + + void cherche(point orig, float dist) + { + object p; + point o; + + p = radarGuepe(orig, dist); + while (p == null) + { + wait(0.1); + p = radarGuepe(orig, dist); + } + + pos.x = p.position.x; + pos.y = p.position.y; + pos.z = p.position.z; + + //o = p.position; + //wait(0.1); + + //vitessex = (p.position.x - o.x)/0.1; + //vitessey = (p.position.y - o.y)/0.1; + //vitessez = (p.position.z - o.z)/0.1; + + } + + + void tire(point orig, float orient) + { + //float t = 3; //temps d'anticipation + float angle; + point cible; + + cible.x = pos.x;// + t*vitessex; + cible.y = pos.y;// + t*vitessey; + cible.z = pos.z;// + t*vitessez; + + if (cible.x == 0) angle = 90; else + angle = atan(cible.y / cible.x); + if (cible.x < 0) angle = angle + 180; + angle = angle - orient; + if (angle > 180) angle = angle - 360; + if (angle < -180) angle = angle + 360; + turn(angle); + + angle = atan((cible.z-orig.z) / distance2d(orig, cible)); + aim(angle); + + fire(0.1); + + } +} + +extern void object::Fourmi6() +{ + //fps(1000); + Guepe guepe = new Guepe(); + + while (true) + { + guepe.cherche(position, 50); + + guepe.tire(position, orientation); + } +} +object radarGuepe(point orig, float dist) +{ + int i; + object pr, r; + float mindist; + + i = 0; + mindist = 1000; + while (i<30) + { + pr = radar(i); + if (pr != null) + { + + if (F(orig, pr.position) < mindist and pr.category == AlienWasp and pr.altitude > 3) + { + mindist = distance(orig, pr.position); + r = pr; + } + } + i = i+1; + } + if (mindist < dist) return(r); else return(null); +} + + +class Guepe +{ + + point pos; + + + void cherche(point orig, float dist) + { + object p; + point o; + + p = radarGuepe(orig, dist); + while (p == null) + { + wait(0.1); + p = radarGuepe(orig, dist); + } + + pos.x = p.position.x; + pos.y = p.position.y; + pos.z = p.position.z; + + //o = p.position; + //wait(0.1); + + //vitessex = (p.position.x - o.x)/0.1; + //vitessey = (p.position.y - o.y)/0.1; + //vitessez = (p.position.z - o.z)/0.1; + + } + + + void tire(point orig, float orient) + { + //float t = 3; //temps d'anticipation + float angle; + point cible; + + cible.x = pos.x;// + t*vitessex; + cible.y = pos.y;// + t*vitessey; + cible.z = pos.z;// + t*vitessez; + + if (cible.x == 0) angle = 90; else + angle = atan(cible.y / cible.x); + if (cible.x < 0) angle = angle + 180; + angle = angle - orient; + if (angle > 180) angle = angle - 360; + if (angle < -180) angle = angle + 360; + turn(angle); + + angle = atan((cible.z-orig.z) / distance2d(orig, cible)); + aim(angle); + + fire(0.1); + + } +} + +extern void object::Fourmi6() +{ + //fps(1000); + Guepe guepe = new Guepe(); + + while (true) + { + guepe.cherche(position, 50); + + guepe.tire(position, orientation); + } +} +
+public extern void TestTableau ()
+{
+ int tableau [ 12 ] ;
+
+ point array[ 12 ] [ 14 ] ;
+
+ point zéro ( 1, 2 ) ;
+ point a = zéro ;
+
+ for ( int i = 0 ; i < 10 ; i++ ) array[ i ] [ i ]= zéro ;
+
+ array[ 5 ] [3 ] . x =1.5 ;
+
+ array[ 2 ] [ 2 ] . y = array[ 5 ] [ 5 ] . x ;
+
+ array[ 4 ] = array [ 2 ] ;
+
+ for ( int i = 0 ; i < 10 ; i++ ) for ( int j = 0 ; j < 4 ; j++ ) println ( i, j, array [ i ] [ j ] ) ;
+
+ show( zéro, a, array );
+
+}
+
diff --git a/test/cbot/scenarios/bug.txt b/test/cbot/scenarios/bug.txt new file mode 100644 index 0000000..4ec6eb3 --- /dev/null +++ b/test/cbot/scenarios/bug.txt @@ -0,0 +1,12 @@ +public extern void object::Bug()
+{
+ point a;
+ a = position;
+ TEST();
+ float d=dist(a, position);
+}
+
+float dist(point a, point b)
+{
+ return a.x-b.x;
+}
diff --git a/test/cbot/scenarios/bugmw.txt b/test/cbot/scenarios/bugmw.txt new file mode 100644 index 0000000..284ee43 --- /dev/null +++ b/test/cbot/scenarios/bugmw.txt @@ -0,0 +1,9 @@ +extern public void main()
+{
+ show(fact(30)) ;
+}
+
+public int fact(int n)
+{
+ return (fact(n-1)*n) ;
+}
diff --git a/test/cbot/scenarios/ccc.txt b/test/cbot/scenarios/ccc.txt new file mode 100644 index 0000000..dbcd1d5 --- /dev/null +++ b/test/cbot/scenarios/ccc.txt @@ -0,0 +1,8 @@ +public extern void ccc()
+{
+ int a;
+ a = 0 ;
+
+ if ( a == 0 );
+
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/enum.txt b/test/cbot/scenarios/enum.txt new file mode 100644 index 0000000..a592a7f --- /dev/null +++ b/test/cbot/scenarios/enum.txt @@ -0,0 +1,9 @@ +
+enum JourDeLaSemaine {
+ lundi = 1,
+ mardi,
+ mercredi,
+ jeudi,
+ vendredi,
+ samedi,
+ dimanche = 0 }
\ No newline at end of file diff --git a/test/cbot/scenarios/fibo.txt b/test/cbot/scenarios/fibo.txt new file mode 100644 index 0000000..88f5357 --- /dev/null +++ b/test/cbot/scenarios/fibo.txt @@ -0,0 +1,25 @@ +
+extern public int Fibo( int n, boolean b )
+{
+ if ( n < 2 ) return n;
+ int a = Fibo(n-1, b) + Fibo(n-2, false);
+ if ( b ) print (n + "=" + a);
+ return a;
+}
+
+extern public void t()
+{
+ Fibo( 23, true);
+}
+
+extern public void tt()
+{
+ t();
+}
+
+// cette routine n'est évidemment pas du tout obtimisée
+// c'est même un très mauvais exemple de programmation récursive
+
+// pour un test de durée, Fibo(23, true) prend
+// en mode Debug 67 secondes
+// en mode Release 8 secondes
diff --git a/test/cbot/scenarios/file.txt b/test/cbot/scenarios/file.txt new file mode 100644 index 0000000..2a22dd9 --- /dev/null +++ b/test/cbot/scenarios/file.txt @@ -0,0 +1,70 @@ +class CLASS22
+{
+ static int nb = 2;
+ void T22 ( ) { nb = nb / 0 ; }
+}
+
+public extern void object :: TEST()
+{
+ switch ( 1 )
+ {
+ case 1:
+ {
+ file h();
+ h.open("Mon Fichier.txt", "r");
+show ( h.filename, h.handle );
+h.filename = "xx";
+h.handle = 1 ;
+ h.readln();
+ h.close();
+ }
+ case 2:
+ {
+ file h("Mon Fichier.txt");
+ h.open("r");
+ h.readln();
+ h.close();
+ }
+ case 3:
+ {
+ file h("Mon Fichier.txt", "r");
+ h.readln();
+ h.close();
+ }
+ case 4:
+ {
+ file h();
+ h.filename = "Mon Fichier.txt";
+ h.open("r");
+ h.readln();
+ h.close();
+ }
+ case 5:
+ {
+ file h = fileopen( "Mon 2Fichier.txt", "r" );
+ h.readln();
+ h.close();
+ }
+ }
+{
+ file h( ) ;
+ h.filename = "Test.h";
+ h.open ( "r" );
+
+
+ file pf ( "Mon Fichier.txt" ) ;
+ pf . open ( "w" ) ;
+ pf . writeln ( "Voici encore du texte" ) ;
+ pf . writeln ( "et une seconde ligne" ) ;
+ pf . close( );
+
+ pf . open ( "r" ) ;
+
+ while ( not pf . eof( ) )
+ {
+ string s = pf . readln ( );
+ show ( s );
+ }
+ pf.close( );
+}
+}
diff --git a/test/cbot/scenarios/h.txt b/test/cbot/scenarios/h.txt new file mode 100644 index 0000000..c395319 --- /dev/null +++ b/test/cbot/scenarios/h.txt @@ -0,0 +1,5 @@ +void tf()
+{
+ file h;
+ h.handle += 1 ;
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/include.txt b/test/cbot/scenarios/include.txt new file mode 100644 index 0000000..e8f8cc9 --- /dev/null +++ b/test/cbot/scenarios/include.txt @@ -0,0 +1,27 @@ +class Z
+{
+ static int x = 0;
+ private int y;
+
+ void T( )
+ {
+ // autorisé ici
+ y = x ;
+ this.y = this.x ;
+ x = y ;
+ this.x = this.y ;
+ }
+}
+
+extern public void test()
+{
+ Z a();
+ 3 * a.x; // autorisé
+//vu 3 * a.y; // interdit
+//vu a.y = 3; // interdit ici
+ a.x = 1; // autorisé
+
+ show ( a );
+ a.T();
+ show ( a );
+}
diff --git a/test/cbot/scenarios/intrinsic.txt b/test/cbot/scenarios/intrinsic.txt new file mode 100644 index 0000000..f215791 --- /dev/null +++ b/test/cbot/scenarios/intrinsic.txt @@ -0,0 +1,16 @@ +public extern void TestIntrinsic()
+{
+ point a ( 1, 2 );
+ print (a);
+
+ a.x = 3;
+ a.y = 4;
+
+ point b = a;
+
+ println ( b.x, b.y, b ) ;
+ if ( b == a ) b.y = 0;
+ println (a,b);
+ if ( b != a ) b.y = a.y;
+ println(a,b);
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/methode1.txt b/test/cbot/scenarios/methode1.txt new file mode 100644 index 0000000..080bba2 --- /dev/null +++ b/test/cbot/scenarios/methode1.txt @@ -0,0 +1,57 @@ +class t {
+ point p;
+}
+
+void object :: toto()
+{
+ show ( Position ) ;
+}
+
+extern public void object :: XX()
+{
+ int test [];
+ test [ 9999 ] = 3;
+
+ toto () ;
+/*
+ Radar();
+
+ object test ;
+ test = this. Radar();
+
+ do {
+ test = this.Radar();
+ } while ( test == null );
+
+/*
+ t test [ 4 ];
+ for ( int i = 0 ; i < 4 ; i++ ) test [ i ] = new t();
+ test [ 3 ] .p.x = 2;
+ show ( test );
+/*
+ int a = nan;
+ show ( a ) ;
+
+ a = TypeMarkPath;
+ show ( a, a++, --a ) ;
+
+ if ( a != nan ) a += 1 ;
+
+ a = TypeMarkPath;
+ float q = a ;
+ show ( a, q ) ;
+
+return;
+
+ a += ++a;
+ show ( a ) ;
+
+ boolean i = false;
+
+ if ( i == true ) {}
+
+ object p;
+ if ( p == null) { p = p ; }
+*/
+}
+
diff --git a/test/cbot/scenarios/methode2.txt b/test/cbot/scenarios/methode2.txt new file mode 100644 index 0000000..76ce7f4 --- /dev/null +++ b/test/cbot/scenarios/methode2.txt @@ -0,0 +1,50 @@ +
+extern void Toto()
+{
+ TEST(12);
+
+ for ( int i = 0 ; i<1000; i++)
+ {
+ int j = 1;
+ if (i==55) TEST(12);
+ }
+
+ TEST(2);
+
+
+// Nouveau();
+ int toto[4];
+ point Z[3];
+
+ Z[1].x = 11; Z[1].y = 12;
+
+ toto[2] = 12;
+ toto[1] = nan;
+
+// point test, autre(2,3) ;
+// object titi = Radar();
+
+ TEST ( 1 ) ;
+
+ toto[0] = 11;
+
+ TEST ( 2 ) ;
+
+ toto[6] = 0;
+}
+
+extern void object::Nouveau()
+{
+ point a;
+ a = np(Position);
+}
+
+point np(point b)
+{
+ point c;
+ c.x = b.y;
+ c.y = b.x;
+ return c ;
+}
+
+
diff --git a/test/cbot/scenarios/mp1.txt b/test/cbot/scenarios/mp1.txt new file mode 100644 index 0000000..599cfc4 --- /dev/null +++ b/test/cbot/scenarios/mp1.txt @@ -0,0 +1,25 @@ +class Guepet
+{
+
+ float a;
+ float b;
+
+ void init()
+ {
+ a = 12.34;
+ b = 56.78;
+ }
+
+
+}
+
+extern void object::Fourmi6()
+{
+ Guepet guepe =new Guepet();
+
+ guepe.init();
+
+
+ show("test "+guepe.a+" "+guepe.b);
+
+}
diff --git a/test/cbot/scenarios/mp2.txt b/test/cbot/scenarios/mp2.txt new file mode 100644 index 0000000..1c2972c --- /dev/null +++ b/test/cbot/scenarios/mp2.txt @@ -0,0 +1,28 @@ +class Guepet
+{
+
+ float a;
+ float b;
+
+ void init()
+ {
+ a = 12.34;
+ b = 56.78;
+
+ object x = radar(123);
+ show("radar "+x.position.x);
+ show("C'est fait");
+ }
+
+
+}
+
+extern void object::Fourmi6()
+{
+ Guepet guepe=new Guepet();
+
+ guepe.init();
+
+ show("test "+guepe.a+" "+guepe.b);
+
+}
diff --git a/test/cbot/scenarios/mw.txt b/test/cbot/scenarios/mw.txt new file mode 100644 index 0000000..c237670 --- /dev/null +++ b/test/cbot/scenarios/mw.txt @@ -0,0 +1,16 @@ +extern public void main()
+{
+// goto( 3, 4 );
+
+ while( true )
+ {
+ try { goto (12) ; }
+ catch( FF( ) )
+ { show( "ko"); }
+ }
+}
+
+boolean FF()
+{
+ return false;
+}
diff --git a/test/cbot/scenarios/null.txt b/test/cbot/scenarios/null.txt new file mode 100644 index 0000000..ae76b74 --- /dev/null +++ b/test/cbot/scenarios/null.txt @@ -0,0 +1,5 @@ +extern public void xxx ()
+{
+ CPoint test = null ;
+ if ( test == null ) show ( "NULL" );
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/opnew.txt b/test/cbot/scenarios/opnew.txt new file mode 100644 index 0000000..7d6838c --- /dev/null +++ b/test/cbot/scenarios/opnew.txt @@ -0,0 +1,20 @@ +extern public void xx ()
+{
+ CPoint pointeur, test = null ;
+ pointeur = new CPoint ( 3, 4 );
+
+ if ( test == null ) show ( "NULL" );
+
+ CPoint pp = pointeur;
+
+show( pointeur , pp );
+
+ pp.x = 33.3;
+ if ( pointeur.x != pp.x ) 0/0;
+
+ pp = new CPoint();
+// pointeur = pp;
+
+show( pointeur , pp );
+
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/plante.txt b/test/cbot/scenarios/plante.txt new file mode 100644 index 0000000..363461b --- /dev/null +++ b/test/cbot/scenarios/plante.txt @@ -0,0 +1,25 @@ +class Guepet
+{
+
+ point pos;
+ float t = 0.1;
+
+ void init()
+ {
+ pos.x = 12.123;
+ pos.y = 34.345;
+
+ F(t);
+ }
+
+
+}
+
+extern void object::Fourmi6()
+{
+ Guepet guepe=new Guepet();
+
+ guepe.init();
+
+ show ( guepe );
+}
diff --git a/test/cbot/scenarios/pointer.txt b/test/cbot/scenarios/pointer.txt new file mode 100644 index 0000000..2d4d907 --- /dev/null +++ b/test/cbot/scenarios/pointer.txt @@ -0,0 +1,41 @@ +extern public void x ()
+{
+ show ( 3 ** 4 );
+ float z = 1e-3;
+ show ( z );
+
+ CPoint b ( 4,5 );
+ show ( b );
+
+ CPoint a ( ) ;
+ a.x = 21; a.y = 12;
+ show ( a ) ;
+
+ CPoint test = new CPoint ( 1,1 );
+ test = new CPoint ( 2, 2 );
+ show ( test );
+}
+
+// crée un objet et retourne son pointeur
+CPoint newcpoint()
+{
+ CPoint p = new CPoint ( 3, 3 );
+ return p;
+}
+
+extern public void y ()
+{
+ CPoint test = newcpoint();
+ println ( test );
+ dontmodif( test );
+ println ( test );
+}
+
+// ne doit pas modifier l'objet en paramètre
+void dontmodif ( CPoint pp )
+{
+ pp.x = 5;
+ pp.y = 2;
+ println ( pp, pp.x, pp.y );
+}
+
diff --git a/test/cbot/scenarios/postinc.txt b/test/cbot/scenarios/postinc.txt new file mode 100644 index 0000000..cdf6ab5 --- /dev/null +++ b/test/cbot/scenarios/postinc.txt @@ -0,0 +1,7 @@ +extern public void X()
+{
+ point A [ ] ;
+ A[5] = new point (2,3);
+ int val = A[5].x++ + --A[5].y;
+ show ( A, val );
+}
diff --git a/test/cbot/scenarios/radar.txt b/test/cbot/scenarios/radar.txt new file mode 100644 index 0000000..09d84a2 --- /dev/null +++ b/test/cbot/scenarios/radar.txt @@ -0,0 +1,39 @@ +extern void object::Bug( )
+{
+ try{ int a = 44 ; a = 12 / 0 ; }
+ catch(6000) { int b = 4 ; }
+ finally { int z = 1 ; }
+
+// tp ( A, B );
+
+/* int a = 4, b = 2, c = nan;
+ float x, y = 3/2, z = nan;
+ boolean i, j = false, k = true;
+
+ string s, ss = "xyz";
+
+ while ( false )
+ {
+ object left, right;
+
+ left = Radar(TypeMarkPath, -45, 120, 100);
+ right = Radar(TypeMarkPath, 45, 120, 100);
+
+ if ( left == null && right == null )
+ {
+ }
+ }
+ int t = fact ( 4 ) ;*/
+}
+
+void tp( point a , point b )
+{
+ a.x += b.x;
+}
+
+
+int fact( int n )
+{
+ if ( n < 2 ) return n;
+ return n * fact ( n - 1 ) ;
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/solution.txt b/test/cbot/scenarios/solution.txt new file mode 100644 index 0000000..f78cf12 --- /dev/null +++ b/test/cbot/scenarios/solution.txt @@ -0,0 +1,13 @@ +extern void object::Solution( )
+{
+show ( "Solution " + Position );
+ Carré(15);
+ Carré(25);
+}
+
+void object::Carré(float côté)
+{
+show ( "Carré " + Position );
+ Move(côté);
+ Turn(-90);
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/test.txt b/test/cbot/scenarios/test.txt new file mode 100644 index 0000000..0693994 --- /dev/null +++ b/test/cbot/scenarios/test.txt @@ -0,0 +1,8 @@ +extern public void x()
+{
+ float a= 1, b = 2;
+ a = b * ( 2 + 2 );
+ print (a);
+ a += 4;
+ print (a);
+}
diff --git a/test/cbot/scenarios/test23.txt b/test/cbot/scenarios/test23.txt new file mode 100644 index 0000000..d6e1ddd --- /dev/null +++ b/test/cbot/scenarios/test23.txt @@ -0,0 +1,10 @@ +extern public void object::TEST23()
+{
+ CLASS22 T;
+ T.T22( ) ;
+
+ show( position );
+ show( this.position );
+
+// T22();
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/testmw.txt b/test/cbot/scenarios/testmw.txt new file mode 100644 index 0000000..6570f6d --- /dev/null +++ b/test/cbot/scenarios/testmw.txt @@ -0,0 +1,14 @@ +extern public int testmw( int a)
+{
+ boolean b = true ;
+
+ if (b)
+ return 1 ;
+ else
+ return a ; 0 * testmw(a-1) ;
+}
+
+public int Fibo2 ( int n )
+{
+ print ( " bof " );
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/this.txt b/test/cbot/scenarios/this.txt new file mode 100644 index 0000000..b8a9e04 --- /dev/null +++ b/test/cbot/scenarios/this.txt @@ -0,0 +1,13 @@ +extern void object :: TEST22 ( )
+{
+ show( position );
+ show( this.position );
+
+ T();
+}
+
+public void object :: T22()
+{
+ show( position );
+ show( this.position );
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/tt.txt b/test/cbot/scenarios/tt.txt new file mode 100644 index 0000000..cd13c9d --- /dev/null +++ b/test/cbot/scenarios/tt.txt @@ -0,0 +1,12 @@ +extern public void T() { T1(); }
+
+public void T1()
+{
+ show( "T1" );
+ T2();
+}
+
+public void T2()
+{
+ show( "T2" );
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/tt2.txt b/test/cbot/scenarios/tt2.txt new file mode 100644 index 0000000..ad9dc1d --- /dev/null +++ b/test/cbot/scenarios/tt2.txt @@ -0,0 +1,5 @@ +extern public void TT()
+{
+ T1();
+ T2();
+}
\ No newline at end of file diff --git a/test/cbot/scenarios/vide.txt b/test/cbot/scenarios/vide.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/cbot/scenarios/vide.txt diff --git a/test/cbot/scenarios/zz.txt b/test/cbot/scenarios/zz.txt new file mode 100644 index 0000000..da764ac --- /dev/null +++ b/test/cbot/scenarios/zz.txt @@ -0,0 +1,6 @@ +extern public void zz()
+{
+ MaClass TOTO ();
+
+ show (TOTO);
+}
\ No newline at end of file diff --git a/test/envs/CMakeLists.txt b/test/envs/CMakeLists.txt new file mode 100644 index 0000000..374c39f --- /dev/null +++ b/test/envs/CMakeLists.txt @@ -0,0 +1,2 @@ +# OpenGL tests +add_subdirectory(opengl) diff --git a/test/envs/opengl/CMakeLists.txt b/test/envs/opengl/CMakeLists.txt new file mode 100644 index 0000000..588a864 --- /dev/null +++ b/test/envs/opengl/CMakeLists.txt @@ -0,0 +1,63 @@ +set(SRC_DIR ${colobot_SOURCE_DIR}/src) + +configure_file(${SRC_DIR}/common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h) + + +set(TEXTURE_SOURCES +${SRC_DIR}/graphics/opengl/gldevice.cpp +${SRC_DIR}/common/logger.cpp +${SRC_DIR}/common/image.cpp +texture_test.cpp +) + +set(MODEL_SOURCES +${SRC_DIR}/graphics/opengl/gldevice.cpp +${SRC_DIR}/graphics/engine/modelfile.cpp +${SRC_DIR}/common/logger.cpp +${SRC_DIR}/common/image.cpp +${SRC_DIR}/common/iman.cpp +${SRC_DIR}/common/stringutils.cpp +${SRC_DIR}/app/system.cpp +model_test.cpp +) + +set(TRANSFORM_SOURCES +${SRC_DIR}/graphics/opengl/gldevice.cpp +${SRC_DIR}/common/logger.cpp +${SRC_DIR}/common/image.cpp +${SRC_DIR}/common/iman.cpp +${SRC_DIR}/app/system.cpp +transform_test.cpp +) + +set(LIGHT_SOURCES +${SRC_DIR}/graphics/opengl/gldevice.cpp +${SRC_DIR}/common/logger.cpp +${SRC_DIR}/common/image.cpp +${SRC_DIR}/common/iman.cpp +${SRC_DIR}/app/system.cpp +light_test.cpp +) + +include_directories(${SRC_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +set(LIBS +${SDL_LIBRARY} +${SDLIMAGE_LIBRARY} +${OPENGL_LIBRARY} +${GLEW_LIBRARY} +${PNG_LIBRARIES} +${ADD_LIBS} +) + +add_executable(texture_test ${TEXTURE_SOURCES}) +target_link_libraries(texture_test ${LIBS}) + +add_executable(model_test ${MODEL_SOURCES}) +target_link_libraries(model_test ${LIBS}) + +add_executable(transform_test ${TRANSFORM_SOURCES}) +target_link_libraries(transform_test ${LIBS}) + +add_executable(light_test ${LIGHT_SOURCES}) +target_link_libraries(light_test ${LIBS}) diff --git a/test/envs/opengl/README.txt b/test/envs/opengl/README.txt new file mode 100644 index 0000000..c618415 --- /dev/null +++ b/test/envs/opengl/README.txt @@ -0,0 +1,9 @@ +Test programs for OpenGL engine: + - texture_test -> multitexturing test with 2 textures (included as files: ./tex1.png, ./tex2.png) + - model_test -> simple model viewer to test model loading + usage: ./model_test {dxf|mod} model_file + second argument is the loaded format (DXF or Colobot .mod files) + requires ./tex folder (or symlink) with Colobot textures + viewer is controlled from keyboard - the bindings can be found in code + - transform_test -> simple "walk around" test for world & view transformations + - light test -> test for lighting diff --git a/test/envs/opengl/light_test.cpp b/test/envs/opengl/light_test.cpp new file mode 100644 index 0000000..b19ba4b --- /dev/null +++ b/test/envs/opengl/light_test.cpp @@ -0,0 +1,462 @@ +#include "app/system.h" +#include "common/logger.h" +#include "common/image.h" +#include "common/iman.h" +#include "graphics/opengl/gldevice.h" +#include "math/geometry.h" + +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <unistd.h> + +#include <iostream> +#include <map> + +enum KeySlots +{ + K_Forward, + K_Back, + K_Left, + K_Right, + K_Up, + K_Down, + K_Count +}; +bool KEYMAP[K_Count] = { false }; + +Math::Point MOUSE_POS_BASE; + +Math::Vector TRANSLATION(0.0f, 2.0f, 0.0f); +Math::Vector ROTATION, ROTATION_BASE; + +float CUBE_ORBIT = 0.0f; + +const int FRAME_DELAY = 5000; + +SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL; + +void Init(Gfx::CGLDevice *device) +{ + device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true); + device->SetShadeModel(Gfx::SHADE_SMOOTH); +} + +void Render(Gfx::CGLDevice *device) +{ + device->BeginScene(); + + /* Unlit part of scene */ + + device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); // Double-sided drawing + + Math::Matrix persp; + Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 50.0f); + device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp); + + + Math::Matrix viewMat; + Math::Matrix mat; + + viewMat.LoadIdentity(); + + Math::LoadRotationXMatrix(mat, -ROTATION.x); + viewMat = Math::MultiplyMatrices(viewMat, mat); + + Math::LoadRotationYMatrix(mat, -ROTATION.y); + viewMat = Math::MultiplyMatrices(viewMat, mat); + + Math::LoadTranslationMatrix(mat, -TRANSLATION); + viewMat = Math::MultiplyMatrices(viewMat, mat); + + device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat); + + Math::Matrix worldMat; + worldMat.LoadIdentity(); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + Gfx::VertexCol line[2] = { Gfx::VertexCol() }; + + for (int x = -40; x <= 40; ++x) + { + line[0].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f); + line[0].coord.z = -40; + line[0].coord.x = x; + line[1].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f); + line[1].coord.z = 40; + line[1].coord.x = x; + device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2); + } + + for (int z = -40; z <= 40; ++z) + { + line[0].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f); + line[0].coord.z = z; + line[0].coord.x = -40; + line[1].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f); + line[1].coord.z = z; + line[1].coord.x = 40; + device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2); + } + + + Gfx::VertexCol quad[6] = { Gfx::VertexCol() }; + + quad[0].coord = Math::Vector(-1.0f, -1.0f, 0.0f); + quad[1].coord = Math::Vector( 1.0f, -1.0f, 0.0f); + quad[2].coord = Math::Vector(-1.0f, 1.0f, 0.0f); + quad[3].coord = Math::Vector( 1.0f, 1.0f, 0.0f); + + for (int i = 0; i < 6; ++i) + quad[i].color = Gfx::Color(1.0f, 1.0f, 0.0f); + + Math::LoadTranslationMatrix(worldMat, Math::Vector(40.0f, 2.0f, 40.0f)); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + + for (int i = 0; i < 6; ++i) + quad[i].color = Gfx::Color(0.0f, 1.0f, 1.0f); + + Math::LoadTranslationMatrix(worldMat, Math::Vector(-40.0f, 2.0f, -40.0f)); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + int planes = device->ComputeSphereVisibility(Math::Vector(0.0f, 0.0f, 0.0f), 1.0f); + printf("Planes:"); + if (planes == 0) + printf(" (none)"); + + if (planes & Gfx::FRUSTUM_PLANE_LEFT) + printf(" LEFT"); + + if (planes & Gfx::FRUSTUM_PLANE_RIGHT) + printf(" RIGHT"); + + if (planes & Gfx::FRUSTUM_PLANE_BOTTOM) + printf(" BOTTOM"); + + if (planes & Gfx::FRUSTUM_PLANE_TOP) + printf(" TOP"); + + if (planes & Gfx::FRUSTUM_PLANE_FRONT) + printf(" FRONT"); + + if (planes & Gfx::FRUSTUM_PLANE_BACK) + printf(" BACK"); + + printf("\n"); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + + for (int i = 0; i < 6; ++i) + quad[i].color = Gfx::Color(1.0f, 0.0f, 1.0f); + + Math::LoadTranslationMatrix(worldMat, Math::Vector(10.0f, 4.5f, 5.0f)); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + + /* Moving lit cube */ + device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); + device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); // Culling (CCW faces) + + device->SetGlobalAmbient(Gfx::Color(0.4f, 0.4f, 0.4f)); + + Gfx::Light light1; + light1.type = Gfx::LIGHT_POINT; + light1.position = Math::Vector(10.0f, 4.5f, 5.0f); + light1.ambient = Gfx::Color(0.2f, 0.2f, 0.2f); + light1.diffuse = Gfx::Color(1.0f, 0.1f, 0.1f); + light1.specular = Gfx::Color(0.0f, 0.0f, 0.0f); + device->SetLight(0, light1); + device->SetLightEnabled(0, true); + + /*Gfx::Light light2; + device->SetLight(1, light2); + device->SetLightEnabled(1, true);*/ + + Gfx::Material material; + material.ambient = Gfx::Color(0.3f, 0.3f, 0.3f); + material.diffuse = Gfx::Color(0.8f, 0.7f, 0.6f); + material.specular = Gfx::Color(0.0f, 0.0f, 0.0f); + device->SetMaterial(material); + + const Gfx::Vertex cube[6][4] = + { + { + // Front + Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)), + Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)), + Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)), + Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)) + }, + + { + // Back + Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)), + Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)), + Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)), + Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)) + }, + + { + // Top + Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)), + Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)), + Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)), + Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)) + }, + + { + // Bottom + Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)), + Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)), + Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)), + Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)) + }, + + { + // Left + Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)) + }, + + { + // Right + Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)), + Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)), + Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)), + Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)) + } + }; + + Math::Matrix cubeTrans; + Math::LoadTranslationMatrix(cubeTrans, Math::Vector(10.0f, 2.0f, 5.0f)); + Math::Matrix cubeRot; + Math::LoadRotationMatrix(cubeRot, Math::Vector(0.0f, 1.0f, 0.0f), CUBE_ORBIT); + Math::Matrix cubeRotInv; + Math::LoadRotationMatrix(cubeRotInv, Math::Vector(0.0f, 1.0f, 0.0f), -CUBE_ORBIT); + Math::Matrix cubeTransRad; + Math::LoadTranslationMatrix(cubeTransRad, Math::Vector(0.0f, 0.0f, 6.0f)); + worldMat = Math::MultiplyMatrices(cubeTransRad, cubeRotInv); + worldMat = Math::MultiplyMatrices(cubeRot, worldMat); + worldMat = Math::MultiplyMatrices(cubeTrans, worldMat); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + for (int i = 0; i < 6; ++i) + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, cube[i], 4); + + device->EndScene(); +} + +void Update() +{ + const float TRANS_SPEED = 6.0f; // units / sec + + GetCurrentTimeStamp(CURR_TIME); + float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC); + CopyTimeStamp(PREV_TIME, CURR_TIME); + + CUBE_ORBIT += timeDiff * (Math::PI / 4.0f); + + Math::Vector incTrans; + + if (KEYMAP[K_Forward]) + incTrans.z = +TRANS_SPEED * timeDiff; + if (KEYMAP[K_Back]) + incTrans.z = -TRANS_SPEED * timeDiff; + if (KEYMAP[K_Right]) + incTrans.x = +TRANS_SPEED * timeDiff; + if (KEYMAP[K_Left]) + incTrans.x = -TRANS_SPEED * timeDiff; + if (KEYMAP[K_Up]) + incTrans.y = +TRANS_SPEED * timeDiff; + if (KEYMAP[K_Down]) + incTrans.y = -TRANS_SPEED * timeDiff; + + Math::Point rotTrans = Math::RotatePoint(-ROTATION.y, Math::Point(incTrans.x, incTrans.z)); + incTrans.x = rotTrans.x; + incTrans.z = rotTrans.y; + TRANSLATION += incTrans; +} + +void KeyboardDown(SDLKey key) +{ + switch (key) + { + case SDLK_w: + KEYMAP[K_Forward] = true; + break; + case SDLK_s: + KEYMAP[K_Back] = true; + break; + case SDLK_d: + KEYMAP[K_Right] = true; + break; + case SDLK_a: + KEYMAP[K_Left] = true; + break; + case SDLK_z: + KEYMAP[K_Down] = true; + break; + case SDLK_x: + KEYMAP[K_Up] = true; + break; + default: + break; + } +} + +void KeyboardUp(SDLKey key) +{ + switch (key) + { + case SDLK_w: + KEYMAP[K_Forward] = false; + break; + case SDLK_s: + KEYMAP[K_Back] = false; + break; + case SDLK_d: + KEYMAP[K_Right] = false; + break; + case SDLK_a: + KEYMAP[K_Left] = false; + break; + case SDLK_z: + KEYMAP[K_Down] = false; + break; + case SDLK_x: + KEYMAP[K_Up] = false; + break; + default: + break; + } +} + +void MouseMove(int x, int y) +{ + Math::Point currentPos(static_cast<float>(x), static_cast<float>(y)); + + static bool first = true; + if (first || (x < 10) || (y < 10) || (x > 790) || (y > 590)) + { + SDL_WarpMouse(400, 300); + MOUSE_POS_BASE.x = 400; + MOUSE_POS_BASE.y = 300; + ROTATION_BASE = ROTATION; + first = false; + return; + } + + ROTATION.y = ROTATION_BASE.y + (static_cast<float> (x - MOUSE_POS_BASE.x) / 800.0f) * Math::PI; + ROTATION.x = ROTATION_BASE.x + (static_cast<float> (y - MOUSE_POS_BASE.y) / 600.0f) * Math::PI; +} + +int main(int argc, char *argv[]) +{ + CLogger logger; + + PREV_TIME = CreateTimeStamp(); + CURR_TIME = CreateTimeStamp(); + + GetCurrentTimeStamp(PREV_TIME); + GetCurrentTimeStamp(CURR_TIME); + + CInstanceManager iMan; + + // Without any error checking, for simplicity + + SDL_Init(SDL_INIT_VIDEO); + + IMG_Init(IMG_INIT_PNG); + + const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); + + Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE; + + if (videoInfo->hw_available) + videoFlags |= SDL_HWSURFACE; + else + videoFlags |= SDL_SWSURFACE; + + if (videoInfo->blit_hw) + videoFlags |= SDL_HWACCEL; + + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags); + + + SDL_WM_SetCaption("Light Test", "Light Test"); + + //SDL_WM_GrabInput(SDL_GRAB_ON); + SDL_ShowCursor(SDL_DISABLE); + + Gfx::CGLDevice *device = new Gfx::CGLDevice(Gfx::GLDeviceConfig()); + device->Create(); + + Init(device); + + bool done = false; + while (! done) + { + Render(device); + Update(); + + SDL_GL_SwapBuffers(); + + SDL_Event event; + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + done = true; + } + else if (event.type == SDL_KEYDOWN) + { + if (event.key.keysym.sym == SDLK_q) + { + done = true; + break; + } + else + KeyboardDown(event.key.keysym.sym); + } + else if (event.type == SDL_KEYUP) + KeyboardUp(event.key.keysym.sym); + else if (event.type == SDL_MOUSEMOTION) + MouseMove(event.motion.x, event.motion.y); + } + + usleep(FRAME_DELAY); + } + + //SDL_WM_GrabInput(SDL_GRAB_OFF); + SDL_ShowCursor(SDL_ENABLE); + + device->Destroy(); + delete device; + + SDL_FreeSurface(surface); + + IMG_Quit(); + + SDL_Quit(); + + DestroyTimeStamp(PREV_TIME); + DestroyTimeStamp(CURR_TIME); + + return 0; +} diff --git a/test/envs/opengl/model_test.cpp b/test/envs/opengl/model_test.cpp new file mode 100644 index 0000000..a06a178 --- /dev/null +++ b/test/envs/opengl/model_test.cpp @@ -0,0 +1,377 @@ +#include "app/system.h" +#include "common/logger.h" +#include "common/image.h" +#include "graphics/engine/modelfile.h" +#include "graphics/opengl/gldevice.h" +#include "math/geometry.h" + +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <unistd.h> + +#include <iostream> +#include <map> + +enum KeySlots +{ + K_RotXUp, + K_RotXDown, + K_RotYLeft, + K_RotYRight, + K_Forward, + K_Back, + K_Left, + K_Right, + K_Up, + K_Down, + K_Count +}; +bool KEYMAP[K_Count] = { false }; + +Math::Vector TRANSLATION(0.0f, 0.0f, 30.0f); +Math::Vector ROTATION; + +const int FRAME_DELAY = 5000; + +std::map<std::string, Gfx::Texture> TEXS; + +SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL; + +Gfx::Texture GetTexture(const std::string &name) +{ + std::map<std::string, Gfx::Texture>::iterator it = TEXS.find(name); + if (it == TEXS.end()) + return Gfx::Texture(); + + return (*it).second; +} + +void LoadTexture(Gfx::CGLDevice *device, const std::string &name) +{ + if (name.empty()) + return; + + Gfx::Texture tex = GetTexture(name); + + if (tex.Valid()) + return; + + CImage img; + if (! img.Load(std::string("tex/") + name)) + { + std::string err = img.GetError(); + GetLogger()->Error("Texture not loaded, error: %s!\n", err.c_str()); + } + else + { + Gfx::TextureCreateParams texCreateParams; + texCreateParams.mipmap = true; + texCreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR; + texCreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR; + + tex = device->CreateTexture(&img, texCreateParams); + } + + TEXS[name] = tex; +} + +void Init(Gfx::CGLDevice *device, Gfx::CModelFile *model) +{ + const std::vector<Gfx::ModelTriangle> &triangles = model->GetTriangles(); + + for (int i = 0; i < static_cast<int>( triangles.size() ); ++i) + { + LoadTexture(device, triangles[i].tex1Name); + LoadTexture(device, triangles[i].tex2Name); + } + + device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); + device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true); + device->SetShadeModel(Gfx::SHADE_SMOOTH); + + Gfx::Light light; + light.type = Gfx::LIGHT_DIRECTIONAL; + light.ambient = Gfx::Color(0.4f, 0.4f, 0.4f, 0.0f); + light.diffuse = Gfx::Color(0.8f, 0.8f, 0.8f, 0.0f); + light.specular = Gfx::Color(0.2f, 0.2f, 0.2f, 0.0f); + light.position = Math::Vector(0.0f, 0.0f, -1.0f); + light.direction = Math::Vector(0.0f, 0.0f, 1.0f); + + device->SetGlobalAmbient(Gfx::Color(0.5f, 0.5f, 0.5f, 0.0f)); + device->SetLight(0, light); + device->SetLightEnabled(0, true); +} + +void Render(Gfx::CGLDevice *device, Gfx::CModelFile *modelFile) +{ + device->BeginScene(); + + Math::Matrix persp; + Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f); + device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp); + + Math::Matrix id; + id.LoadIdentity(); + device->SetTransform(Gfx::TRANSFORM_WORLD, id); + + Math::Matrix viewMat; + Math::LoadTranslationMatrix(viewMat, TRANSLATION); + Math::Matrix rot; + Math::LoadRotationXZYMatrix(rot, ROTATION); + viewMat = Math::MultiplyMatrices(viewMat, rot); + device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat); + + const std::vector<Gfx::ModelTriangle> &triangles = modelFile->GetTriangles(); + + Gfx::VertexTex2 tri[3]; + + for (int i = 0; i < static_cast<int>( triangles.size() ); ++i) + { + device->SetTexture(0, GetTexture(triangles[i].tex1Name)); + device->SetTexture(1, GetTexture(triangles[i].tex2Name)); + device->SetTextureEnabled(0, true); + device->SetTextureEnabled(1, true); + + device->SetMaterial(triangles[i].material); + + tri[0] = triangles[i].p1; + tri[1] = triangles[i].p2; + tri[2] = triangles[i].p3; + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, tri, 3); + } + + device->EndScene(); +} + +void Update() +{ + const float ROT_SPEED = 80.0f * Math::DEG_TO_RAD; // rad / sec + const float TRANS_SPEED = 3.0f; // units / sec + + GetCurrentTimeStamp(CURR_TIME); + float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC); + CopyTimeStamp(PREV_TIME, CURR_TIME); + + if (KEYMAP[K_RotYLeft]) + ROTATION.y -= ROT_SPEED * timeDiff; + if (KEYMAP[K_RotYRight]) + ROTATION.y += ROT_SPEED * timeDiff; + if (KEYMAP[K_RotXDown]) + ROTATION.x -= ROT_SPEED * timeDiff; + if (KEYMAP[K_RotXUp]) + ROTATION.x += ROT_SPEED * timeDiff; + + if (KEYMAP[K_Forward]) + TRANSLATION.z -= TRANS_SPEED * timeDiff; + if (KEYMAP[K_Back]) + TRANSLATION.z += TRANS_SPEED * timeDiff; + if (KEYMAP[K_Left]) + TRANSLATION.x += TRANS_SPEED * timeDiff; + if (KEYMAP[K_Right]) + TRANSLATION.x -= TRANS_SPEED * timeDiff; + if (KEYMAP[K_Up]) + TRANSLATION.y += TRANS_SPEED * timeDiff; + if (KEYMAP[K_Down]) + TRANSLATION.y -= TRANS_SPEED * timeDiff; +} + +void KeyboardDown(SDLKey key) +{ + switch (key) + { + case SDLK_LEFT: + KEYMAP[K_RotYLeft] = true; + break; + case SDLK_RIGHT: + KEYMAP[K_RotYRight] = true; + break; + case SDLK_UP: + KEYMAP[K_RotXUp] = true; + break; + case SDLK_DOWN: + KEYMAP[K_RotXDown] = true; + break; + case SDLK_w: + KEYMAP[K_Forward] = true; + break; + case SDLK_s: + KEYMAP[K_Back] = true; + break; + case SDLK_a: + KEYMAP[K_Left] = true; + break; + case SDLK_d: + KEYMAP[K_Right] = true; + break; + case SDLK_z: + KEYMAP[K_Down] = true; + break; + case SDLK_x: + KEYMAP[K_Up] = true; + break; + default: + break; + } +} + +void KeyboardUp(SDLKey key) +{ + switch (key) + { + case SDLK_LEFT: + KEYMAP[K_RotYLeft] = false; + break; + case SDLK_RIGHT: + KEYMAP[K_RotYRight] = false; + break; + case SDLK_UP: + KEYMAP[K_RotXUp] = false; + break; + case SDLK_DOWN: + KEYMAP[K_RotXDown] = false; + break; + case SDLK_w: + KEYMAP[K_Forward] = false; + break; + case SDLK_s: + KEYMAP[K_Back] = false; + break; + case SDLK_a: + KEYMAP[K_Left] = false; + break; + case SDLK_d: + KEYMAP[K_Right] = false; + break; + case SDLK_z: + KEYMAP[K_Down] = false; + break; + case SDLK_x: + KEYMAP[K_Up] = false; + break; + default: + break; + } +} + +int main(int argc, char *argv[]) +{ + CLogger logger; + + PREV_TIME = CreateTimeStamp(); + CURR_TIME = CreateTimeStamp(); + + GetCurrentTimeStamp(PREV_TIME); + GetCurrentTimeStamp(CURR_TIME); + + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << "{old|new_txt|new_bin} model_file" << std::endl; + return 1; + } + + Gfx::CModelFile *modelFile = new Gfx::CModelFile(); + if (std::string(argv[1]) == "old") + { + if (! modelFile->ReadModel(argv[2])) + { + std::cerr << "Error reading model file" << std::endl; + return 1; + } + } + else if (std::string(argv[1]) == "new_txt") + { + if (! modelFile->ReadTextModel(argv[2])) + { + std::cerr << "Error reading model file" << std::endl; + return 1; + } + } + else if (std::string(argv[1]) == "new_bin") + { + if (! modelFile->ReadBinaryModel(argv[2])) + { + std::cerr << "Error reading model file" << std::endl; + return 1; + } + } + else + { + std::cerr << "Usage: " << argv[0] << "{old|new_txt|new_bin} model_file" << std::endl; + return 1; + } + + // Without any error checking, for simplicity + + SDL_Init(SDL_INIT_VIDEO); + + IMG_Init(IMG_INIT_PNG); + + const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); + + Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE; + + if (videoInfo->hw_available) + videoFlags |= SDL_HWSURFACE; + else + videoFlags |= SDL_SWSURFACE; + + if (videoInfo->blit_hw) + videoFlags |= SDL_HWACCEL; + + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags); + + + SDL_WM_SetCaption("Model Test", "Model Test"); + + Gfx::CGLDevice *device = new Gfx::CGLDevice(Gfx::GLDeviceConfig()); + device->Create(); + + Init(device, modelFile); + + bool done = false; + while (! done) + { + Render(device, modelFile); + Update(); + + SDL_GL_SwapBuffers(); + + SDL_Event event; + SDL_PollEvent(&event); + if (event.type == SDL_QUIT) + done = true; + else if (event.type == SDL_KEYDOWN) + KeyboardDown(event.key.keysym.sym); + else if (event.type == SDL_KEYUP) + KeyboardUp(event.key.keysym.sym); + + usleep(FRAME_DELAY); + } + + delete modelFile; + + device->Destroy(); + delete device; + + SDL_FreeSurface(surface); + + IMG_Quit(); + + SDL_Quit(); + + DestroyTimeStamp(PREV_TIME); + DestroyTimeStamp(CURR_TIME); + + return 0; +} diff --git a/test/envs/opengl/tex1.png b/test/envs/opengl/tex1.png Binary files differnew file mode 100644 index 0000000..46c68a0 --- /dev/null +++ b/test/envs/opengl/tex1.png diff --git a/test/envs/opengl/tex2.png b/test/envs/opengl/tex2.png Binary files differnew file mode 100644 index 0000000..ebdae0d --- /dev/null +++ b/test/envs/opengl/tex2.png diff --git a/test/envs/opengl/texture_test.cpp b/test/envs/opengl/texture_test.cpp new file mode 100644 index 0000000..de9caf3 --- /dev/null +++ b/test/envs/opengl/texture_test.cpp @@ -0,0 +1,192 @@ +#include "common/logger.h" +#include "common/image.h" +#include "graphics/opengl/gldevice.h" +#include "math/geometry.h" + +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <unistd.h> + + +void Init(Gfx::CGLDevice *device) +{ + device->SetShadeModel(Gfx::SHADE_SMOOTH); + + device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + + device->SetTextureEnabled(0, true); + device->SetTextureEnabled(1, true); + + CImage img1; + if (! img1.Load("tex1.png")) + { + std::string err = img1.GetError(); + GetLogger()->Error("texture 1 not loaded, error: %s!\n", err.c_str()); + } + CImage img2; + if (! img2.Load("tex2.png")) + { + std::string err = img2.GetError(); + GetLogger()->Error("texture 2 not loaded, error: %s!\n", err.c_str()); + } + + Gfx::TextureCreateParams tex1CreateParams; + tex1CreateParams.mipmap = true; + tex1CreateParams.format = Gfx::TEX_IMG_RGBA; + tex1CreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR; + tex1CreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR; + + Gfx::TextureCreateParams tex2CreateParams; + tex2CreateParams.mipmap = true; + tex2CreateParams.format = Gfx::TEX_IMG_RGBA; + tex2CreateParams.minFilter = Gfx::TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST; + tex2CreateParams.magFilter = Gfx::TEX_MAG_FILTER_NEAREST; + + Gfx::Texture tex1 = device->CreateTexture(&img1, tex1CreateParams); + Gfx::Texture tex2 = device->CreateTexture(&img2, tex2CreateParams); + + device->SetTexture(0, tex1); + device->SetTexture(1, tex2); +} + +void Render(Gfx::CGLDevice *device) +{ + device->BeginScene(); + + Math::Matrix ortho; + Math::LoadOrthoProjectionMatrix(ortho, -10, 10, -10, 10); + device->SetTransform(Gfx::TRANSFORM_PROJECTION, ortho); + + Math::Matrix id; + id.LoadIdentity(); + + device->SetTransform(Gfx::TRANSFORM_WORLD, id); + device->SetTransform(Gfx::TRANSFORM_VIEW, id); + + static Gfx::VertexTex2 quad[] = + { + Gfx::VertexTex2(Math::Vector(-2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f)), + Gfx::VertexTex2(Math::Vector( 2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 0.0f), Math::Point(1.0f, 0.0f)), + Gfx::VertexTex2(Math::Vector( 2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 1.0f), Math::Point(1.0f, 1.0f)), + + Gfx::VertexTex2(Math::Vector( 2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 1.0f), Math::Point(1.0f, 1.0f)), + Gfx::VertexTex2(Math::Vector(-2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 1.0f), Math::Point(0.0f, 1.0f)), + Gfx::VertexTex2(Math::Vector(-2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f)), + }; + + Gfx::TextureStageParams tex1StageParams; + tex1StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT; + tex1StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; + device->SetTextureStageParams(0, tex1StageParams); + + Gfx::TextureStageParams tex2StageParams; + tex2StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT; + tex2StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; + device->SetTextureStageParams(1, tex2StageParams); + + Math::Matrix t; + Math::LoadTranslationMatrix(t, Math::Vector(-4.0f, 4.0f, 0.0f)); + device->SetTransform(Gfx::TRANSFORM_VIEW, t); + + device->SetTextureEnabled(0, true); + device->SetTextureEnabled(1, false); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6); + + Math::LoadTranslationMatrix(t, Math::Vector( 4.0f, 4.0f, 0.0f)); + device->SetTransform(Gfx::TRANSFORM_VIEW, t); + + device->SetTextureEnabled(0, false); + device->SetTextureEnabled(1, true); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6); + + Math::LoadTranslationMatrix(t, Math::Vector( 0.0f, -4.0f, 0.0f)); + device->SetTransform(Gfx::TRANSFORM_VIEW, t); + + device->SetTextureEnabled(0, true); + device->SetTextureEnabled(1, true); + + tex1StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT; + tex1StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; + device->SetTextureStageParams(0, tex1StageParams); + + tex2StageParams.colorOperation = Gfx::TEX_MIX_OPER_ADD; + tex2StageParams.colorArg1 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR; + tex2StageParams.colorArg2 = Gfx::TEX_MIX_ARG_TEXTURE; + tex2StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; + device->SetTextureStageParams(1, tex2StageParams); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6); + + device->EndScene(); +} + +int main() +{ + CLogger logger; + + // Without any error checking, for simplicity + + SDL_Init(SDL_INIT_VIDEO); + + IMG_Init(IMG_INIT_PNG); + + const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); + + Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE; + + if (videoInfo->hw_available) + videoFlags |= SDL_HWSURFACE; + else + videoFlags |= SDL_SWSURFACE; + + if (videoInfo->blit_hw) + videoFlags |= SDL_HWACCEL; + + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags); + + + SDL_WM_SetCaption("Texture Test", "Texture Test"); + + Gfx::CGLDevice *device = new Gfx::CGLDevice(Gfx::GLDeviceConfig()); + device->Create(); + + Init(device); + + bool done = false; + while (! done) + { + Render(device); + + SDL_GL_SwapBuffers(); + + SDL_Event event; + SDL_PollEvent(&event); + if (event.type == SDL_QUIT) + done = true; + + usleep(10000); + } + + device->Destroy(); + delete device; + + SDL_FreeSurface(surface); + + IMG_Quit(); + + SDL_Quit(); + + return 0; +} diff --git a/test/envs/opengl/transform_test.cpp b/test/envs/opengl/transform_test.cpp new file mode 100644 index 0000000..cddd1b8 --- /dev/null +++ b/test/envs/opengl/transform_test.cpp @@ -0,0 +1,339 @@ +#include "app/system.h" +#include "common/logger.h" +#include "common/image.h" +#include "common/iman.h" +#include "graphics/opengl/gldevice.h" +#include "math/geometry.h" + +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <unistd.h> + +#include <iostream> +#include <map> + +enum KeySlots +{ + K_Forward, + K_Back, + K_Left, + K_Right, + K_Up, + K_Down, + K_Count +}; +bool KEYMAP[K_Count] = { false }; + +Math::Point MOUSE_POS_BASE; + +Math::Vector TRANSLATION(0.0f, 2.0f, 0.0f); +Math::Vector ROTATION, ROTATION_BASE; + +const int FRAME_DELAY = 5000; + +SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL; + +void Init(Gfx::CGLDevice *device) +{ + device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true); + device->SetShadeModel(Gfx::SHADE_SMOOTH); +} + +void Render(Gfx::CGLDevice *device) +{ + device->BeginScene(); + + Math::Matrix persp; + Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f); + device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp); + + + Math::Matrix viewMat; + Math::Matrix mat; + + viewMat.LoadIdentity(); + + Math::LoadRotationXMatrix(mat, -ROTATION.x); + viewMat = Math::MultiplyMatrices(viewMat, mat); + + Math::LoadRotationYMatrix(mat, -ROTATION.y); + viewMat = Math::MultiplyMatrices(viewMat, mat); + + Math::LoadTranslationMatrix(mat, -TRANSLATION); + viewMat = Math::MultiplyMatrices(viewMat, mat); + + device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat); + + + Math::Matrix worldMat; + worldMat.LoadIdentity(); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + Gfx::VertexCol line[2] = { Gfx::VertexCol() }; + + for (int x = -40; x <= 40; ++x) + { + line[0].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f); + line[0].coord.z = -40; + line[0].coord.x = x; + line[1].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f); + line[1].coord.z = 40; + line[1].coord.x = x; + device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2); + } + + for (int z = -40; z <= 40; ++z) + { + line[0].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f); + line[0].coord.z = z; + line[0].coord.x = -40; + line[1].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f); + line[1].coord.z = z; + line[1].coord.x = 40; + device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2); + } + + + Gfx::VertexCol quad[6] = { Gfx::VertexCol() }; + + for (int i = 0; i < 6; ++i) + quad[i].color = Gfx::Color(1.0f, 1.0f, 0.0f); + + quad[0].coord = Math::Vector(-1.0f, -1.0f, 0.0f); + quad[1].coord = Math::Vector( 1.0f, -1.0f, 0.0f); + quad[2].coord = Math::Vector( 1.0f, 1.0f, 0.0f); + quad[3].coord = Math::Vector( 1.0f, 1.0f, 0.0f); + quad[4].coord = Math::Vector(-1.0f, 1.0f, 0.0f); + quad[5].coord = Math::Vector(-1.0f, -1.0f, 0.0f); + + Math::LoadTranslationMatrix(worldMat, Math::Vector(40.0f, 2.0f, 40.0f)); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6); + + for (int i = 0; i < 6; ++i) + quad[i].color = Gfx::Color(0.0f, 1.0f, 1.0f); + + Math::LoadTranslationMatrix(worldMat, Math::Vector(-40.0f, 2.0f, -40.0f)); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6); + + for (int i = 0; i < 6; ++i) + quad[i].color = Gfx::Color(1.0f, 0.0f, 1.0f); + + Math::LoadTranslationMatrix(worldMat, Math::Vector(0.0f, 10.0f, 0.0f)); + device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6); + + device->EndScene(); +} + +void Update() +{ + const float TRANS_SPEED = 6.0f; // units / sec + + GetCurrentTimeStamp(CURR_TIME); + float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC); + CopyTimeStamp(PREV_TIME, CURR_TIME); + + Math::Vector incTrans; + + if (KEYMAP[K_Forward]) + incTrans.z = +TRANS_SPEED * timeDiff; + if (KEYMAP[K_Back]) + incTrans.z = -TRANS_SPEED * timeDiff; + if (KEYMAP[K_Right]) + incTrans.x = +TRANS_SPEED * timeDiff; + if (KEYMAP[K_Left]) + incTrans.x = -TRANS_SPEED * timeDiff; + if (KEYMAP[K_Up]) + incTrans.y = +TRANS_SPEED * timeDiff; + if (KEYMAP[K_Down]) + incTrans.y = -TRANS_SPEED * timeDiff; + + Math::Point rotTrans = Math::RotatePoint(-ROTATION.y, Math::Point(incTrans.x, incTrans.z)); + incTrans.x = rotTrans.x; + incTrans.z = rotTrans.y; + TRANSLATION += incTrans; +} + +void KeyboardDown(SDLKey key) +{ + switch (key) + { + case SDLK_w: + KEYMAP[K_Forward] = true; + break; + case SDLK_s: + KEYMAP[K_Back] = true; + break; + case SDLK_d: + KEYMAP[K_Right] = true; + break; + case SDLK_a: + KEYMAP[K_Left] = true; + break; + case SDLK_z: + KEYMAP[K_Down] = true; + break; + case SDLK_x: + KEYMAP[K_Up] = true; + break; + default: + break; + } +} + +void KeyboardUp(SDLKey key) +{ + switch (key) + { + case SDLK_w: + KEYMAP[K_Forward] = false; + break; + case SDLK_s: + KEYMAP[K_Back] = false; + break; + case SDLK_d: + KEYMAP[K_Right] = false; + break; + case SDLK_a: + KEYMAP[K_Left] = false; + break; + case SDLK_z: + KEYMAP[K_Down] = false; + break; + case SDLK_x: + KEYMAP[K_Up] = false; + break; + default: + break; + } +} + +void MouseMove(int x, int y) +{ + Math::Point currentPos(static_cast<float>(x), static_cast<float>(y)); + + static bool first = true; + if (first || (x < 10) || (y < 10) || (x > 790) || (y > 590)) + { + SDL_WarpMouse(400, 300); + MOUSE_POS_BASE.x = 400; + MOUSE_POS_BASE.y = 300; + ROTATION_BASE = ROTATION; + first = false; + return; + } + + ROTATION.y = ROTATION_BASE.y + (static_cast<float> (x - MOUSE_POS_BASE.x) / 800.0f) * Math::PI; + ROTATION.x = ROTATION_BASE.x + (static_cast<float> (y - MOUSE_POS_BASE.y) / 600.0f) * Math::PI; +} + +int main(int argc, char *argv[]) +{ + CLogger logger; + + PREV_TIME = CreateTimeStamp(); + CURR_TIME = CreateTimeStamp(); + + GetCurrentTimeStamp(PREV_TIME); + GetCurrentTimeStamp(CURR_TIME); + + CInstanceManager iMan; + + // Without any error checking, for simplicity + + SDL_Init(SDL_INIT_VIDEO); + + IMG_Init(IMG_INIT_PNG); + + const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); + + Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE; + + if (videoInfo->hw_available) + videoFlags |= SDL_HWSURFACE; + else + videoFlags |= SDL_SWSURFACE; + + if (videoInfo->blit_hw) + videoFlags |= SDL_HWACCEL; + + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags); + + + SDL_WM_SetCaption("Transform Test", "Transform Test"); + + //SDL_WM_GrabInput(SDL_GRAB_ON); + SDL_ShowCursor(SDL_DISABLE); + + Gfx::CGLDevice *device = new Gfx::CGLDevice(Gfx::GLDeviceConfig()); + device->Create(); + + Init(device); + + bool done = false; + while (! done) + { + Render(device); + Update(); + + SDL_GL_SwapBuffers(); + + SDL_Event event; + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + done = true; + } + else if (event.type == SDL_KEYDOWN) + { + if (event.key.keysym.sym == SDLK_q) + { + done = true; + break; + } + else + KeyboardDown(event.key.keysym.sym); + } + else if (event.type == SDL_KEYUP) + KeyboardUp(event.key.keysym.sym); + else if (event.type == SDL_MOUSEMOTION) + MouseMove(event.motion.x, event.motion.y); + } + + usleep(FRAME_DELAY); + } + + //SDL_WM_GrabInput(SDL_GRAB_OFF); + SDL_ShowCursor(SDL_ENABLE); + + device->Destroy(); + delete device; + + SDL_FreeSurface(surface); + + IMG_Quit(); + + SDL_Quit(); + + DestroyTimeStamp(PREV_TIME); + DestroyTimeStamp(CURR_TIME); + + return 0; +} diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt new file mode 100644 index 0000000..f6a1d75 --- /dev/null +++ b/test/unit/CMakeLists.txt @@ -0,0 +1,24 @@ +set(SRC_DIR ${colobot_SOURCE_DIR}/src) + +include_directories( +${SRC_DIR} +${GTEST_INCLUDE_DIR} +math +common +) + +set(UT_SOURCES +main.cpp +math/geometry_test.cpp +math/matrix_test.cpp +math/vector_test.cpp +) + +add_executable(colobot_ut ${UT_SOURCES}) +target_link_libraries(colobot_ut gtest) + +add_test(colobot_ut ./colobot_ut) + +# TODO: change the unit cases to independent automated tests to be included in colobot_ut +add_subdirectory(common) +add_subdirectory(ui) diff --git a/test/unit/common/CMakeLists.txt b/test/unit/common/CMakeLists.txt new file mode 100644 index 0000000..a34c708 --- /dev/null +++ b/test/unit/common/CMakeLists.txt @@ -0,0 +1,16 @@ +set(SRC_DIR ${colobot_SOURCE_DIR}/src) + +include_directories( +${SRC_DIR} +${GTEST_INCLUDE_DIR} +) + +add_executable(image_test ${SRC_DIR}/common/image.cpp image_test.cpp) +target_link_libraries(image_test ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} ${PNG_LIBRARIES}) + +file(COPY colobot.ini DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(profile_test ${SRC_DIR}/common/profile.cpp ${SRC_DIR}/common/logger.cpp profile_test.cpp) +target_link_libraries(profile_test gtest ${Boost_LIBRARIES}) + +add_test(profile_test ./profile_test) diff --git a/test/unit/common/colobot.ini b/test/unit/common/colobot.ini new file mode 100644 index 0000000..2ca37ee --- /dev/null +++ b/test/unit/common/colobot.ini @@ -0,0 +1,15 @@ +[test_float] +float_value=1.5 + +[test_string] +string_value=Hello world + +[test_int] +int_value=42 + +[test_multi] +entry1=1 +entry2=2 +entry3=3 +entry4=4 +entry5=5 diff --git a/test/unit/common/image_test.cpp b/test/unit/common/image_test.cpp new file mode 100644 index 0000000..2a8d5e4 --- /dev/null +++ b/test/unit/common/image_test.cpp @@ -0,0 +1,57 @@ +#include "common/image.h" + +#include <SDL/SDL.h> +#include <stdio.h> + +/* For now, just a simple test: loading a file from image + * and saving it to another in PNG. */ + +int main(int argc, char *argv[]) +{ + if (argc != 3) + { + printf("Usage: %s in_image out_image\n", argv[0]); + return 0; + } + + CImage image; + + if (! image.Load(argv[1])) + { + std::string err = image.GetError(); + printf("Error loading '%s': %s\n", argv[1], err.c_str()); + return 1; + } + Gfx::Color color; + std::string str; + + color = image.GetPixel(Math::IntPoint(0, 0)); + str = color.ToString(); + printf("pixel @ (0,0): %s\n", str.c_str()); + + color = image.GetPixel(Math::IntPoint(0, 1)); + str = color.ToString(); + printf("pixel @ (0,1): %s\n", str.c_str()); + + color = image.GetPixel(Math::IntPoint(1, 0)); + str = color.ToString(); + printf("pixel @ (1,0): %s\n", str.c_str()); + + color = image.GetPixel(Math::IntPoint(1, 1)); + str = color.ToString(); + printf("pixel @ (1,1): %s\n", str.c_str()); + + image.SetPixel(Math::IntPoint(0, 0), Gfx::Color(0.1f, 0.2f, 0.3f, 0.0f)); + image.SetPixel(Math::IntPoint(1, 0), Gfx::Color(0.3f, 0.2f, 0.1f, 1.0f)); + image.SetPixel(Math::IntPoint(0, 1), Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); + image.SetPixel(Math::IntPoint(1, 1), Gfx::Color(0.0f, 0.0f, 0.0f, 1.0f)); + + if (! image.SavePNG(argv[2])) + { + std::string err = image.GetError(); + printf("Error saving PNG '%s': %s\n", argv[2], err.c_str()); + return 2; + } + + return 0; +} diff --git a/test/unit/common/profile_test.cpp b/test/unit/common/profile_test.cpp new file mode 100644 index 0000000..e7b64d5 --- /dev/null +++ b/test/unit/common/profile_test.cpp @@ -0,0 +1,43 @@ +#include "common/profile.h" +#include "common/logger.h" + +#include <iostream> +#include <string> +#include <vector> +#include <gtest/gtest.h> + + +class CProfileTest : public testing::Test +{ +protected: + CLogger m_logger; + CProfile m_profile; + +}; + +TEST_F(CProfileTest, ReadTest) +{ + ASSERT_TRUE(m_profile.InitCurrentDirectory()); // load colobot.ini file + + std::string result; + ASSERT_TRUE(m_profile.GetLocalProfileString("test_string", "string_value", result)); + ASSERT_STREQ("Hello world", result.c_str()); + + int int_value; + ASSERT_TRUE(m_profile.GetLocalProfileInt("test_int", "int_value", int_value)); + ASSERT_EQ(42, int_value); + + float float_value; + ASSERT_TRUE(m_profile.GetLocalProfileFloat("test_float", "float_value", float_value)); + ASSERT_FLOAT_EQ(1.5, float_value); + + std::vector<std::string> list; + list = m_profile.GetLocalProfileSection("test_multi", "entry"); + ASSERT_EQ(5u, list.size()); +} + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/unit/main.cpp b/test/unit/main.cpp new file mode 100644 index 0000000..e978630 --- /dev/null +++ b/test/unit/main.cpp @@ -0,0 +1,24 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +#include "gtest/gtest.h" + +int main(int argc, char* argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/test/unit/math/gendata.m b/test/unit/math/gendata.m new file mode 100644 index 0000000..5c13491 --- /dev/null +++ b/test/unit/math/gendata.m @@ -0,0 +1,86 @@ +% Script in Octave for generating test data + +1; + +% Returns the minor matrix +function m = minor(A, r, c) + + m = A; + m(r,:) = []; + m(:,c) = []; + +end; + +% Returns the cofactor matrix +function m = cofactors(A) + + m = zeros(rows(A), columns(A)); + + for r = [1 : rows(A)] + for c = [1 : columns(A)] + m(r, c) = det(minor(A, r, c)); + if (mod(r + c, 2) == 1) + m(r, c) = -m(r, c); + end; + end; + end; + +end; + +% Prints the matrix as C++ code +function printout(A, name) + + printf('const float %s[16] = \n', name); + printf('{\n'); + + for c = [1 : columns(A)] + for r = [1 : rows(A)] + printf(' %f', A(r,c)); + if (! ( (r == 4) && (c == 4) ) ) + printf(','); + end; + printf('\n'); + end; + end; + + printf('};\n'); + +end; + +printf('// Cofactors\n'); +A = randn(4,4); +printout(A, 'COF_MAT'); +printf('\n'); +printout(cofactors(A), 'COF_RESULT'); +printf('\n'); + +printf('\n'); + +printf('// Det\n'); +A = randn(4,4); +printout(A, 'DET_MAT'); +printf('\n'); +printf('const float DET_RESULT = %f;', det(A)); +printf('\n'); + +printf('\n'); + +printf('// Invert\n'); +A = randn(4,4); +printout(A, 'INV_MAT'); +printf('\n'); +printout(inv(A), 'COF_RESULT'); +printf('\n'); + +printf('\n'); + +printf('// Multiplication\n'); +A = randn(4,4); +printout(A, 'MUL_A'); +printf('\n'); +B = randn(4,4); +printout(B, 'MUL_B'); +printf('\n'); +C = A * B; +printout(C, 'MUL_RESULT'); +printf('\n'); diff --git a/test/unit/math/geometry_test.cpp b/test/unit/math/geometry_test.cpp new file mode 100644 index 0000000..f50df4e --- /dev/null +++ b/test/unit/math/geometry_test.cpp @@ -0,0 +1,352 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// math/test/geometry_test.cpp + +/* Unit tests for functions in geometry.h */ + +#include "math/func.h" +#include "math/geometry.h" + +#include "gtest/gtest.h" + + +const float TEST_TOLERANCE = 1e-5; + + +// Test for rewritten function RotateAngle() +TEST(GeometryTest, RotateAngleTest) +{ + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(0.0f, 0.0f), 0.0f, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(1.0f, 0.0f), 0.0f, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(1.0f, 1.0f), 0.25f * Math::PI, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(0.0f, 2.0f), 0.5f * Math::PI, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(-0.5f, 0.5f), 0.75f * Math::PI, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(-1.0f, 0.0f), Math::PI, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(-1.0f, -1.0f), 1.25f * Math::PI, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(0.0f, -2.0f), 1.5f * Math::PI, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(1.0f, -1.0f), 1.75f * Math::PI, TEST_TOLERANCE)); +} + +// Tests for other altered, complex or uncertain functions + +/* + + TODO: write meaningful tests with proper test values + +int TestAngle() +{ + const Math::Vector u(-0.0786076246943884, 0.2231249091714256, -1.1601361718477805); + const Math::Vector v(-1.231228742001907, -1.720549809950561, -0.690468438834111); + + float mathResult = Math::Angle(u, v); + float oldMathResult = Angle(VEC_TO_D3DVEC(u), VEC_TO_D3DVEC(v)); + + if (! Math::IsEqual(mathResult, oldMathResult, TEST_TOLERANCE) ) + return __LINE__; + + return 0; +} + +int TestRotateView() +{ + const Math::Vector center(0.617909142705555, 0.896939729454538, -0.615041943652284); + const float angleH = 44.5; + const float angleV = 12.3; + const float dist = 34.76; + + Math::Vector mathResult = Math::RotateView(center, angleH, angleV, dist); + Math::Vector oldMathResult = D3DVEC_TO_VEC(RotateView(VEC_TO_D3DVEC(center), angleH, angleV, dist)); + + if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLookatPoint() +{ + const Math::Vector eye(-2.451183170579471, 0.241270270546559, -0.490677411454893); + const float angleH = 48.4; + const float angleV = 32.4; + const float length = 74.44; + + Math::Vector mathResult = Math::LookatPoint(eye, angleH, angleV, length); + Math::Vector oldMathResult = D3DVEC_TO_VEC(LookatPoint(VEC_TO_D3DVEC(eye), angleH, angleV, length)); + + if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestProjection() +{ + const Math::Vector a(0.852064846846319, -0.794279497087496, -0.655779805476688); + const Math::Vector b(-0.245838834102304, -0.841115596038861, 0.470457161487799); + const Math::Vector p(2.289326061164255, -0.505511362271196, 0.660204551169491); + + Math::Vector mathResult = Math::Projection(a, b, p); + Math::Vector oldMathResult = D3DVEC_TO_VEC(Projection(VEC_TO_D3DVEC(a), VEC_TO_D3DVEC(b), VEC_TO_D3DVEC(p))); + + if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadViewMatrix() +{ + const Math::Vector from(2.5646013154868874, -0.6058794133917031, -0.0441195127419744); + const Math::Vector at(0.728044925765569, -0.206343977871841, 2.543158236935463); + const Math::Vector worldUp(-1.893738133660711, -1.009584441407070, 0.521745988225582); + + Math::Matrix mathResult; + Math::LoadViewMatrix(mathResult, from, at, worldUp); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DVECTOR fromD3D = VEC_TO_D3DVEC(from); + D3DVECTOR atD3D = VEC_TO_D3DVEC(at); + D3DVECTOR worldUpD3D = VEC_TO_D3DVEC(worldUp); + D3DUtil_SetViewMatrix(mat, fromD3D, atD3D, worldUpD3D); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadProjectionMatrix() +{ + const float fov = 76.3f; + const float aspect = 0.891f; + const float nearPlane = 12.3f; + const float farPlane = 1238.9f; + + Math::Matrix mathResult; + Math::LoadProjectionMatrix(mathResult, fov, aspect, nearPlane, farPlane); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetProjectionMatrix(mat, fov, aspect, nearPlane, farPlane); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadTranslationMatrix() +{ + const Math::Vector translation(-0.3631590720995237, 1.6976327614875211, 0.0148815191502145); + + Math::Matrix mathResult; + Math::LoadTranslationMatrix(mathResult, translation); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetTranslateMatrix(mat, translation.x, translation.y, translation.z); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadScaleMatrix() +{ + const Math::Vector scale(0.612236460285503, -0.635566935025364, -0.254321375332065); + + Math::Matrix mathResult; + Math::LoadScaleMatrix(mathResult, scale); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetScaleMatrix(mat, scale.x, scale.y, scale.z); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadRotationXMatrix() +{ + const float angle = 0.513790685774275; + + Math::Matrix mathResult; + Math::LoadRotationXMatrix(mathResult, angle); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetRotateXMatrix(mat, angle); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadRotationYMatrix() +{ + const float angle = -0.569166650127303; + + Math::Matrix mathResult; + Math::LoadRotationYMatrix(mathResult, angle); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetRotateYMatrix(mat, angle); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadRotationZMatrix() +{ + const float angle = 0.380448034347452; + + Math::Matrix mathResult; + Math::LoadRotationZMatrix(mathResult, angle); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetRotateZMatrix(mat, angle); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadRotationMatrix() +{ + const float angle = -0.987747190637790; + const Math::Vector dir(-0.113024727688331, -0.781265998072571, 1.838972397076884); + + Math::Matrix mathResult; + Math::LoadRotationMatrix(mathResult, dir, angle); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DVECTOR dirD3D = VEC_TO_D3DVEC(dir); + D3DUtil_SetRotationMatrix(mat, dirD3D, angle); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadRotationXZYMatrix() +{ + const Math::Vector angles(-0.841366567984597, -0.100543315396357, 1.610647811559988); + + Math::Matrix mathResult; + Math::LoadRotationXZYMatrix(mathResult, angles); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + MatRotateXZY(mat, VEC_TO_D3DVEC(angles)); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestLoadRotationZXYMatrix() +{ + const Math::Vector angles(0.275558495480206, -0.224328265970090, 0.943077216574253); + + Math::Matrix mathResult; + Math::LoadRotationZXYMatrix(mathResult, angles); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + MatRotateZXY(mat, VEC_TO_D3DVEC(angles)); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +int TestTransform() +{ + Math::Matrix transformMatrix( + (float[4][4]) + { + { -0.9282074720977896, 0.6794734970319730, -1.3234304946882685, 0.0925294727863890 }, + { -0.0395527963683484, 0.2897634352353881, 1.9144398570315440, -1.4062267508968478 }, + { 0.9133323625282361, -0.6741836434774530, -0.2188812951424338, -1.0089184339952666 }, + { 0.0f, 0.0f, 0.0f, 1.0f } + } + ); + Math::Vector vector(-0.314596433318370, -0.622681232583150, -0.371307535743574); + + Math::Vector mathResult = Math::Transform(transformMatrix, vector); + Math::Vector oldMathResult = Transform(transformMatrix, vector); + + if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; +} + +*/ + diff --git a/test/unit/math/matrix_test.cpp b/test/unit/math/matrix_test.cpp new file mode 100644 index 0000000..6ae2c6b --- /dev/null +++ b/test/unit/math/matrix_test.cpp @@ -0,0 +1,314 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// math/test/matrix_test.cpp + +/* + Unit tests for Matrix struct + + Test data was randomly generated and the expected results + calculated using GNU Octave. + */ + +#include "math/func.h" +#include "math/matrix.h" + +#include "gtest/gtest.h" + + +const float TEST_TOLERANCE = 1e-6; + + +TEST(MatrixTest, TransposeTest) +{ + const Math::Matrix mat( + (float[4][4]) + { + { -0.07011674491203920, 1.26145596067429810, 2.09476603598066902, 0.35560176915570696 }, + { -1.34075615966224704, 1.17988499016709314, 0.00601713429241016, -0.75213676977972566 }, + { 0.59186722295223981, 0.88089224074765293, 0.70994467464257294, 0.36730385425340212 }, + { -0.95649396555068111, 0.75912182022565566, 1.34883305778387186, -1.34957997578168754 } + } + ); + + const Math::Matrix expectedTranspose( + (float[4][4]) + { + { -0.07011674491203920, -1.34075615966224704, 0.59186722295223981, -0.95649396555068111 }, + { 1.26145596067429810, 1.17988499016709314, 0.88089224074765293, 0.75912182022565566 }, + { 2.09476603598066902, 0.00601713429241016, 0.70994467464257294, 1.34883305778387186 }, + { 0.35560176915570696, -0.75213676977972566, 0.36730385425340212, -1.34957997578168754 } + } + ); + + Math::Matrix transpose = Math::Transpose(mat); + + EXPECT_TRUE(Math::MatricesEqual(transpose, expectedTranspose, TEST_TOLERANCE)); +} + +TEST(MatrixTest, CofactorTest) +{ + const Math::Matrix mat1( + (float[4][4]) + { + { 0.610630320796245, 1.059932357918312, -1.581674311378210, 1.782214448453331 }, + { 0.191028848211526, -0.813898708757524, 1.516114203870644, 0.395202639476002 }, + { 0.335142750345279, -0.346586619596529, 0.545382042472336, -0.879268918923072 }, + { 1.417588151657198, 1.450841789070141, 0.219080104196171, 0.378724047481655 } + } + ); + + const Math::Matrix expectedCofactors1( + (float[4][4]) + { + { -2.402679369186782, 2.282452509293019, 1.722732204057644, -0.746939701104385 }, + { -0.687677756877654, 1.168949180331164, -0.985354966837796, -1.334071111592705 }, + { -5.115621958424845, 4.229724770159009, 2.529000630782808, 1.481632618355891 }, + { 0.147480897398694, -2.140677680337111, -1.207189492265546, 0.151236920408051 } + } + ); + + for (int r = 0; r < 4; ++r) + { + for (int c = 0; c < 4; ++c) + { + float ret = mat1.Cofactor(r, c); + float exp = expectedCofactors1.m[4*c+r]; + EXPECT_TRUE(Math::IsEqual(ret, exp, TEST_TOLERANCE)); + } + } + + const Math::Matrix mat2( + (float[4][4]) + { + { 0.9845099464982393, -0.9091233416532389, -0.6272243714245945, 0.4645001858944354 }, + { -0.1333308471483736, 0.9128181433725897, -1.0937461393836190, 0.3180936795928376 }, + { -0.0654324396846289, 0.1014641705415945, 1.5107709042683430, -0.0240560430414690 }, + { 0.0179638644093347, -1.0695585982782767, -0.1741250853101032, 1.0803106709464336 } + } + ); + + const Math::Matrix expectedCofactors2( + (float[4][4]) + { + { 2.0861102207614466, 0.2989010779528912, 0.0746276150537432, 0.2732659822656097 }, + { 0.6850002886584565, 1.5513169659641379, -0.0503743176545917, 1.5163672441575642 }, + { 1.2385556680997216, 1.1827709562505695, 1.2282813085138962, 1.3483789679871401 }, + { -1.0710790241539783, -0.5589604503588883, 0.0100959837872308, 1.1897872684455839 } + } + ); + + + for (int r = 0; r < 4; ++r) + { + for (int c = 0; c < 4; ++c) + { + float ret = mat2.Cofactor(r, c); + float exp = expectedCofactors2.m[4*c+r]; + EXPECT_TRUE(Math::IsEqual(ret, exp, TEST_TOLERANCE)); + } + } +} + +TEST(MatrixTest, DetTest) +{ + const Math::Matrix mat1( + (float[4][4]) + { + { -0.95880162984708284, 0.24004047608997131, -0.78172309932665407, -0.11604124457222834 }, + { -0.36230592086261376, -0.75778166876017261, 0.33041059404631740, -1.06001391941094836 }, + { 0.00260215210936187, 1.27485610196385113, -0.26149859846418033, -0.59669701186364876 }, + { 0.36899429848485432, 3.01720896813933104, 2.10311476609438719, -1.68627076626448269 } + } + ); + + const float expectedDet1 = 4.07415413729671; + + float ret1 = mat1.Det(); + EXPECT_TRUE(Math::IsEqual(ret1, expectedDet1, TEST_TOLERANCE)); + + const Math::Matrix mat2( + (float[4][4]) + { + { -1.0860073221346871, 0.9150354098189495, -0.2723201933559999, 0.2922832160271507 }, + { -1.0248331304801788, -2.5081237461125205, -1.0277123574586633, -0.2254690663329798 }, + { -1.4227635282899367, -0.0403846809122684, 0.9216148477171653, 1.2517067488015878 }, + { -0.1160254467152022, 0.8270675274393656, 1.0327218739781614, -0.3674886870220400 } + } + ); + + const float expectedDet2 = -6.35122307880942; + + float ret2 = mat2.Det(); + EXPECT_TRUE(Math::IsEqual(ret2, expectedDet2, TEST_TOLERANCE)); +} + +TEST(MatrixTest, InverseTest) +{ + const Math::Matrix mat1( + (float[4][4]) + { + { -2.2829352811514658, -0.9103222363187888, 0.2792976509411680, -0.7984393573193174 }, + { 2.4823665798689589, -0.0599056759070980, 0.3832364352926366, -1.6404257204372739 }, + { -0.3841952272526398, -0.8377700696457873, -0.3416328338427138, 1.1746577275723329 }, + { 0.1746031241954947, -0.4952532117949962, 0.2155084379835037, -1.6586460437329220 } + } + ); + + const Math::Matrix expectedInverse1( + (float[4][4]) + { + { -0.119472603171041, 0.331675963276297, 0.187516809009720, -0.137720814290806 }, + { -0.387591686166085, -0.487284946727583, -0.798527541290274, 0.102991635972060 }, + { 2.601905603425902, 2.606899016264679, -0.528006148839176, -4.204703326522837 }, + { 0.441220327151392, 0.519128136207318, 0.189567009205522, -1.194469716136194 } + } + ); + + Math::Matrix inverse1 = mat1.Inverse(); + + EXPECT_TRUE(Math::MatricesEqual(inverse1, expectedInverse1, TEST_TOLERANCE)); + + const Math::Matrix mat2( + (float[4][4]) + { + { -0.05464332404298505, -0.64357755258235749, -0.13017671677619302, -0.56742332785888006 }, + { 0.29048383600458222, -0.91517047043724875, 0.84517524415561684, 0.51628195547960565 }, + { 0.00946488004480186, -0.89077382212689293, 0.73565573766341397, -0.15932513521840930 }, + { -1.01244718912499132, -0.27840911963972276, -0.39189681211309862, 1.18315064340192055 } + } + ); + + const Math::Matrix expectedInverse2( + (float[4][4]) + { + { 0.771302711132012, 1.587542278361995, -2.003075114445104, -0.592574156227379 }, + { -1.208929259769431, -0.786598967848473, 0.607335305808052, -0.154759693303324 }, + { -1.500037668208218, -0.774300278997914, 1.917800427261255, -0.123268572651291 }, + { -0.121314770937944, 0.916925149209746, -0.935924950785014, 0.260875394250671 } + } + ); + + Math::Matrix inverse2 = mat2.Inverse(); + + EXPECT_TRUE(Math::MatricesEqual(inverse2, expectedInverse2, TEST_TOLERANCE)); +} + +TEST(MatrixTest, MultiplyTest) +{ + const Math::Matrix mat1A( + (float[4][4]) + { + { 0.6561727049162027, -1.4180263627131411, -0.8271026046117423, 2.3919331748512578 }, + { -0.6035665535146352, 0.0150827348790615, -0.7090794192822540, 0.9057604704594814 }, + { -0.9871045001223655, -0.4980646811455065, 0.3806177002298990, 0.1520583649240934 }, + { -0.2721911170792712, 0.7627928194552067, -0.1504091336784158, 0.9747545351840121 } + } + ); + + const Math::Matrix mat1B( + (float[4][4]) + { + { -0.2643735892448818, -0.7542994492819621, 0.6082322350568750, 0.0581733424861419 }, + { 1.0293246070431237, 0.1979285388251341, -0.2932031385332818, 0.8838407179018929 }, + { 0.3448687251553114, 0.5031654871245456, 0.7554693012922442, -0.4845315903845708 }, + { -1.8662838497278593, -0.7843850624747805, 0.1389026096476257, -1.3686415408300689 } + } + ); + + const Math::Matrix expectedMultiply1( + (float[4][4]) + { + { -6.382352236417988, -3.067984733682130, 0.522270304251466, -4.088079444498280 }, + { -1.759853366848825, -0.608994052024491, -0.781406179437379, -0.917870775786188 }, + { -0.404226802169062, 0.718232546720114, -0.145688356880835, -0.890167707987175 }, + { -1.013918490922430, -0.483971504099758, -0.367442194643757, -0.602858486133615 } + } + ); + + Math::Matrix multiply1 = Math::MultiplyMatrices(mat1A, mat1B); + EXPECT_TRUE(Math::MatricesEqual(multiply1, expectedMultiply1, TEST_TOLERANCE)); + + const Math::Matrix mat2A( + (float[4][4]) + { + { 0.8697203025776754, 2.1259475710644935, 1.7856691009707812, -2.1563963348328126 }, + { 1.5888074489288735, -0.0794849733953615, 0.7307782768677457, 0.7943129159612630 }, + { 0.2859761537233830, -0.6231231890384962, -0.0496743172880377, -0.8137857518646087 }, + { 1.2670547229512983, -0.5305171374831831, -0.4987412674062375, -1.1257327113869595 } + } + ); + + const Math::Matrix mat2B( + (float[4][4]) + { + { 1.1321105701165317, 0.1759563504574463, -2.0675778912000418, 1.4840339814245538 }, + { -1.5117280888829916, -0.0933013188828093, -0.2079262944351640, 0.9575727579539316 }, + { 0.3615378398970173, 1.2465163589027248, 1.1326150997082589, 0.9921208694352303 }, + { -0.7357104529373861, -0.4774022005969588, -0.2118739096676499, 1.1427567093270703 } + } + ); + + const Math::Matrix expectedMultiply2( + (float[4][4]) + { + { 0.00283516267056338, 3.21001319965989307, 0.23910503934370686, 2.63380716363006107 }, + { 1.59868505822469742, 0.81869715594617765, -2.60905981088293570, 3.91445839239110294 }, + { 1.84650099286297942, 0.43504079532852930, -0.34555619012424243, -1.15152951542451487 }, + { 2.88434318563174585, 0.18818239851585700, -2.83579436909308980, -0.40890672198610400 } + } + ); + + Math::Matrix multiply2 = Math::MultiplyMatrices(mat2A, mat2B); + EXPECT_TRUE(Math::MatricesEqual(multiply2, expectedMultiply2, TEST_TOLERANCE)); +} + +TEST(MatrixTest, MultiplyVectorTest) +{ + const Math::Matrix mat1( + (float[4][4]) + { + { 0.188562846910008, -0.015148651460679, 0.394512304108827, 0.906910631257135 }, + { -0.297506779519667, 0.940119328178913, 0.970957796752517, 0.310559318965526 }, + { -0.819770525290873, -2.316574438778879, 0.155756069319732, -0.855661405742964 }, + { 0.000000000000000, 0.000000000000000, 0.000000000000000, 1.000000000000000 } + } + ); + + const Math::Vector vec1(-0.824708565156661, -1.598287748103842, -0.422498044734181); + + const Math::Vector expectedMultiply1(0.608932463260470, -1.356893266403749, 3.457156276255142); + + Math::Vector multiply1 = Math::MatrixVectorMultiply(mat1, vec1, false); + EXPECT_TRUE(Math::VectorsEqual(multiply1, expectedMultiply1, TEST_TOLERANCE)); + + const Math::Matrix mat2( + (float[4][4]) + { + { -0.63287117038834284, 0.55148060401816856, -0.02042395559467368, -1.50367083897656850 }, + { 0.69629042156335297, 0.12982747869796774, -1.16250029235919405, 1.19084447253756909 }, + { 0.44164132914357224, -0.15169304045662041, -0.00880583574621390, -0.55817802940035310 }, + { 0.95680476533530789, -1.51912346889253125, -0.74209769406615944, -0.20938988867903682 } + } + ); + + const Math::Vector vec2(0.330987381051962, 1.494375516393466, 1.483422335561857); + + const Math::Vector expectedMultiply2(0.2816820577317669, 0.0334468811767428, 0.1996974284970455); + + Math::Vector multiply2 = Math::MatrixVectorMultiply(mat2, vec2, true); + EXPECT_TRUE(Math::VectorsEqual(multiply2, expectedMultiply2, TEST_TOLERANCE)); +} diff --git a/test/unit/math/vector_test.cpp b/test/unit/math/vector_test.cpp new file mode 100644 index 0000000..199f4c3 --- /dev/null +++ b/test/unit/math/vector_test.cpp @@ -0,0 +1,74 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// math/test/vector_test.cpp + +/* + Unit tests for Vector struct + + Test data was randomly generated and the expected results + calculated using GNU Octave. + */ + +#include "math/func.h" +#include "math/vector.h" + +#include "gtest/gtest.h" + + +const float TEST_TOLERANCE = 1e-6; + + +TEST(VectorTest, LengthTest) +{ + Math::Vector vec(-1.288447945923275, 0.681452565308134, -0.633761098985957); + const float expectedLength = 1.58938001708428; + + EXPECT_TRUE(Math::IsEqual(vec.Length(), expectedLength, TEST_TOLERANCE)); +} + +TEST(VectorTest, NormalizeTest) +{ + Math::Vector vec(1.848877241804398, -0.157262961268577, -1.963031403332377); + const Math::Vector expectedNormalized(0.6844609421393856, -0.0582193085618106, -0.7267212194481797); + + vec.Normalize(); + + EXPECT_TRUE(Math::VectorsEqual(vec, expectedNormalized, TEST_TOLERANCE)); +} + +TEST(VectorTest, DotTest) +{ + Math::Vector vecA(0.8202190530968309, 0.0130926060162780, 0.2411914183883510); + Math::Vector vecB(-0.0524083951404069, 1.5564932716738220, -0.8971342631500536); + + float expectedDot = -0.238988896477326; + + EXPECT_TRUE(Math::IsEqual(Math::DotProduct(vecA, vecB), expectedDot, TEST_TOLERANCE)); +} + +TEST(VectorTest, CrossTest) +{ + Math::Vector vecA(1.37380499798567, 1.18054518384682, 1.95166361293121); + Math::Vector vecB(0.891657855926886, 0.447591335394532, -0.901604070087823); + + Math::Vector expectedCross(-1.937932065431669, 2.978844370287636, -0.437739173833581); + Math::Vector expectedReverseCross = -expectedCross; + + EXPECT_TRUE(Math::VectorsEqual(vecA.CrossMultiply(vecB), expectedCross, TEST_TOLERANCE)); + + EXPECT_TRUE(Math::VectorsEqual(vecB.CrossMultiply(vecA), expectedReverseCross, TEST_TOLERANCE)); +} diff --git a/test/unit/ui/CMakeLists.txt b/test/unit/ui/CMakeLists.txt new file mode 100644 index 0000000..32af230 --- /dev/null +++ b/test/unit/ui/CMakeLists.txt @@ -0,0 +1,29 @@ +set(SRC_DIR ${colobot_SOURCE_DIR}/src) + +include_directories( +. +${SRC_DIR} +${GTEST_INCLUDE_DIR} +${GMOCK_INCLUDE_DIR} +) + +add_executable(edit_test +${SRC_DIR}/common/event.cpp +${SRC_DIR}/common/logger.cpp +${SRC_DIR}/common/misc.cpp +${SRC_DIR}/common/iman.cpp +${SRC_DIR}/common/stringutils.cpp +${SRC_DIR}/graphics/engine/text.cpp +${SRC_DIR}/ui/button.cpp +${SRC_DIR}/ui/control.cpp +${SRC_DIR}/ui/edit.cpp +${SRC_DIR}/ui/scroll.cpp +stubs/app_stub.cpp +stubs/engine_stub.cpp +stubs/particle_stub.cpp +stubs/restext_stub.cpp +stubs/robotmain_stub.cpp +edit_test.cpp) +target_link_libraries(edit_test gtest gmock ${SDL_LIBRARY} ${SDLTTF_LIBRARY} ${Boost_LIBRARIES}) + +add_test(edit_test ./edit_test) diff --git a/test/unit/ui/edit_test.cpp b/test/unit/ui/edit_test.cpp new file mode 100644 index 0000000..f878f4b --- /dev/null +++ b/test/unit/ui/edit_test.cpp @@ -0,0 +1,74 @@ +#include "app/app.h" +#include "ui/edit.h" +#include "mocks/text_mock.h" + +#include <gtest/gtest.h> +#include <gmock/gmock.h> +#include <fstream> + +class CEditTest : public testing::Test +{ +public: + CEditTest(){}; + + virtual void SetUp() + { + m_engine = new Gfx::CEngine(&m_iMan, NULL); + + m_iMan.AddInstance(CLASS_ENGINE, m_engine); + m_edit = new Ui::CEdit; + } + + virtual void TearDown() + { + m_iMan.DeleteInstance(CLASS_ENGINE, m_engine); + delete m_engine; + m_engine = NULL; + delete m_edit; + m_edit = NULL; + + } + virtual ~CEditTest() + { + + }; + +protected: + CInstanceManager m_iMan; + CApplication m_app; + Gfx::CEngine * m_engine; + Ui::CEdit * m_edit; + CLogger m_logger; +}; + +using ::testing::_; +using ::testing::Return; + +TEST_F(CEditTest, WriteTest) +{ + ASSERT_TRUE(true); + CTextMock * text = dynamic_cast<CTextMock *>(m_engine->GetText()); + EXPECT_CALL(*text, GetCharWidth(_, _, _, _)).WillRepeatedly(Return(1.0f)); + EXPECT_CALL(*text, GetStringWidth(_, _, _)).WillOnce(Return(1.0f)); + std::string filename = "test.file"; + m_edit->SetMaxChar(Ui::EDITSTUDIOMAX); + m_edit->SetAutoIndent(true); + std::string inputScript = "{\ntext1\ntext2\n\ntext3\n{\ntext4\n}\n}"; + std::string expectedScript = "{\r\n\ttext1\r\n\ttext2\r\n\t\r\n\ttext3\r\n\t{\r\n\t\ttext4\r\n\t}\r\n}"; + m_edit->SetText(inputScript.c_str(), true); + GetLogger()->Info("Writing text \n"); + m_edit->WriteText("script.txt"); + + std::fstream scriptFile; + + scriptFile.open("script.txt", std::ios_base::binary | std::ios_base::in); + std::string outputScript((std::istreambuf_iterator<char>(scriptFile)), std::istreambuf_iterator<char>()); + ASSERT_STREQ(expectedScript.c_str(), outputScript.c_str()); +} + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/test/unit/ui/mocks/text_mock.h b/test/unit/ui/mocks/text_mock.h new file mode 100644 index 0000000..f0ad339 --- /dev/null +++ b/test/unit/ui/mocks/text_mock.h @@ -0,0 +1,21 @@ +#include "common/logger.h" +#include "graphics/engine/text.h" + +#include <gmock/gmock.h> + +class CTextMock : public Gfx::CText +{ +public: + CTextMock(CInstanceManager *iMan, Gfx::CEngine* engine) : CText(iMan, engine) + { + } + + virtual ~CTextMock() + { + }; + + MOCK_METHOD4(GetCharWidth, float(Gfx::UTF8Char, Gfx::FontType, float, float)); + MOCK_METHOD3(GetStringWidth, float(const std::string &, Gfx::FontType, float)); + +}; + diff --git a/test/unit/ui/stubs/app_stub.cpp b/test/unit/ui/stubs/app_stub.cpp new file mode 100644 index 0000000..70d9e82 --- /dev/null +++ b/test/unit/ui/stubs/app_stub.cpp @@ -0,0 +1,26 @@ +#include "app/app.h" +#include "graphics/opengl/gldevice.h" + +template<> CApplication* CSingleton<CApplication>::mInstance = nullptr; + +namespace Gfx { + +GLDeviceConfig::GLDeviceConfig() +{ +} + +} /* Gfx */ +CApplication::CApplication() +{ +} + +CApplication::~CApplication() +{ +} + +std::string CApplication::GetDataFilePath(DataDir /* dataDir */, const std::string& subpath) +{ + return subpath; +} + + diff --git a/test/unit/ui/stubs/engine_stub.cpp b/test/unit/ui/stubs/engine_stub.cpp new file mode 100644 index 0000000..de7bbe7 --- /dev/null +++ b/test/unit/ui/stubs/engine_stub.cpp @@ -0,0 +1,79 @@ +#include "graphics/engine/engine.h" +#include "graphics/engine/text.h" +#include "mocks/text_mock.h" + +namespace Gfx { + +CEngine::CEngine(CInstanceManager* iMan, CApplication* app) : + m_iMan(iMan), m_app(app) +{ + m_text = new CTextMock(m_iMan, this); + m_text->Create(); +} + +CEngine::~CEngine() +{ + delete m_text; + m_text = NULL; +} + +Math::Point CEngine::WindowToInterfaceSize(Math::IntPoint size) +{ + return Math::Point(size.x, size.y); +} + +void CEngine::SetState(int state, const Color& color) +{ + if (state == m_lastState && color == m_lastColor) + return; + + m_lastState = state; + m_lastColor = color; +} + +Math::IntPoint CEngine::GetWindowSize() +{ + return m_size; +} + +void CEngine::AddStatisticTriangle(int count) +{ + m_statisticTriangle += count; +} + +void CEngine::SetMouseType(EngineMouseType type) +{ + m_mouseType = type; +} + +bool CEngine::SetTexture(const std::string& /* name */, int /* stage */) +{ + return true; +} + +CText* CEngine::GetText() +{ + return m_text; +} + +CDevice* CEngine::GetDevice() +{ + return m_device; +} + +int CEngine::GetEditIndentValue() +{ + return m_editIndentValue; +} + +void CEngine::DeleteTexture(const std::string& /* texName */) +{ +} +Texture CEngine::LoadTexture(const std::string& /* name */) +{ + Texture texture; + return texture; +} + +} /* Gfx */ + diff --git a/test/unit/ui/stubs/particle_stub.cpp b/test/unit/ui/stubs/particle_stub.cpp new file mode 100644 index 0000000..c3bf6dc --- /dev/null +++ b/test/unit/ui/stubs/particle_stub.cpp @@ -0,0 +1,205 @@ +#include "graphics/engine/particle.h" + +#include "common/logger.h" + + +// Graphics module namespace +namespace Gfx { + + +CParticle::CParticle(CInstanceManager* /*iMan*/, CEngine* /*engine*/) +{ +} + +CParticle::~CParticle() +{ +} + +void CParticle::SetDevice(CDevice* /*device*/) +{ +} + +void CParticle::FlushParticle() +{ +} + +void CParticle::FlushParticle(int /*sheet*/) +{ +} + +int CParticle::CreateParticle(Math::Vector /*pos*/, Math::Vector /*speed*/, Math::Point /*dim*/, + ParticleType /*type*/, float /*duration*/, float /*mass*/, + float /*windSensitivity*/, int /*sheet*/) +{ + return 0; +} + +int CParticle::CreateFrag(Math::Vector /*pos*/, Math::Vector /*speed*/, EngineTriangle */*triangle*/, + ParticleType /*type*/, float /*duration*/, float /*mass*/, + float /*windSensitivity*/, int /*sheet*/) +{ + return 0; +} + +int CParticle::CreatePart(Math::Vector /*pos*/, Math::Vector /*speed*/, ParticleType /*type*/, + float /*duration*/, float /*mass*/, float /*weight*/, + float /*windSensitivity*/, int /*sheet*/) +{ + return 0; +} + +int CParticle::CreateRay(Math::Vector /*pos*/, Math::Vector /*goal*/, ParticleType /*type*/, Math::Point /*dim*/, + float /*duration*/, int /*sheet*/) +{ + return 0; +} + +int CParticle::CreateTrack(Math::Vector /*pos*/, Math::Vector /*speed*/, Math::Point /*dim*/, ParticleType /*type*/, + float /*duration*/, float /*mass*/, float /*length*/, float /*width*/) +{ + return 0; +} + +void CParticle::CreateWheelTrace(const Math::Vector &/*p1*/, const Math::Vector &/*p2*/, const Math::Vector &/*p3*/, + const Math::Vector &/*p4*/, ParticleType /*type*/) +{ +} + +void CParticle::DeleteParticle(ParticleType /*type*/) +{ +} + +void CParticle::DeleteParticle(int /*channel*/) +{ +} + +void CParticle::SetObjectLink(int /*channel*/, CObject */*object*/) +{ +} + +void CParticle::SetObjectFather(int /*channel*/, CObject */*object*/) +{ +} + +void CParticle::SetPosition(int /*channel*/, Math::Vector /*pos*/) +{ +} + +void CParticle::SetDimension(int /*channel*/, Math::Point /*dim*/) +{ +} + +void CParticle::SetZoom(int /*channel*/, float /*zoom*/) +{ +} + +void CParticle::SetAngle(int /*channel*/, float /*angle*/) +{ +} + +void CParticle::SetIntensity(int /*channel*/, float /*intensity*/) +{ +} + +void CParticle::SetParam(int /*channel*/, Math::Vector /*pos*/, Math::Point /*dim*/, float /*zoom*/, float /*angle*/, float /*intensity*/) +{ +} + +void CParticle::SetPhase(int /*channel*/, ParticlePhase /*phase*/, float /*duration*/) +{ +} + +bool CParticle::GetPosition(int /*channel*/, Math::Vector &/*pos*/) +{ + return true; +} + +Color CParticle::GetFogColor(Math::Vector /*pos*/) +{ + return Color(); +} + +void CParticle::SetFrameUpdate(int /*sheet*/, bool /*update*/) +{ +} + +void CParticle::FrameParticle(float /*rTime*/) +{ +} + +void CParticle::DrawParticle(int /*sheet*/) +{ +} + +bool CParticle::WriteWheelTrace(const char */*filename*/, int /*width*/, int /*height*/, Math::Vector /*dl*/, Math::Vector /*ur*/) +{ + return true; +} + +void CParticle::DeleteRank(int /*rank*/) +{ +} + +bool CParticle::CheckChannel(int &/*channel*/) +{ + return true; +} + +void CParticle::DrawParticleTriangle(int /*i*/) +{ +} + +void CParticle::DrawParticleNorm(int /*i*/) +{ +} + +void CParticle::DrawParticleFlat(int /*i*/) +{ +} + +void CParticle::DrawParticleFog(int /*i*/) +{ +} + +void CParticle::DrawParticleRay(int /*i*/) +{ +} + +void CParticle::DrawParticleSphere(int /*i*/) +{ +} + +void CParticle::DrawParticleCylinder(int /*i*/) +{ +} + +void CParticle::DrawParticleWheel(int /*i*/) +{ +} + +CObject* CParticle::SearchObjectGun(Math::Vector /*old*/, Math::Vector /*pos*/, ParticleType /*type*/, CObject */*father*/) +{ + return nullptr; +} + +CObject* CParticle::SearchObjectRay(Math::Vector /*pos*/, Math::Vector /*goal*/, ParticleType /*type*/, CObject */*father*/) +{ + return nullptr; +} + +void CParticle::Play(Sound /*sound*/, Math::Vector /*pos*/, float /*amplitude*/) +{ +} + +bool CParticle::TrackMove(int /*i*/, Math::Vector /*pos*/, float /*progress*/) +{ + return true; +} + +void CParticle::TrackDraw(int /*i*/, ParticleType /*type*/) +{ +} + + +} // namespace Gfx + diff --git a/test/unit/ui/stubs/restext_stub.cpp b/test/unit/ui/stubs/restext_stub.cpp new file mode 100644 index 0000000..004da19 --- /dev/null +++ b/test/unit/ui/stubs/restext_stub.cpp @@ -0,0 +1,12 @@ +#include "common/restext.h" + +bool GetResource(ResType /* type */, int /* num */, char* /* text */) +{ + return true; +} + +bool SearchKey(const char * /* cmd */, InputSlot & /* key */) +{ + return true; +} + diff --git a/test/unit/ui/stubs/robotmain_stub.cpp b/test/unit/ui/stubs/robotmain_stub.cpp new file mode 100644 index 0000000..a36b1a1 --- /dev/null +++ b/test/unit/ui/stubs/robotmain_stub.cpp @@ -0,0 +1,17 @@ +#include "object/robotmain.h" + + +template<> CRobotMain* CSingleton<CRobotMain>::mInstance = nullptr; + +bool CRobotMain::GetGlint() +{ + return false; +} + +const InputBinding& CRobotMain::GetInputBinding(InputSlot slot) +{ + unsigned int index = static_cast<unsigned int>(slot); + assert(index >= 0 && index < INPUT_SLOT_MAX); + return m_inputBindings[index]; +} + |