From 81bb6873f1c0291fecbf6e429ad15ac3db66a4c0 Mon Sep 17 00:00:00 2001 From: Aki Date: Tue, 12 Mar 2024 22:07:03 +0100 Subject: Legal notices updated Rename contrib -> third-party intendes to express the origin and purpose of that part of the code better. I plan to readd contrib/ again but with more in-project things like bash-completions, dev workflow scripts etc. --- CMakeLists.txt | 4 +- COPYING | 2 +- DefinitionEx/Parser_ss.cpp | 2 +- DefinitionEx/Parser_ss.h | 2 +- DefinitionEx/Term.cpp | 2 +- DefinitionEx/Term.h | 2 +- DefinitionEx/Token.cpp | 2 +- DefinitionEx/Token.h | 2 +- FoundationEx/include/Dictionary.h | 2 +- FoundationEx/include/Dictionary.inl.h | 2 +- FoundationEx/include/List.h | 2 +- FoundationEx/include/List.inl.h | 2 +- FoundationEx/include/Reader.h | 2 +- FoundationEx/include/Text.h | 2 +- FoundationEx/include/Utils.h | 2 +- FoundationEx/src/Reader.cpp | 2 +- FoundationEx/src/Text.cpp | 2 +- FoundationEx/src/Utils.cpp | 2 +- NOTICE | 35 +- NetEx/HttpClient.cpp | 2 +- NetEx/HttpClient.h | 2 +- NetEx/HttpParam.cpp | 2 +- NetEx/HttpParam.h | 2 +- NetEx/HttpRequest.cpp | 2 +- NetEx/HttpRequest.h | 2 +- NetEx/HttpResponse.cpp | 2 +- NetEx/HttpResponse.h | 2 +- NetEx/HttpServer.cpp | 2 +- NetEx/HttpServer.h | 2 +- NetEx/HttpServlet.cpp | 2 +- NetEx/HttpServlet.h | 2 +- NetEx/HttpServletExec.cpp | 2 +- NetEx/HttpServletExec.h | 2 +- NetEx/HttpSession.cpp | 2 +- NetEx/HttpSession.h | 2 +- NetEx/NetAddr.cpp | 2 +- NetEx/NetAddr.h | 2 +- NetEx/NetClient.cpp | 2 +- NetEx/NetClient.h | 2 +- NetEx/NetGram.cpp | 2 +- NetEx/NetGram.h | 2 +- NetEx/NetHost.cpp | 2 +- NetEx/NetHost.h | 2 +- NetEx/NetLayer.cpp | 2 +- NetEx/NetLayer.h | 2 +- NetEx/NetLink.cpp | 2 +- NetEx/NetLink.h | 2 +- NetEx/NetMsg.cpp | 2 +- NetEx/NetMsg.h | 2 +- NetEx/NetPeer.cpp | 2 +- NetEx/NetPeer.h | 2 +- NetEx/NetServer.cpp | 2 +- NetEx/NetServer.h | 2 +- NetEx/NetSock.cpp | 2 +- NetEx/NetSock.h | 2 +- StarsEx/ActiveWindow.cpp | 2 +- StarsEx/ActiveWindow.h | 2 +- StarsEx/Asteroid.cpp | 2 +- StarsEx/Asteroid.h | 2 +- StarsEx/AudDlg.cpp | 2 +- StarsEx/AudDlg.h | 2 +- StarsEx/AudioConfig.cpp | 2 +- StarsEx/AudioConfig.h | 2 +- StarsEx/AwardDlg.cpp | 2 +- StarsEx/AwardDlg.h | 2 +- StarsEx/AwardShowDlg.cpp | 2 +- StarsEx/AwardShowDlg.h | 2 +- StarsEx/BaseScreen.h | 2 +- StarsEx/Bitmap.cpp | 2 +- StarsEx/Bitmap.h | 2 +- StarsEx/Bmp.cpp | 2 +- StarsEx/Bmp.h | 2 +- StarsEx/Bolt.cpp | 2 +- StarsEx/Bolt.h | 2 +- StarsEx/Button.cpp | 2 +- StarsEx/Button.h | 2 +- StarsEx/Callsign.cpp | 2 +- StarsEx/Callsign.h | 2 +- StarsEx/Camera.cpp | 2 +- StarsEx/Camera.h | 2 +- StarsEx/CameraDirector.cpp | 2 +- StarsEx/CameraDirector.h | 2 +- StarsEx/CameraView.cpp | 2 +- StarsEx/CameraView.h | 2 +- StarsEx/Campaign.cpp | 2 +- StarsEx/Campaign.h | 2 +- StarsEx/CampaignMissionFighter.cpp | 2 +- StarsEx/CampaignMissionFighter.h | 2 +- StarsEx/CampaignMissionRequest.cpp | 2 +- StarsEx/CampaignMissionRequest.h | 2 +- StarsEx/CampaignMissionStarship.cpp | 2 +- StarsEx/CampaignMissionStarship.h | 2 +- StarsEx/CampaignPlan.h | 2 +- StarsEx/CampaignPlanAssignment.cpp | 2 +- StarsEx/CampaignPlanAssignment.h | 2 +- StarsEx/CampaignPlanEvent.cpp | 2 +- StarsEx/CampaignPlanEvent.h | 2 +- StarsEx/CampaignPlanMission.cpp | 2 +- StarsEx/CampaignPlanMission.h | 2 +- StarsEx/CampaignPlanMovement.cpp | 2 +- StarsEx/CampaignPlanMovement.h | 2 +- StarsEx/CampaignPlanStrategic.cpp | 2 +- StarsEx/CampaignPlanStrategic.h | 2 +- StarsEx/CampaignSaveGame.cpp | 2 +- StarsEx/CampaignSaveGame.h | 2 +- StarsEx/CampaignSituationReport.cpp | 2 +- StarsEx/CampaignSituationReport.h | 2 +- StarsEx/CarrierAI.cpp | 2 +- StarsEx/CarrierAI.h | 2 +- StarsEx/Clock.cpp | 2 +- StarsEx/Clock.h | 2 +- StarsEx/Clock.inl.h | 2 +- StarsEx/CmdDlg.cpp | 2 +- StarsEx/CmdDlg.h | 2 +- StarsEx/CmdForceDlg.cpp | 2 +- StarsEx/CmdForceDlg.h | 2 +- StarsEx/CmdIntelDlg.cpp | 2 +- StarsEx/CmdIntelDlg.h | 2 +- StarsEx/CmdMissionsDlg.cpp | 2 +- StarsEx/CmdMissionsDlg.h | 2 +- StarsEx/CmdMsgDlg.cpp | 2 +- StarsEx/CmdMsgDlg.h | 2 +- StarsEx/CmdOrdersDlg.cpp | 2 +- StarsEx/CmdOrdersDlg.h | 2 +- StarsEx/CmdTheaterDlg.cpp | 2 +- StarsEx/CmdTheaterDlg.h | 2 +- StarsEx/CmdTitleDlg.cpp | 2 +- StarsEx/CmdTitleDlg.h | 2 +- StarsEx/CmpCompleteDlg.cpp | 2 +- StarsEx/CmpCompleteDlg.h | 2 +- StarsEx/CmpFileDlg.cpp | 2 +- StarsEx/CmpFileDlg.h | 2 +- StarsEx/CmpLoadDlg.cpp | 2 +- StarsEx/CmpLoadDlg.h | 2 +- StarsEx/CmpSceneDlg.cpp | 2 +- StarsEx/CmpSceneDlg.h | 2 +- StarsEx/CmpSelectDlg.cpp | 2 +- StarsEx/CmpSelectDlg.h | 2 +- StarsEx/CmpnScreen.cpp | 2 +- StarsEx/CmpnScreen.h | 2 +- StarsEx/Color.cpp | 2 +- StarsEx/Color.h | 2 +- StarsEx/CombatAction.cpp | 2 +- StarsEx/CombatAction.h | 2 +- StarsEx/CombatAssignment.cpp | 2 +- StarsEx/CombatAssignment.h | 2 +- StarsEx/CombatEvent.cpp | 2 +- StarsEx/CombatEvent.h | 2 +- StarsEx/CombatGroup.cpp | 2 +- StarsEx/CombatGroup.h | 2 +- StarsEx/CombatRoster.cpp | 2 +- StarsEx/CombatRoster.h | 2 +- StarsEx/CombatUnit.cpp | 2 +- StarsEx/CombatUnit.h | 2 +- StarsEx/CombatZone.cpp | 2 +- StarsEx/CombatZone.h | 2 +- StarsEx/Combatant.cpp | 2 +- StarsEx/Combatant.h | 2 +- StarsEx/ComboBox.cpp | 2 +- StarsEx/ComboBox.h | 2 +- StarsEx/ComboList.cpp | 2 +- StarsEx/ComboList.h | 2 +- StarsEx/Component.cpp | 2 +- StarsEx/Component.h | 2 +- StarsEx/Computer.cpp | 2 +- StarsEx/Computer.h | 2 +- StarsEx/ConfirmDlg.cpp | 2 +- StarsEx/ConfirmDlg.h | 2 +- StarsEx/Contact.cpp | 2 +- StarsEx/Contact.h | 2 +- StarsEx/ContentBundle.cpp | 2 +- StarsEx/ContentBundle.h | 2 +- StarsEx/CtlDlg.cpp | 2 +- StarsEx/CtlDlg.h | 2 +- StarsEx/D3DXImage.cpp | 2 +- StarsEx/D3DXImage.h | 2 +- StarsEx/DataLoader.cpp | 2 +- StarsEx/DataLoader.h | 2 +- StarsEx/DataSource.cpp | 2 +- StarsEx/DataSource.h | 2 +- StarsEx/DebriefDlg.cpp | 2 +- StarsEx/DebriefDlg.h | 2 +- StarsEx/Debris.cpp | 2 +- StarsEx/Debris.h | 2 +- StarsEx/DetailSet.cpp | 2 +- StarsEx/DetailSet.h | 2 +- StarsEx/Director.h | 2 +- StarsEx/DisplayView.cpp | 2 +- StarsEx/DisplayView.h | 2 +- StarsEx/Drive.cpp | 2 +- StarsEx/Drive.h | 2 +- StarsEx/DriveSprite.cpp | 2 +- StarsEx/DriveSprite.h | 2 +- StarsEx/Drone.cpp | 2 +- StarsEx/Drone.h | 2 +- StarsEx/DropShipAI.cpp | 2 +- StarsEx/DropShipAI.h | 2 +- StarsEx/EditBox.cpp | 2 +- StarsEx/EditBox.h | 2 +- StarsEx/Element.cpp | 2 +- StarsEx/Element.h | 2 +- StarsEx/Encrypt.cpp | 2 +- StarsEx/Encrypt.h | 2 +- StarsEx/EngDlg.cpp | 2 +- StarsEx/EngDlg.h | 2 +- StarsEx/ExceptionHandler.cpp | 2 +- StarsEx/ExitDlg.cpp | 2 +- StarsEx/ExitDlg.h | 2 +- StarsEx/Explosion.cpp | 2 +- StarsEx/Explosion.h | 2 +- StarsEx/FadeView.cpp | 2 +- StarsEx/FadeView.h | 2 +- StarsEx/Farcaster.cpp | 2 +- StarsEx/Farcaster.h | 2 +- StarsEx/FighterAI.cpp | 2 +- StarsEx/FighterAI.h | 2 +- StarsEx/FighterTacticalAI.cpp | 2 +- StarsEx/FighterTacticalAI.h | 2 +- StarsEx/FirstTimeDlg.cpp | 2 +- StarsEx/FirstTimeDlg.h | 2 +- StarsEx/Fix.cpp | 2 +- StarsEx/Fix.h | 2 +- StarsEx/FlightComp.cpp | 2 +- StarsEx/FlightComp.h | 2 +- StarsEx/FlightDeck.cpp | 2 +- StarsEx/FlightDeck.h | 2 +- StarsEx/FlightPlanner.cpp | 2 +- StarsEx/FlightPlanner.h | 2 +- StarsEx/FltDlg.cpp | 2 +- StarsEx/FltDlg.h | 2 +- StarsEx/Font.cpp | 2 +- StarsEx/Font.h | 2 +- StarsEx/FontMgr.cpp | 2 +- StarsEx/FontMgr.h | 2 +- StarsEx/FormDef.cpp | 2 +- StarsEx/FormDef.h | 2 +- StarsEx/FormWindow.cpp | 2 +- StarsEx/FormWindow.h | 2 +- StarsEx/FormatUtil.cpp | 2 +- StarsEx/FormatUtil.h | 2 +- StarsEx/Galaxy.cpp | 2 +- StarsEx/Galaxy.h | 2 +- StarsEx/Game.cpp | 2 +- StarsEx/Game.h | 2 +- StarsEx/GameScreen.cpp | 2 +- StarsEx/GameScreen.h | 2 +- StarsEx/GameWinDX9.cpp | 2 +- StarsEx/GameWinDX9.h | 2 +- StarsEx/Geometry.cpp | 2 +- StarsEx/Geometry.h | 2 +- StarsEx/Graphic.cpp | 2 +- StarsEx/Graphic.h | 2 +- StarsEx/Grid.cpp | 2 +- StarsEx/Grid.h | 2 +- StarsEx/GroundAI.cpp | 2 +- StarsEx/GroundAI.h | 2 +- StarsEx/HUDSounds.cpp | 2 +- StarsEx/HUDSounds.h | 2 +- StarsEx/HUDView.cpp | 2 +- StarsEx/HUDView.h | 2 +- StarsEx/Hangar.cpp | 2 +- StarsEx/Hangar.h | 2 +- StarsEx/HardPoint.cpp | 2 +- StarsEx/HardPoint.h | 2 +- StarsEx/Hoop.cpp | 2 +- StarsEx/Hoop.h | 2 +- StarsEx/ImageBox.cpp | 2 +- StarsEx/ImageBox.h | 2 +- StarsEx/ImgView.cpp | 2 +- StarsEx/ImgView.h | 2 +- StarsEx/Instruction.cpp | 2 +- StarsEx/Instruction.h | 2 +- StarsEx/Intel.cpp | 2 +- StarsEx/Intel.h | 2 +- StarsEx/JoyDlg.cpp | 2 +- StarsEx/JoyDlg.h | 2 +- StarsEx/Joystick.cpp | 2 +- StarsEx/Joystick.h | 2 +- StarsEx/KeyDlg.cpp | 2 +- StarsEx/KeyDlg.h | 2 +- StarsEx/KeyMap.cpp | 2 +- StarsEx/KeyMap.h | 2 +- StarsEx/Keyboard.cpp | 2 +- StarsEx/Keyboard.h | 2 +- StarsEx/LandingGear.cpp | 2 +- StarsEx/LandingGear.h | 2 +- StarsEx/Layout.cpp | 2 +- StarsEx/Layout.h | 2 +- StarsEx/Light.cpp | 2 +- StarsEx/Light.h | 2 +- StarsEx/ListBox.cpp | 2 +- StarsEx/ListBox.h | 2 +- StarsEx/LoadDlg.cpp | 2 +- StarsEx/LoadDlg.h | 2 +- StarsEx/LoadScreen.cpp | 2 +- StarsEx/LoadScreen.h | 2 +- StarsEx/Locale_ss.cpp | 2 +- StarsEx/Locale_ss.h | 2 +- StarsEx/MCIWave.cpp | 2 +- StarsEx/MCIWave.h | 2 +- StarsEx/MapView.cpp | 2 +- StarsEx/MapView.h | 2 +- StarsEx/Menu.cpp | 2 +- StarsEx/Menu.h | 2 +- StarsEx/MenuDlg.cpp | 2 +- StarsEx/MenuDlg.h | 2 +- StarsEx/MenuScreen.cpp | 2 +- StarsEx/MenuScreen.h | 2 +- StarsEx/MenuView.cpp | 2 +- StarsEx/MenuView.h | 2 +- StarsEx/Mfd.cpp | 2 +- StarsEx/Mfd.h | 2 +- StarsEx/Mission.cpp | 2 +- StarsEx/Mission.h | 2 +- StarsEx/MissionEvent.cpp | 2 +- StarsEx/MissionEvent.h | 2 +- StarsEx/MissionTemplate.cpp | 2 +- StarsEx/MissionTemplate.h | 2 +- StarsEx/ModConfig.cpp | 2 +- StarsEx/ModConfig.h | 2 +- StarsEx/ModDlg.cpp | 2 +- StarsEx/ModDlg.h | 2 +- StarsEx/ModInfo.cpp | 2 +- StarsEx/ModInfo.h | 2 +- StarsEx/ModInfoDlg.cpp | 2 +- StarsEx/ModInfoDlg.h | 2 +- StarsEx/MotionController.h | 2 +- StarsEx/Mouse.cpp | 2 +- StarsEx/Mouse.h | 2 +- StarsEx/MouseController.cpp | 2 +- StarsEx/MouseController.h | 2 +- StarsEx/MsnDlg.cpp | 2 +- StarsEx/MsnDlg.h | 2 +- StarsEx/MsnEditDlg.cpp | 2 +- StarsEx/MsnEditDlg.h | 2 +- StarsEx/MsnEditNavDlg.cpp | 2 +- StarsEx/MsnEditNavDlg.h | 2 +- StarsEx/MsnElemDlg.cpp | 2 +- StarsEx/MsnElemDlg.h | 2 +- StarsEx/MsnEventDlg.cpp | 2 +- StarsEx/MsnEventDlg.h | 2 +- StarsEx/MsnNavDlg.cpp | 2 +- StarsEx/MsnNavDlg.h | 2 +- StarsEx/MsnObjDlg.cpp | 2 +- StarsEx/MsnObjDlg.h | 2 +- StarsEx/MsnPkgDlg.cpp | 2 +- StarsEx/MsnPkgDlg.h | 2 +- StarsEx/MsnSelectDlg.cpp | 2 +- StarsEx/MsnSelectDlg.h | 2 +- StarsEx/MsnWepDlg.cpp | 2 +- StarsEx/MsnWepDlg.h | 2 +- StarsEx/MultiController.cpp | 2 +- StarsEx/MultiController.h | 2 +- StarsEx/MusicDirector.cpp | 2 +- StarsEx/MusicDirector.h | 2 +- StarsEx/MusicTrack.cpp | 2 +- StarsEx/MusicTrack.h | 2 +- StarsEx/NavAI.cpp | 2 +- StarsEx/NavAI.h | 2 +- StarsEx/NavDlg.cpp | 2 +- StarsEx/NavDlg.h | 2 +- StarsEx/NavLight.cpp | 2 +- StarsEx/NavLight.h | 2 +- StarsEx/NavSystem.cpp | 2 +- StarsEx/NavSystem.h | 2 +- StarsEx/NetAddrDlg.cpp | 2 +- StarsEx/NetAddrDlg.h | 2 +- StarsEx/NetAuth.cpp | 2 +- StarsEx/NetAuth.h | 2 +- StarsEx/NetBrokerClient.cpp | 2 +- StarsEx/NetBrokerClient.h | 2 +- StarsEx/NetChat.cpp | 2 +- StarsEx/NetChat.h | 2 +- StarsEx/NetClientConfig.cpp | 2 +- StarsEx/NetClientConfig.h | 2 +- StarsEx/NetClientDlg.cpp | 2 +- StarsEx/NetClientDlg.h | 2 +- StarsEx/NetData.cpp | 2 +- StarsEx/NetData.h | 2 +- StarsEx/NetGame.cpp | 2 +- StarsEx/NetGame.h | 2 +- StarsEx/NetGameClient.cpp | 2 +- StarsEx/NetGameClient.h | 2 +- StarsEx/NetGameServer.cpp | 2 +- StarsEx/NetGameServer.h | 2 +- StarsEx/NetLobby.cpp | 2 +- StarsEx/NetLobby.h | 2 +- StarsEx/NetLobbyClient.cpp | 2 +- StarsEx/NetLobbyClient.h | 2 +- StarsEx/NetLobbyDlg.cpp | 2 +- StarsEx/NetLobbyDlg.h | 2 +- StarsEx/NetLobbyServer.cpp | 2 +- StarsEx/NetLobbyServer.h | 2 +- StarsEx/NetPacket.cpp | 2 +- StarsEx/NetPacket.h | 2 +- StarsEx/NetPassDlg.cpp | 2 +- StarsEx/NetPassDlg.h | 2 +- StarsEx/NetPlayer.cpp | 2 +- StarsEx/NetPlayer.h | 2 +- StarsEx/NetServerConfig.cpp | 2 +- StarsEx/NetServerConfig.h | 2 +- StarsEx/NetServerDlg.cpp | 2 +- StarsEx/NetServerDlg.h | 2 +- StarsEx/NetUnitDlg.cpp | 2 +- StarsEx/NetUnitDlg.h | 2 +- StarsEx/NetUser.cpp | 2 +- StarsEx/NetUser.h | 2 +- StarsEx/NetUtil.cpp | 2 +- StarsEx/NetUtil.h | 2 +- StarsEx/OptDlg.cpp | 2 +- StarsEx/OptDlg.h | 2 +- StarsEx/Panic.cpp | 2 +- StarsEx/Panic.h | 2 +- StarsEx/ParseUtil.cpp | 2 +- StarsEx/ParseUtil.h | 2 +- StarsEx/Particles.cpp | 2 +- StarsEx/Particles.h | 2 +- StarsEx/Pcx.cpp | 2 +- StarsEx/Pcx.h | 2 +- StarsEx/Physical.cpp | 2 +- StarsEx/Physical.h | 2 +- StarsEx/PlanScreen.cpp | 2 +- StarsEx/PlanScreen.h | 2 +- StarsEx/Player.cpp | 2 +- StarsEx/Player.h | 2 +- StarsEx/PlayerDlg.cpp | 2 +- StarsEx/PlayerDlg.h | 2 +- StarsEx/PngImage.cpp | 2 +- StarsEx/PngImage.h | 2 +- StarsEx/Polygon.cpp | 2 +- StarsEx/Polygon.h | 2 +- StarsEx/Power.cpp | 2 +- StarsEx/Power.h | 2 +- StarsEx/Projector.cpp | 2 +- StarsEx/Projector.h | 2 +- StarsEx/QuantumDrive.cpp | 2 +- StarsEx/QuantumDrive.h | 2 +- StarsEx/QuantumFlash.cpp | 2 +- StarsEx/QuantumFlash.h | 2 +- StarsEx/QuantumView.cpp | 2 +- StarsEx/QuantumView.h | 2 +- StarsEx/QuitView.cpp | 2 +- StarsEx/QuitView.h | 2 +- StarsEx/RLoc.cpp | 2 +- StarsEx/RLoc.h | 2 +- StarsEx/RadioHandler.cpp | 2 +- StarsEx/RadioHandler.h | 2 +- StarsEx/RadioMessage.cpp | 2 +- StarsEx/RadioMessage.h | 2 +- StarsEx/RadioTraffic.cpp | 2 +- StarsEx/RadioTraffic.h | 2 +- StarsEx/RadioView.cpp | 2 +- StarsEx/RadioView.h | 2 +- StarsEx/RadioVox.cpp | 2 +- StarsEx/RadioVox.h | 2 +- StarsEx/Random.cpp | 2 +- StarsEx/Random.h | 2 +- StarsEx/Res.cpp | 2 +- StarsEx/Res.h | 2 +- StarsEx/RichTextBox.cpp | 2 +- StarsEx/RichTextBox.h | 2 +- StarsEx/Scene.cpp | 2 +- StarsEx/Scene.h | 2 +- StarsEx/Screen.cpp | 2 +- StarsEx/Screen.h | 2 +- StarsEx/ScrollWindow.cpp | 2 +- StarsEx/ScrollWindow.h | 2 +- StarsEx/SeekerAI.cpp | 2 +- StarsEx/SeekerAI.h | 2 +- StarsEx/Sensor.cpp | 2 +- StarsEx/Sensor.h | 2 +- StarsEx/Shadow.cpp | 2 +- StarsEx/Shadow.h | 2 +- StarsEx/Shield.cpp | 2 +- StarsEx/Shield.h | 2 +- StarsEx/ShieldRep.cpp | 2 +- StarsEx/ShieldRep.h | 2 +- StarsEx/Ship.cpp | 2 +- StarsEx/Ship.h | 2 +- StarsEx/ShipAI.cpp | 2 +- StarsEx/ShipAI.h | 2 +- StarsEx/ShipCtrl.cpp | 2 +- StarsEx/ShipCtrl.h | 2 +- StarsEx/ShipDesign.cpp | 2 +- StarsEx/ShipDesign.h | 2 +- StarsEx/ShipKiller.cpp | 2 +- StarsEx/ShipKiller.h | 2 +- StarsEx/ShipSolid.cpp | 2 +- StarsEx/ShipSolid.h | 2 +- StarsEx/Shot.cpp | 2 +- StarsEx/Shot.h | 2 +- StarsEx/Sim.cpp | 2 +- StarsEx/Sim.h | 2 +- StarsEx/SimEvent.cpp | 2 +- StarsEx/SimEvent.h | 2 +- StarsEx/SimObject.cpp | 2 +- StarsEx/SimObject.h | 2 +- StarsEx/Skin.cpp | 2 +- StarsEx/Skin.h | 2 +- StarsEx/Sky.cpp | 2 +- StarsEx/Sky.h | 2 +- StarsEx/Slider.cpp | 2 +- StarsEx/Slider.h | 2 +- StarsEx/Solid.cpp | 2 +- StarsEx/Solid.h | 2 +- StarsEx/Sound.cpp | 2 +- StarsEx/Sound.h | 2 +- StarsEx/SoundCard.cpp | 2 +- StarsEx/SoundCard.h | 2 +- StarsEx/SoundD3D.cpp | 2 +- StarsEx/SoundD3D.h | 2 +- StarsEx/Sprite.cpp | 2 +- StarsEx/Sprite.h | 2 +- StarsEx/StarSystem.cpp | 2 +- StarsEx/StarSystem.h | 2 +- StarsEx/Starshatter.cpp | 2 +- StarsEx/Starshatter.h | 2 +- StarsEx/StarshipAI.cpp | 2 +- StarsEx/StarshipAI.h | 2 +- StarsEx/StarshipTacticalAI.cpp | 2 +- StarsEx/StarshipTacticalAI.h | 2 +- StarsEx/SteerAI.cpp | 2 +- StarsEx/SteerAI.h | 2 +- StarsEx/System.cpp | 2 +- StarsEx/System.h | 2 +- StarsEx/SystemDesign.cpp | 2 +- StarsEx/SystemDesign.h | 2 +- StarsEx/TacRefDlg.cpp | 2 +- StarsEx/TacRefDlg.h | 2 +- StarsEx/TacticalAI.cpp | 2 +- StarsEx/TacticalAI.h | 2 +- StarsEx/TacticalView.cpp | 2 +- StarsEx/TacticalView.h | 2 +- StarsEx/Terrain.cpp | 2 +- StarsEx/Terrain.h | 2 +- StarsEx/TerrainApron.cpp | 2 +- StarsEx/TerrainApron.h | 2 +- StarsEx/TerrainClouds.cpp | 2 +- StarsEx/TerrainClouds.h | 2 +- StarsEx/TerrainHaze.cpp | 2 +- StarsEx/TerrainHaze.h | 2 +- StarsEx/TerrainLayer.h | 2 +- StarsEx/TerrainPatch.cpp | 2 +- StarsEx/TerrainPatch.h | 2 +- StarsEx/TerrainRegion.cpp | 2 +- StarsEx/TerrainRegion.h | 2 +- StarsEx/TexCubeDX9.cpp | 2 +- StarsEx/TexCubeDX9.h | 2 +- StarsEx/TexDX9.cpp | 2 +- StarsEx/TexDX9.h | 2 +- StarsEx/Thruster.cpp | 2 +- StarsEx/Thruster.h | 2 +- StarsEx/TrackIR.cpp | 2 +- StarsEx/TrackIR.h | 2 +- StarsEx/Trail.cpp | 2 +- StarsEx/Trail.h | 2 +- StarsEx/Types.h | 2 +- StarsEx/UIEventDispatch.cpp | 2 +- StarsEx/UIEventDispatch.h | 2 +- StarsEx/UIEventTarget.h | 2 +- StarsEx/Universe.h | 2 +- StarsEx/VersionInfo.h | 2 +- StarsEx/VidDlg.cpp | 2 +- StarsEx/VidDlg.h | 2 +- StarsEx/Video.cpp | 2 +- StarsEx/Video.h | 2 +- StarsEx/VideoDX9.cpp | 2 +- StarsEx/VideoDX9.h | 2 +- StarsEx/VideoDX9Enum.cpp | 2 +- StarsEx/VideoDX9Enum.h | 2 +- StarsEx/VideoDX9VertexBuffer.cpp | 2 +- StarsEx/VideoDX9VertexBuffer.h | 2 +- StarsEx/VideoFactory.cpp | 2 +- StarsEx/VideoFactory.h | 2 +- StarsEx/VideoSettings.cpp | 2 +- StarsEx/VideoSettings.h | 2 +- StarsEx/View.h | 2 +- StarsEx/Water.cpp | 2 +- StarsEx/Water.h | 2 +- StarsEx/Wave.h | 2 +- StarsEx/Weapon.cpp | 2 +- StarsEx/Weapon.h | 2 +- StarsEx/WeaponDesign.cpp | 2 +- StarsEx/WeaponDesign.h | 2 +- StarsEx/WeaponGroup.cpp | 2 +- StarsEx/WeaponGroup.h | 2 +- StarsEx/Weather.cpp | 2 +- StarsEx/Weather.h | 2 +- StarsEx/WepView.cpp | 2 +- StarsEx/WepView.h | 2 +- StarsEx/Window.cpp | 2 +- StarsEx/Window.h | 2 +- StarsEx/WndProc.cpp | 2 +- StarsEx/WndProc.h | 2 +- Starserver/Main.cpp | 2 +- Starserver/NetAdminChat.cpp | 2 +- Starserver/NetAdminChat.h | 2 +- Starserver/NetAdminServer.cpp | 2 +- Starserver/NetAdminServer.h | 2 +- Starserver/NetFileServlet.cpp | 2 +- Starserver/NetFileServlet.h | 2 +- Starserver/StarServer.cpp | 2 +- Starserver/StarServer.h | 2 +- Starshatter/Main.cpp | 2 +- contrib/CMakeLists.txt | 30 - contrib/Opcode/CMakeLists.txt | 55 -- contrib/Opcode/Doc/OpcodeUserManual.pdf | Bin 39653 -> 0 bytes contrib/Opcode/Ice/IceAABB.cpp | 405 ----------- contrib/Opcode/Ice/IceAABB.h | 505 -------------- contrib/Opcode/Ice/IceAxes.h | 54 -- contrib/Opcode/Ice/IceBoundingSphere.h | 142 ---- contrib/Opcode/Ice/IceContainer.cpp | 357 ---------- contrib/Opcode/Ice/IceContainer.h | 212 ------ contrib/Opcode/Ice/IceFPU.h | 237 ------- contrib/Opcode/Ice/IceHPoint.cpp | 70 -- contrib/Opcode/Ice/IceHPoint.h | 157 ----- contrib/Opcode/Ice/IceIndexedTriangle.cpp | 548 --------------- contrib/Opcode/Ice/IceIndexedTriangle.h | 64 -- contrib/Opcode/Ice/IceLSS.h | 75 -- contrib/Opcode/Ice/IceMatrix3x3.cpp | 48 -- contrib/Opcode/Ice/IceMatrix3x3.h | 496 -------------- contrib/Opcode/Ice/IceMatrix4x4.cpp | 135 ---- contrib/Opcode/Ice/IceMatrix4x4.h | 455 ------------- contrib/Opcode/Ice/IceMemoryMacros.h | 89 --- contrib/Opcode/Ice/IceOBB.cpp | 323 --------- contrib/Opcode/Ice/IceOBB.h | 177 ----- contrib/Opcode/Ice/IcePairs.h | 45 -- contrib/Opcode/Ice/IcePlane.cpp | 45 -- contrib/Opcode/Ice/IcePlane.h | 113 --- contrib/Opcode/Ice/IcePoint.cpp | 193 ------ contrib/Opcode/Ice/IcePoint.h | 528 -------------- contrib/Opcode/Ice/IcePreprocessor.h | 132 ---- contrib/Opcode/Ice/IceRandom.cpp | 35 - contrib/Opcode/Ice/IceRandom.h | 42 -- contrib/Opcode/Ice/IceRay.cpp | 84 --- contrib/Opcode/Ice/IceRay.h | 98 --- contrib/Opcode/Ice/IceRevisitedRadix.cpp | 520 -------------- contrib/Opcode/Ice/IceRevisitedRadix.h | 65 -- contrib/Opcode/Ice/IceSegment.cpp | 57 -- contrib/Opcode/Ice/IceSegment.h | 55 -- contrib/Opcode/Ice/IceTriangle.cpp | 286 -------- contrib/Opcode/Ice/IceTriangle.h | 68 -- contrib/Opcode/Ice/IceTrilist.h | 61 -- contrib/Opcode/Ice/IceTypes.h | 164 ----- contrib/Opcode/Ice/IceUtils.cpp | 39 -- contrib/Opcode/Ice/IceUtils.h | 256 ------- contrib/Opcode/OPC_AABBCollider.cpp | 696 ------------------- contrib/Opcode/OPC_AABBCollider.h | 97 --- contrib/Opcode/OPC_AABBTree.cpp | 573 ---------------- contrib/Opcode/OPC_AABBTree.h | 137 ---- contrib/Opcode/OPC_BaseModel.cpp | 138 ---- contrib/Opcode/OPC_BaseModel.h | 175 ----- contrib/Opcode/OPC_BoxBoxOverlap.h | 122 ---- contrib/Opcode/OPC_BoxPruning.cpp | 367 ---------- contrib/Opcode/OPC_BoxPruning.h | 31 - contrib/Opcode/OPC_Collider.cpp | 54 -- contrib/Opcode/OPC_Collider.h | 176 ----- contrib/Opcode/OPC_Common.cpp | 48 -- contrib/Opcode/OPC_Common.h | 101 --- contrib/Opcode/OPC_HybridModel.cpp | 466 ------------- contrib/Opcode/OPC_HybridModel.h | 106 --- contrib/Opcode/OPC_IceHook.h | 70 -- contrib/Opcode/OPC_LSSAABBOverlap.h | 523 -------------- contrib/Opcode/OPC_LSSCollider.cpp | 725 -------------------- contrib/Opcode/OPC_LSSCollider.h | 99 --- contrib/Opcode/OPC_LSSTriOverlap.h | 679 ------------------- contrib/Opcode/OPC_MeshInterface.cpp | 299 -------- contrib/Opcode/OPC_MeshInterface.h | 182 ----- contrib/Opcode/OPC_Model.cpp | 222 ------ contrib/Opcode/OPC_Model.h | 65 -- contrib/Opcode/OPC_OBBCollider.cpp | 767 --------------------- contrib/Opcode/OPC_OBBCollider.h | 142 ---- contrib/Opcode/OPC_OptimizedTree.cpp | 782 --------------------- contrib/Opcode/OPC_OptimizedTree.h | 206 ------ contrib/Opcode/OPC_Picking.cpp | 182 ----- contrib/Opcode/OPC_Picking.h | 45 -- contrib/Opcode/OPC_PlanesAABBOverlap.h | 50 -- contrib/Opcode/OPC_PlanesCollider.cpp | 653 ------------------ contrib/Opcode/OPC_PlanesCollider.h | 121 ---- contrib/Opcode/OPC_PlanesTriOverlap.h | 40 -- contrib/Opcode/OPC_RayAABBOverlap.h | 63 -- contrib/Opcode/OPC_RayCollider.cpp | 762 --------------------- contrib/Opcode/OPC_RayCollider.h | 225 ------ contrib/Opcode/OPC_RayTriOverlap.h | 89 --- contrib/Opcode/OPC_Settings.h | 49 -- contrib/Opcode/OPC_SphereAABBOverlap.h | 128 ---- contrib/Opcode/OPC_SphereCollider.cpp | 726 -------------------- contrib/Opcode/OPC_SphereCollider.h | 96 --- contrib/Opcode/OPC_SphereTriOverlap.h | 187 ----- contrib/Opcode/OPC_SweepAndPrune.cpp | 664 ------------------ contrib/Opcode/OPC_SweepAndPrune.h | 86 --- contrib/Opcode/OPC_TreeBuilders.cpp | 255 ------- contrib/Opcode/OPC_TreeBuilders.h | 173 ----- contrib/Opcode/OPC_TreeCollider.cpp | 943 -------------------------- contrib/Opcode/OPC_TreeCollider.h | 244 ------- contrib/Opcode/OPC_TriBoxOverlap.h | 339 --------- contrib/Opcode/OPC_TriTriOverlap.h | 279 -------- contrib/Opcode/OPC_VolumeCollider.cpp | 103 --- contrib/Opcode/OPC_VolumeCollider.h | 138 ---- contrib/Opcode/Opcode.cpp | 65 -- contrib/Opcode/Opcode.h | 72 -- contrib/Opcode/ReadMe.txt | 171 ----- contrib/Opcode/StdAfx.cpp | 10 - contrib/Opcode/StdAfx.h | 24 - contrib/Opcode/TemporalCoherence.txt | 32 - contrib/gtest/CMakeLists.txt | 7 - contrib/infoware/1.current.patch | 30 - contrib/infoware/CMakeLists.txt | 6 - contrib/libpng/1.zlib.patch | 41 -- contrib/libpng/2.export.patch | 16 - contrib/libpng/3.includes.patch | 37 - contrib/libpng/4.aliases.patch | 19 - contrib/libpng/CMakeLists.txt | 11 - contrib/libpng/LICENSE | 111 --- contrib/ogg/1.cmake.patch | 111 --- contrib/ogg/CMakeLists.txt | 8 - contrib/sha1/CMakeLists.txt | 6 - contrib/sha1/Sha1.cpp | 589 ---------------- contrib/sha1/include/Sha1.h | 89 --- contrib/vorbis/1.cmake.patch | 176 ----- contrib/vorbis/CMakeLists.txt | 8 - contrib/zlib/1.zconf.patch | 560 --------------- contrib/zlib/2.includes.patch | 28 - contrib/zlib/3.aliases.patch | 12 - contrib/zlib/4.examples.patch | 29 - contrib/zlib/CMakeLists.txt | 9 - contrib/zlib/LICENSE | 27 - third-party/CMakeLists.txt | 30 + third-party/Opcode/CMakeLists.txt | 55 ++ third-party/Opcode/Doc/OpcodeUserManual.pdf | Bin 0 -> 39653 bytes third-party/Opcode/Ice/IceAABB.cpp | 405 +++++++++++ third-party/Opcode/Ice/IceAABB.h | 505 ++++++++++++++ third-party/Opcode/Ice/IceAxes.h | 54 ++ third-party/Opcode/Ice/IceBoundingSphere.h | 142 ++++ third-party/Opcode/Ice/IceContainer.cpp | 357 ++++++++++ third-party/Opcode/Ice/IceContainer.h | 212 ++++++ third-party/Opcode/Ice/IceFPU.h | 237 +++++++ third-party/Opcode/Ice/IceHPoint.cpp | 70 ++ third-party/Opcode/Ice/IceHPoint.h | 157 +++++ third-party/Opcode/Ice/IceIndexedTriangle.cpp | 548 +++++++++++++++ third-party/Opcode/Ice/IceIndexedTriangle.h | 64 ++ third-party/Opcode/Ice/IceLSS.h | 75 ++ third-party/Opcode/Ice/IceMatrix3x3.cpp | 48 ++ third-party/Opcode/Ice/IceMatrix3x3.h | 496 ++++++++++++++ third-party/Opcode/Ice/IceMatrix4x4.cpp | 135 ++++ third-party/Opcode/Ice/IceMatrix4x4.h | 455 +++++++++++++ third-party/Opcode/Ice/IceMemoryMacros.h | 89 +++ third-party/Opcode/Ice/IceOBB.cpp | 323 +++++++++ third-party/Opcode/Ice/IceOBB.h | 177 +++++ third-party/Opcode/Ice/IcePairs.h | 45 ++ third-party/Opcode/Ice/IcePlane.cpp | 45 ++ third-party/Opcode/Ice/IcePlane.h | 113 +++ third-party/Opcode/Ice/IcePoint.cpp | 193 ++++++ third-party/Opcode/Ice/IcePoint.h | 528 ++++++++++++++ third-party/Opcode/Ice/IcePreprocessor.h | 132 ++++ third-party/Opcode/Ice/IceRandom.cpp | 35 + third-party/Opcode/Ice/IceRandom.h | 42 ++ third-party/Opcode/Ice/IceRay.cpp | 84 +++ third-party/Opcode/Ice/IceRay.h | 98 +++ third-party/Opcode/Ice/IceRevisitedRadix.cpp | 520 ++++++++++++++ third-party/Opcode/Ice/IceRevisitedRadix.h | 65 ++ third-party/Opcode/Ice/IceSegment.cpp | 57 ++ third-party/Opcode/Ice/IceSegment.h | 55 ++ third-party/Opcode/Ice/IceTriangle.cpp | 286 ++++++++ third-party/Opcode/Ice/IceTriangle.h | 68 ++ third-party/Opcode/Ice/IceTrilist.h | 61 ++ third-party/Opcode/Ice/IceTypes.h | 164 +++++ third-party/Opcode/Ice/IceUtils.cpp | 39 ++ third-party/Opcode/Ice/IceUtils.h | 256 +++++++ third-party/Opcode/OPC_AABBCollider.cpp | 696 +++++++++++++++++++ third-party/Opcode/OPC_AABBCollider.h | 97 +++ third-party/Opcode/OPC_AABBTree.cpp | 573 ++++++++++++++++ third-party/Opcode/OPC_AABBTree.h | 137 ++++ third-party/Opcode/OPC_BaseModel.cpp | 138 ++++ third-party/Opcode/OPC_BaseModel.h | 175 +++++ third-party/Opcode/OPC_BoxBoxOverlap.h | 122 ++++ third-party/Opcode/OPC_BoxPruning.cpp | 367 ++++++++++ third-party/Opcode/OPC_BoxPruning.h | 31 + third-party/Opcode/OPC_Collider.cpp | 54 ++ third-party/Opcode/OPC_Collider.h | 176 +++++ third-party/Opcode/OPC_Common.cpp | 48 ++ third-party/Opcode/OPC_Common.h | 101 +++ third-party/Opcode/OPC_HybridModel.cpp | 466 +++++++++++++ third-party/Opcode/OPC_HybridModel.h | 106 +++ third-party/Opcode/OPC_IceHook.h | 70 ++ third-party/Opcode/OPC_LSSAABBOverlap.h | 523 ++++++++++++++ third-party/Opcode/OPC_LSSCollider.cpp | 725 ++++++++++++++++++++ third-party/Opcode/OPC_LSSCollider.h | 99 +++ third-party/Opcode/OPC_LSSTriOverlap.h | 679 +++++++++++++++++++ third-party/Opcode/OPC_MeshInterface.cpp | 299 ++++++++ third-party/Opcode/OPC_MeshInterface.h | 182 +++++ third-party/Opcode/OPC_Model.cpp | 222 ++++++ third-party/Opcode/OPC_Model.h | 65 ++ third-party/Opcode/OPC_OBBCollider.cpp | 767 +++++++++++++++++++++ third-party/Opcode/OPC_OBBCollider.h | 142 ++++ third-party/Opcode/OPC_OptimizedTree.cpp | 782 +++++++++++++++++++++ third-party/Opcode/OPC_OptimizedTree.h | 206 ++++++ third-party/Opcode/OPC_Picking.cpp | 182 +++++ third-party/Opcode/OPC_Picking.h | 45 ++ third-party/Opcode/OPC_PlanesAABBOverlap.h | 50 ++ third-party/Opcode/OPC_PlanesCollider.cpp | 653 ++++++++++++++++++ third-party/Opcode/OPC_PlanesCollider.h | 121 ++++ third-party/Opcode/OPC_PlanesTriOverlap.h | 40 ++ third-party/Opcode/OPC_RayAABBOverlap.h | 63 ++ third-party/Opcode/OPC_RayCollider.cpp | 762 +++++++++++++++++++++ third-party/Opcode/OPC_RayCollider.h | 225 ++++++ third-party/Opcode/OPC_RayTriOverlap.h | 89 +++ third-party/Opcode/OPC_Settings.h | 49 ++ third-party/Opcode/OPC_SphereAABBOverlap.h | 128 ++++ third-party/Opcode/OPC_SphereCollider.cpp | 726 ++++++++++++++++++++ third-party/Opcode/OPC_SphereCollider.h | 96 +++ third-party/Opcode/OPC_SphereTriOverlap.h | 187 +++++ third-party/Opcode/OPC_SweepAndPrune.cpp | 664 ++++++++++++++++++ third-party/Opcode/OPC_SweepAndPrune.h | 86 +++ third-party/Opcode/OPC_TreeBuilders.cpp | 255 +++++++ third-party/Opcode/OPC_TreeBuilders.h | 173 +++++ third-party/Opcode/OPC_TreeCollider.cpp | 943 ++++++++++++++++++++++++++ third-party/Opcode/OPC_TreeCollider.h | 244 +++++++ third-party/Opcode/OPC_TriBoxOverlap.h | 339 +++++++++ third-party/Opcode/OPC_TriTriOverlap.h | 279 ++++++++ third-party/Opcode/OPC_VolumeCollider.cpp | 103 +++ third-party/Opcode/OPC_VolumeCollider.h | 138 ++++ third-party/Opcode/Opcode.cpp | 65 ++ third-party/Opcode/Opcode.h | 72 ++ third-party/Opcode/ReadMe.txt | 171 +++++ third-party/Opcode/StdAfx.cpp | 10 + third-party/Opcode/StdAfx.h | 24 + third-party/Opcode/TemporalCoherence.txt | 32 + third-party/gtest/CMakeLists.txt | 7 + third-party/gtest/LICENSE | 28 + third-party/infoware/1.current.patch | 30 + third-party/infoware/CMakeLists.txt | 6 + third-party/infoware/LICENSE | 116 ++++ third-party/libpng/1.zlib.patch | 41 ++ third-party/libpng/2.export.patch | 16 + third-party/libpng/3.includes.patch | 37 + third-party/libpng/4.aliases.patch | 19 + third-party/libpng/CMakeLists.txt | 11 + third-party/libpng/LICENSE | 111 +++ third-party/ogg/1.cmake.patch | 111 +++ third-party/ogg/CMakeLists.txt | 8 + third-party/ogg/COPYING | 28 + third-party/sha1/CMakeLists.txt | 6 + third-party/sha1/Sha1.cpp | 589 ++++++++++++++++ third-party/sha1/include/Sha1.h | 89 +++ third-party/vorbis/1.cmake.patch | 176 +++++ third-party/vorbis/CMakeLists.txt | 8 + third-party/vorbis/COPYING | 28 + third-party/zlib/1.zconf.patch | 560 +++++++++++++++ third-party/zlib/2.includes.patch | 28 + third-party/zlib/3.aliases.patch | 12 + third-party/zlib/4.examples.patch | 29 + third-party/zlib/CMakeLists.txt | 9 + third-party/zlib/LICENSE | 27 + 854 files changed, 25340 insertions(+), 25127 deletions(-) delete mode 100644 contrib/CMakeLists.txt delete mode 100644 contrib/Opcode/CMakeLists.txt delete mode 100644 contrib/Opcode/Doc/OpcodeUserManual.pdf delete mode 100644 contrib/Opcode/Ice/IceAABB.cpp delete mode 100644 contrib/Opcode/Ice/IceAABB.h delete mode 100644 contrib/Opcode/Ice/IceAxes.h delete mode 100644 contrib/Opcode/Ice/IceBoundingSphere.h delete mode 100644 contrib/Opcode/Ice/IceContainer.cpp delete mode 100644 contrib/Opcode/Ice/IceContainer.h delete mode 100644 contrib/Opcode/Ice/IceFPU.h delete mode 100644 contrib/Opcode/Ice/IceHPoint.cpp delete mode 100644 contrib/Opcode/Ice/IceHPoint.h delete mode 100644 contrib/Opcode/Ice/IceIndexedTriangle.cpp delete mode 100644 contrib/Opcode/Ice/IceIndexedTriangle.h delete mode 100644 contrib/Opcode/Ice/IceLSS.h delete mode 100644 contrib/Opcode/Ice/IceMatrix3x3.cpp delete mode 100644 contrib/Opcode/Ice/IceMatrix3x3.h delete mode 100644 contrib/Opcode/Ice/IceMatrix4x4.cpp delete mode 100644 contrib/Opcode/Ice/IceMatrix4x4.h delete mode 100644 contrib/Opcode/Ice/IceMemoryMacros.h delete mode 100644 contrib/Opcode/Ice/IceOBB.cpp delete mode 100644 contrib/Opcode/Ice/IceOBB.h delete mode 100644 contrib/Opcode/Ice/IcePairs.h delete mode 100644 contrib/Opcode/Ice/IcePlane.cpp delete mode 100644 contrib/Opcode/Ice/IcePlane.h delete mode 100644 contrib/Opcode/Ice/IcePoint.cpp delete mode 100644 contrib/Opcode/Ice/IcePoint.h delete mode 100644 contrib/Opcode/Ice/IcePreprocessor.h delete mode 100644 contrib/Opcode/Ice/IceRandom.cpp delete mode 100644 contrib/Opcode/Ice/IceRandom.h delete mode 100644 contrib/Opcode/Ice/IceRay.cpp delete mode 100644 contrib/Opcode/Ice/IceRay.h delete mode 100644 contrib/Opcode/Ice/IceRevisitedRadix.cpp delete mode 100644 contrib/Opcode/Ice/IceRevisitedRadix.h delete mode 100644 contrib/Opcode/Ice/IceSegment.cpp delete mode 100644 contrib/Opcode/Ice/IceSegment.h delete mode 100644 contrib/Opcode/Ice/IceTriangle.cpp delete mode 100644 contrib/Opcode/Ice/IceTriangle.h delete mode 100644 contrib/Opcode/Ice/IceTrilist.h delete mode 100644 contrib/Opcode/Ice/IceTypes.h delete mode 100644 contrib/Opcode/Ice/IceUtils.cpp delete mode 100644 contrib/Opcode/Ice/IceUtils.h delete mode 100644 contrib/Opcode/OPC_AABBCollider.cpp delete mode 100644 contrib/Opcode/OPC_AABBCollider.h delete mode 100644 contrib/Opcode/OPC_AABBTree.cpp delete mode 100644 contrib/Opcode/OPC_AABBTree.h delete mode 100644 contrib/Opcode/OPC_BaseModel.cpp delete mode 100644 contrib/Opcode/OPC_BaseModel.h delete mode 100644 contrib/Opcode/OPC_BoxBoxOverlap.h delete mode 100644 contrib/Opcode/OPC_BoxPruning.cpp delete mode 100644 contrib/Opcode/OPC_BoxPruning.h delete mode 100644 contrib/Opcode/OPC_Collider.cpp delete mode 100644 contrib/Opcode/OPC_Collider.h delete mode 100644 contrib/Opcode/OPC_Common.cpp delete mode 100644 contrib/Opcode/OPC_Common.h delete mode 100644 contrib/Opcode/OPC_HybridModel.cpp delete mode 100644 contrib/Opcode/OPC_HybridModel.h delete mode 100644 contrib/Opcode/OPC_IceHook.h delete mode 100644 contrib/Opcode/OPC_LSSAABBOverlap.h delete mode 100644 contrib/Opcode/OPC_LSSCollider.cpp delete mode 100644 contrib/Opcode/OPC_LSSCollider.h delete mode 100644 contrib/Opcode/OPC_LSSTriOverlap.h delete mode 100644 contrib/Opcode/OPC_MeshInterface.cpp delete mode 100644 contrib/Opcode/OPC_MeshInterface.h delete mode 100644 contrib/Opcode/OPC_Model.cpp delete mode 100644 contrib/Opcode/OPC_Model.h delete mode 100644 contrib/Opcode/OPC_OBBCollider.cpp delete mode 100644 contrib/Opcode/OPC_OBBCollider.h delete mode 100644 contrib/Opcode/OPC_OptimizedTree.cpp delete mode 100644 contrib/Opcode/OPC_OptimizedTree.h delete mode 100644 contrib/Opcode/OPC_Picking.cpp delete mode 100644 contrib/Opcode/OPC_Picking.h delete mode 100644 contrib/Opcode/OPC_PlanesAABBOverlap.h delete mode 100644 contrib/Opcode/OPC_PlanesCollider.cpp delete mode 100644 contrib/Opcode/OPC_PlanesCollider.h delete mode 100644 contrib/Opcode/OPC_PlanesTriOverlap.h delete mode 100644 contrib/Opcode/OPC_RayAABBOverlap.h delete mode 100644 contrib/Opcode/OPC_RayCollider.cpp delete mode 100644 contrib/Opcode/OPC_RayCollider.h delete mode 100644 contrib/Opcode/OPC_RayTriOverlap.h delete mode 100644 contrib/Opcode/OPC_Settings.h delete mode 100644 contrib/Opcode/OPC_SphereAABBOverlap.h delete mode 100644 contrib/Opcode/OPC_SphereCollider.cpp delete mode 100644 contrib/Opcode/OPC_SphereCollider.h delete mode 100644 contrib/Opcode/OPC_SphereTriOverlap.h delete mode 100644 contrib/Opcode/OPC_SweepAndPrune.cpp delete mode 100644 contrib/Opcode/OPC_SweepAndPrune.h delete mode 100644 contrib/Opcode/OPC_TreeBuilders.cpp delete mode 100644 contrib/Opcode/OPC_TreeBuilders.h delete mode 100644 contrib/Opcode/OPC_TreeCollider.cpp delete mode 100644 contrib/Opcode/OPC_TreeCollider.h delete mode 100644 contrib/Opcode/OPC_TriBoxOverlap.h delete mode 100644 contrib/Opcode/OPC_TriTriOverlap.h delete mode 100644 contrib/Opcode/OPC_VolumeCollider.cpp delete mode 100644 contrib/Opcode/OPC_VolumeCollider.h delete mode 100644 contrib/Opcode/Opcode.cpp delete mode 100644 contrib/Opcode/Opcode.h delete mode 100644 contrib/Opcode/ReadMe.txt delete mode 100644 contrib/Opcode/StdAfx.cpp delete mode 100644 contrib/Opcode/StdAfx.h delete mode 100644 contrib/Opcode/TemporalCoherence.txt delete mode 100644 contrib/gtest/CMakeLists.txt delete mode 100644 contrib/infoware/1.current.patch delete mode 100644 contrib/infoware/CMakeLists.txt delete mode 100644 contrib/libpng/1.zlib.patch delete mode 100644 contrib/libpng/2.export.patch delete mode 100644 contrib/libpng/3.includes.patch delete mode 100644 contrib/libpng/4.aliases.patch delete mode 100644 contrib/libpng/CMakeLists.txt delete mode 100644 contrib/libpng/LICENSE delete mode 100644 contrib/ogg/1.cmake.patch delete mode 100644 contrib/ogg/CMakeLists.txt delete mode 100644 contrib/sha1/CMakeLists.txt delete mode 100644 contrib/sha1/Sha1.cpp delete mode 100644 contrib/sha1/include/Sha1.h delete mode 100644 contrib/vorbis/1.cmake.patch delete mode 100644 contrib/vorbis/CMakeLists.txt delete mode 100644 contrib/zlib/1.zconf.patch delete mode 100644 contrib/zlib/2.includes.patch delete mode 100644 contrib/zlib/3.aliases.patch delete mode 100644 contrib/zlib/4.examples.patch delete mode 100644 contrib/zlib/CMakeLists.txt delete mode 100644 contrib/zlib/LICENSE create mode 100644 third-party/CMakeLists.txt create mode 100644 third-party/Opcode/CMakeLists.txt create mode 100644 third-party/Opcode/Doc/OpcodeUserManual.pdf create mode 100644 third-party/Opcode/Ice/IceAABB.cpp create mode 100644 third-party/Opcode/Ice/IceAABB.h create mode 100644 third-party/Opcode/Ice/IceAxes.h create mode 100644 third-party/Opcode/Ice/IceBoundingSphere.h create mode 100644 third-party/Opcode/Ice/IceContainer.cpp create mode 100644 third-party/Opcode/Ice/IceContainer.h create mode 100644 third-party/Opcode/Ice/IceFPU.h create mode 100644 third-party/Opcode/Ice/IceHPoint.cpp create mode 100644 third-party/Opcode/Ice/IceHPoint.h create mode 100644 third-party/Opcode/Ice/IceIndexedTriangle.cpp create mode 100644 third-party/Opcode/Ice/IceIndexedTriangle.h create mode 100644 third-party/Opcode/Ice/IceLSS.h create mode 100644 third-party/Opcode/Ice/IceMatrix3x3.cpp create mode 100644 third-party/Opcode/Ice/IceMatrix3x3.h create mode 100644 third-party/Opcode/Ice/IceMatrix4x4.cpp create mode 100644 third-party/Opcode/Ice/IceMatrix4x4.h create mode 100644 third-party/Opcode/Ice/IceMemoryMacros.h create mode 100644 third-party/Opcode/Ice/IceOBB.cpp create mode 100644 third-party/Opcode/Ice/IceOBB.h create mode 100644 third-party/Opcode/Ice/IcePairs.h create mode 100644 third-party/Opcode/Ice/IcePlane.cpp create mode 100644 third-party/Opcode/Ice/IcePlane.h create mode 100644 third-party/Opcode/Ice/IcePoint.cpp create mode 100644 third-party/Opcode/Ice/IcePoint.h create mode 100644 third-party/Opcode/Ice/IcePreprocessor.h create mode 100644 third-party/Opcode/Ice/IceRandom.cpp create mode 100644 third-party/Opcode/Ice/IceRandom.h create mode 100644 third-party/Opcode/Ice/IceRay.cpp create mode 100644 third-party/Opcode/Ice/IceRay.h create mode 100644 third-party/Opcode/Ice/IceRevisitedRadix.cpp create mode 100644 third-party/Opcode/Ice/IceRevisitedRadix.h create mode 100644 third-party/Opcode/Ice/IceSegment.cpp create mode 100644 third-party/Opcode/Ice/IceSegment.h create mode 100644 third-party/Opcode/Ice/IceTriangle.cpp create mode 100644 third-party/Opcode/Ice/IceTriangle.h create mode 100644 third-party/Opcode/Ice/IceTrilist.h create mode 100644 third-party/Opcode/Ice/IceTypes.h create mode 100644 third-party/Opcode/Ice/IceUtils.cpp create mode 100644 third-party/Opcode/Ice/IceUtils.h create mode 100644 third-party/Opcode/OPC_AABBCollider.cpp create mode 100644 third-party/Opcode/OPC_AABBCollider.h create mode 100644 third-party/Opcode/OPC_AABBTree.cpp create mode 100644 third-party/Opcode/OPC_AABBTree.h create mode 100644 third-party/Opcode/OPC_BaseModel.cpp create mode 100644 third-party/Opcode/OPC_BaseModel.h create mode 100644 third-party/Opcode/OPC_BoxBoxOverlap.h create mode 100644 third-party/Opcode/OPC_BoxPruning.cpp create mode 100644 third-party/Opcode/OPC_BoxPruning.h create mode 100644 third-party/Opcode/OPC_Collider.cpp create mode 100644 third-party/Opcode/OPC_Collider.h create mode 100644 third-party/Opcode/OPC_Common.cpp create mode 100644 third-party/Opcode/OPC_Common.h create mode 100644 third-party/Opcode/OPC_HybridModel.cpp create mode 100644 third-party/Opcode/OPC_HybridModel.h create mode 100644 third-party/Opcode/OPC_IceHook.h create mode 100644 third-party/Opcode/OPC_LSSAABBOverlap.h create mode 100644 third-party/Opcode/OPC_LSSCollider.cpp create mode 100644 third-party/Opcode/OPC_LSSCollider.h create mode 100644 third-party/Opcode/OPC_LSSTriOverlap.h create mode 100644 third-party/Opcode/OPC_MeshInterface.cpp create mode 100644 third-party/Opcode/OPC_MeshInterface.h create mode 100644 third-party/Opcode/OPC_Model.cpp create mode 100644 third-party/Opcode/OPC_Model.h create mode 100644 third-party/Opcode/OPC_OBBCollider.cpp create mode 100644 third-party/Opcode/OPC_OBBCollider.h create mode 100644 third-party/Opcode/OPC_OptimizedTree.cpp create mode 100644 third-party/Opcode/OPC_OptimizedTree.h create mode 100644 third-party/Opcode/OPC_Picking.cpp create mode 100644 third-party/Opcode/OPC_Picking.h create mode 100644 third-party/Opcode/OPC_PlanesAABBOverlap.h create mode 100644 third-party/Opcode/OPC_PlanesCollider.cpp create mode 100644 third-party/Opcode/OPC_PlanesCollider.h create mode 100644 third-party/Opcode/OPC_PlanesTriOverlap.h create mode 100644 third-party/Opcode/OPC_RayAABBOverlap.h create mode 100644 third-party/Opcode/OPC_RayCollider.cpp create mode 100644 third-party/Opcode/OPC_RayCollider.h create mode 100644 third-party/Opcode/OPC_RayTriOverlap.h create mode 100644 third-party/Opcode/OPC_Settings.h create mode 100644 third-party/Opcode/OPC_SphereAABBOverlap.h create mode 100644 third-party/Opcode/OPC_SphereCollider.cpp create mode 100644 third-party/Opcode/OPC_SphereCollider.h create mode 100644 third-party/Opcode/OPC_SphereTriOverlap.h create mode 100644 third-party/Opcode/OPC_SweepAndPrune.cpp create mode 100644 third-party/Opcode/OPC_SweepAndPrune.h create mode 100644 third-party/Opcode/OPC_TreeBuilders.cpp create mode 100644 third-party/Opcode/OPC_TreeBuilders.h create mode 100644 third-party/Opcode/OPC_TreeCollider.cpp create mode 100644 third-party/Opcode/OPC_TreeCollider.h create mode 100644 third-party/Opcode/OPC_TriBoxOverlap.h create mode 100644 third-party/Opcode/OPC_TriTriOverlap.h create mode 100644 third-party/Opcode/OPC_VolumeCollider.cpp create mode 100644 third-party/Opcode/OPC_VolumeCollider.h create mode 100644 third-party/Opcode/Opcode.cpp create mode 100644 third-party/Opcode/Opcode.h create mode 100644 third-party/Opcode/ReadMe.txt create mode 100644 third-party/Opcode/StdAfx.cpp create mode 100644 third-party/Opcode/StdAfx.h create mode 100644 third-party/Opcode/TemporalCoherence.txt create mode 100644 third-party/gtest/CMakeLists.txt create mode 100644 third-party/gtest/LICENSE create mode 100644 third-party/infoware/1.current.patch create mode 100644 third-party/infoware/CMakeLists.txt create mode 100644 third-party/infoware/LICENSE create mode 100644 third-party/libpng/1.zlib.patch create mode 100644 third-party/libpng/2.export.patch create mode 100644 third-party/libpng/3.includes.patch create mode 100644 third-party/libpng/4.aliases.patch create mode 100644 third-party/libpng/CMakeLists.txt create mode 100644 third-party/libpng/LICENSE create mode 100644 third-party/ogg/1.cmake.patch create mode 100644 third-party/ogg/CMakeLists.txt create mode 100644 third-party/ogg/COPYING create mode 100644 third-party/sha1/CMakeLists.txt create mode 100644 third-party/sha1/Sha1.cpp create mode 100644 third-party/sha1/include/Sha1.h create mode 100644 third-party/vorbis/1.cmake.patch create mode 100644 third-party/vorbis/CMakeLists.txt create mode 100644 third-party/vorbis/COPYING create mode 100644 third-party/zlib/1.zconf.patch create mode 100644 third-party/zlib/2.includes.patch create mode 100644 third-party/zlib/3.aliases.patch create mode 100644 third-party/zlib/4.examples.patch create mode 100644 third-party/zlib/CMakeLists.txt create mode 100644 third-party/zlib/LICENSE diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b3575c..0ccd32d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.24) +project(Starshatter) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS Yes) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") -project(Starshatter) enable_testing() include(AddVersionFile) include(GenerateEmulator) @@ -18,8 +18,8 @@ if(MSVC) set(WINDOWSSDK_LIBPATH "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0" CACHE FILEPATH "Path to a versioned lib directory of selected Windows SDK") set(WINDOWSSDK_PATH "C:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0" CACHE FILEPATH "Path to a versioned include directory of selected Windows SDK") endif() +add_subdirectory(third-party) add_subdirectory(ArchiveEx) -add_subdirectory(contrib) add_subdirectory(data) add_subdirectory(DefinitionEx) add_subdirectory(FoundationEx) diff --git a/COPYING b/COPYING index 0e02590..3fc0261 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ Starshatter: The Open Source Project -Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors +Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/DefinitionEx/Parser_ss.cpp b/DefinitionEx/Parser_ss.cpp index 246e4a5..1c07146 100644 --- a/DefinitionEx/Parser_ss.cpp +++ b/DefinitionEx/Parser_ss.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/DefinitionEx/Parser_ss.h b/DefinitionEx/Parser_ss.h index 7ddd256..5019f61 100644 --- a/DefinitionEx/Parser_ss.h +++ b/DefinitionEx/Parser_ss.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/DefinitionEx/Term.cpp b/DefinitionEx/Term.cpp index acd2c74..c27eb4e 100644 --- a/DefinitionEx/Term.cpp +++ b/DefinitionEx/Term.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/DefinitionEx/Term.h b/DefinitionEx/Term.h index 907dc55..f7e2b86 100644 --- a/DefinitionEx/Term.h +++ b/DefinitionEx/Term.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/DefinitionEx/Token.cpp b/DefinitionEx/Token.cpp index e61a1fb..2d060b9 100644 --- a/DefinitionEx/Token.cpp +++ b/DefinitionEx/Token.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/DefinitionEx/Token.h b/DefinitionEx/Token.h index 25ee17d..59a3414 100644 --- a/DefinitionEx/Token.h +++ b/DefinitionEx/Token.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/include/Dictionary.h b/FoundationEx/include/Dictionary.h index bcb30ed..2a8382d 100644 --- a/FoundationEx/include/Dictionary.h +++ b/FoundationEx/include/Dictionary.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/include/Dictionary.inl.h b/FoundationEx/include/Dictionary.inl.h index cd58679..09a0a4c 100644 --- a/FoundationEx/include/Dictionary.inl.h +++ b/FoundationEx/include/Dictionary.inl.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/include/List.h b/FoundationEx/include/List.h index 54dfcb1..ca55ff6 100644 --- a/FoundationEx/include/List.h +++ b/FoundationEx/include/List.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/include/List.inl.h b/FoundationEx/include/List.inl.h index 9ccb796..cf526b5 100644 --- a/FoundationEx/include/List.inl.h +++ b/FoundationEx/include/List.inl.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/include/Reader.h b/FoundationEx/include/Reader.h index ed6aebc..42d5cc0 100644 --- a/FoundationEx/include/Reader.h +++ b/FoundationEx/include/Reader.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/include/Text.h b/FoundationEx/include/Text.h index 4cf5cc4..851cadf 100644 --- a/FoundationEx/include/Text.h +++ b/FoundationEx/include/Text.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/include/Utils.h b/FoundationEx/include/Utils.h index 731bc01..80fed27 100644 --- a/FoundationEx/include/Utils.h +++ b/FoundationEx/include/Utils.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/FoundationEx/src/Reader.cpp b/FoundationEx/src/Reader.cpp index 0ca49aa..fec967e 100644 --- a/FoundationEx/src/Reader.cpp +++ b/FoundationEx/src/Reader.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/src/Text.cpp b/FoundationEx/src/Text.cpp index 1f46c2e..be03ce3 100644 --- a/FoundationEx/src/Text.cpp +++ b/FoundationEx/src/Text.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/FoundationEx/src/Utils.cpp b/FoundationEx/src/Utils.cpp index 827ecba..b93475f 100644 --- a/FoundationEx/src/Utils.cpp +++ b/FoundationEx/src/Utils.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NOTICE b/NOTICE index 46fb3fc..20af89c 100644 --- a/NOTICE +++ b/NOTICE @@ -1,14 +1,15 @@ Starshatter: The Open Source Project -Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors +Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. -This program is free software: you can redistribute it and/or modify it under the terms of the 3-Clause BSD License. -This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. +This program is free software: you can redistribute it and/or modify it +under the terms of the 3-Clause BSD License. This program is distributed +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. -You should have received a copy of the 3-Clause BSD License along with this program. If not, see - +You should have received a copy of the 3-Clause BSD License along with this +program. See . If not, see Previously published in 2011-2012 as: Starshatter OpenSource Distribution Previously published in 2006 as: Starshatter: The Gathering Storm @@ -20,32 +21,44 @@ Copyright (c) 1998-2011, Glenn Randers-Pehrson Copyright (c) 1996, 1997, Andreas Dilger Copyright (c) 1995, 1996, Guy Eric Shalnat, Group 42, Inc. libpng is released under the libpng license. -See . +See . Starshatter: The Open Source Project uses ogg: Copyright (c) 2002, Xiph.org Foundation ogg is released under the 3-Clause BSD License. -See . +See . Starshatter: The Open Source Project uses OPCODE: Copyright (c) 2001, Pierre Terdiman -OPCODE has been patched in this project to compile under Linux. +OPCODE has been patched in this project to compile under Linux and MinGW. Starshatter: The Open Source Project uses vorbis: Copyright (c) 2002-2018, Xiph.org Foundation vorbis is released under the 3-Clause BSD License. -See . +See . Starshatter: The Open Source Project uses zlib: Copyright (c) 1995-2017, Jean-loup Gailly and Mark Adler zlib is released under the zlib license. -See . +See . Starshatter: The Open Source Project uses sha1: Copyright (c) 1998, Paul E. Jones + + +Starshatter: The Open Source Project uses infoware: +Public Domain +infoware is released under CC0-1.0 license. +See . + + +Starshatter: The Open Source Project uses googletest: +Copyright 2008, Google Inc. +googletest is reeleased under BSD 3-Clause license. +See . diff --git a/NetEx/HttpClient.cpp b/NetEx/HttpClient.cpp index 642ebe3..3bd168f 100644 --- a/NetEx/HttpClient.cpp +++ b/NetEx/HttpClient.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/HttpClient.h b/NetEx/HttpClient.h index cded234..442329c 100644 --- a/NetEx/HttpClient.h +++ b/NetEx/HttpClient.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/HttpParam.cpp b/NetEx/HttpParam.cpp index 933e01a..91113e0 100644 --- a/NetEx/HttpParam.cpp +++ b/NetEx/HttpParam.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NetEx/HttpParam.h b/NetEx/HttpParam.h index 8d84296..7747315 100644 --- a/NetEx/HttpParam.h +++ b/NetEx/HttpParam.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NetEx/HttpRequest.cpp b/NetEx/HttpRequest.cpp index 12f6b1b..b947f1c 100644 --- a/NetEx/HttpRequest.cpp +++ b/NetEx/HttpRequest.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NetEx/HttpRequest.h b/NetEx/HttpRequest.h index 10bfc77..861cd2f 100644 --- a/NetEx/HttpRequest.h +++ b/NetEx/HttpRequest.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NetEx/HttpResponse.cpp b/NetEx/HttpResponse.cpp index 65b7e5d..afe190f 100644 --- a/NetEx/HttpResponse.cpp +++ b/NetEx/HttpResponse.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NetEx/HttpResponse.h b/NetEx/HttpResponse.h index cd53fcb..0b8d862 100644 --- a/NetEx/HttpResponse.h +++ b/NetEx/HttpResponse.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NetEx/HttpServer.cpp b/NetEx/HttpServer.cpp index e38612c..cc4b58d 100644 --- a/NetEx/HttpServer.cpp +++ b/NetEx/HttpServer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/HttpServer.h b/NetEx/HttpServer.h index 88c1c3c..eb7ec03 100644 --- a/NetEx/HttpServer.h +++ b/NetEx/HttpServer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/HttpServlet.cpp b/NetEx/HttpServlet.cpp index 150719c..836985b 100644 --- a/NetEx/HttpServlet.cpp +++ b/NetEx/HttpServlet.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/HttpServlet.h b/NetEx/HttpServlet.h index eb706ea..962252e 100644 --- a/NetEx/HttpServlet.h +++ b/NetEx/HttpServlet.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/HttpServletExec.cpp b/NetEx/HttpServletExec.cpp index c64df85..4371957 100644 --- a/NetEx/HttpServletExec.cpp +++ b/NetEx/HttpServletExec.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/HttpServletExec.h b/NetEx/HttpServletExec.h index 8f06d73..9ee398a 100644 --- a/NetEx/HttpServletExec.h +++ b/NetEx/HttpServletExec.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/HttpSession.cpp b/NetEx/HttpSession.cpp index 577b1e3..78f42aa 100644 --- a/NetEx/HttpSession.cpp +++ b/NetEx/HttpSession.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NetEx/HttpSession.h b/NetEx/HttpSession.h index e8d67f8..ebc09bb 100644 --- a/NetEx/HttpSession.h +++ b/NetEx/HttpSession.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/NetEx/NetAddr.cpp b/NetEx/NetAddr.cpp index 5e5468d..0262d5f 100644 --- a/NetEx/NetAddr.cpp +++ b/NetEx/NetAddr.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetAddr.h b/NetEx/NetAddr.h index 1b69c25..df6ba64 100644 --- a/NetEx/NetAddr.h +++ b/NetEx/NetAddr.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetClient.cpp b/NetEx/NetClient.cpp index 7a62160..ff02cbe 100644 --- a/NetEx/NetClient.cpp +++ b/NetEx/NetClient.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetClient.h b/NetEx/NetClient.h index db5543d..9e53d11 100644 --- a/NetEx/NetClient.h +++ b/NetEx/NetClient.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetGram.cpp b/NetEx/NetGram.cpp index 5394df2..6aebadc 100644 --- a/NetEx/NetGram.cpp +++ b/NetEx/NetGram.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetGram.h b/NetEx/NetGram.h index d7a58c9..91e1871 100644 --- a/NetEx/NetGram.h +++ b/NetEx/NetGram.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetHost.cpp b/NetEx/NetHost.cpp index 4c8c89f..00695fd 100644 --- a/NetEx/NetHost.cpp +++ b/NetEx/NetHost.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetHost.h b/NetEx/NetHost.h index c45f04c..4d2783e 100644 --- a/NetEx/NetHost.h +++ b/NetEx/NetHost.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetLayer.cpp b/NetEx/NetLayer.cpp index 5992fbe..cf0dfd0 100644 --- a/NetEx/NetLayer.cpp +++ b/NetEx/NetLayer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetLayer.h b/NetEx/NetLayer.h index 0ffb197..73e7728 100644 --- a/NetEx/NetLayer.h +++ b/NetEx/NetLayer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetLink.cpp b/NetEx/NetLink.cpp index 37ca318..0319a73 100644 --- a/NetEx/NetLink.cpp +++ b/NetEx/NetLink.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetLink.h b/NetEx/NetLink.h index 5f5d081..9266477 100644 --- a/NetEx/NetLink.h +++ b/NetEx/NetLink.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetMsg.cpp b/NetEx/NetMsg.cpp index 4e775da..407fa4f 100644 --- a/NetEx/NetMsg.cpp +++ b/NetEx/NetMsg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetMsg.h b/NetEx/NetMsg.h index 4e1cf18..fd4850c 100644 --- a/NetEx/NetMsg.h +++ b/NetEx/NetMsg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetPeer.cpp b/NetEx/NetPeer.cpp index 34adbbc..ea8217c 100644 --- a/NetEx/NetPeer.cpp +++ b/NetEx/NetPeer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetPeer.h b/NetEx/NetPeer.h index 1ce273e..2c72a77 100644 --- a/NetEx/NetPeer.h +++ b/NetEx/NetPeer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetServer.cpp b/NetEx/NetServer.cpp index 7357928..a9986be 100644 --- a/NetEx/NetServer.cpp +++ b/NetEx/NetServer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetServer.h b/NetEx/NetServer.h index 1fcc938..db2ca71 100644 --- a/NetEx/NetServer.h +++ b/NetEx/NetServer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetSock.cpp b/NetEx/NetSock.cpp index 12778b7..af4eba9 100644 --- a/NetEx/NetSock.cpp +++ b/NetEx/NetSock.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/NetEx/NetSock.h b/NetEx/NetSock.h index b483220..5bbf2ca 100644 --- a/NetEx/NetSock.h +++ b/NetEx/NetSock.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ActiveWindow.cpp b/StarsEx/ActiveWindow.cpp index e5e8e33..fbaacdd 100644 --- a/StarsEx/ActiveWindow.cpp +++ b/StarsEx/ActiveWindow.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ActiveWindow.h b/StarsEx/ActiveWindow.h index 0ad6388..a1b1b2e 100644 --- a/StarsEx/ActiveWindow.h +++ b/StarsEx/ActiveWindow.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Asteroid.cpp b/StarsEx/Asteroid.cpp index fa0f175..7212385 100644 --- a/StarsEx/Asteroid.cpp +++ b/StarsEx/Asteroid.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Asteroid.h b/StarsEx/Asteroid.h index b26b116..74b60a7 100644 --- a/StarsEx/Asteroid.h +++ b/StarsEx/Asteroid.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/AudDlg.cpp b/StarsEx/AudDlg.cpp index 829b987..625a901 100644 --- a/StarsEx/AudDlg.cpp +++ b/StarsEx/AudDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/AudDlg.h b/StarsEx/AudDlg.h index 88ed35c..a448d75 100644 --- a/StarsEx/AudDlg.h +++ b/StarsEx/AudDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/AudioConfig.cpp b/StarsEx/AudioConfig.cpp index b025c41..c8939a1 100644 --- a/StarsEx/AudioConfig.cpp +++ b/StarsEx/AudioConfig.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/AudioConfig.h b/StarsEx/AudioConfig.h index 1f01868..0f4f55a 100644 --- a/StarsEx/AudioConfig.h +++ b/StarsEx/AudioConfig.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/AwardDlg.cpp b/StarsEx/AwardDlg.cpp index e91bdc2..143659f 100644 --- a/StarsEx/AwardDlg.cpp +++ b/StarsEx/AwardDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/AwardDlg.h b/StarsEx/AwardDlg.h index 26996d5..3b0ad0f 100644 --- a/StarsEx/AwardDlg.h +++ b/StarsEx/AwardDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/AwardShowDlg.cpp b/StarsEx/AwardShowDlg.cpp index 48c292d..78487da 100644 --- a/StarsEx/AwardShowDlg.cpp +++ b/StarsEx/AwardShowDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/AwardShowDlg.h b/StarsEx/AwardShowDlg.h index d606be6..f7b8201 100644 --- a/StarsEx/AwardShowDlg.h +++ b/StarsEx/AwardShowDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/BaseScreen.h b/StarsEx/BaseScreen.h index b10dbdb..a99a89c 100644 --- a/StarsEx/BaseScreen.h +++ b/StarsEx/BaseScreen.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Bitmap.cpp b/StarsEx/Bitmap.cpp index 07c5dae..2c71e18 100644 --- a/StarsEx/Bitmap.cpp +++ b/StarsEx/Bitmap.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Bitmap.h b/StarsEx/Bitmap.h index 11eea10..b995f31 100644 --- a/StarsEx/Bitmap.h +++ b/StarsEx/Bitmap.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Bmp.cpp b/StarsEx/Bmp.cpp index 345b9eb..1b9458e 100644 --- a/StarsEx/Bmp.cpp +++ b/StarsEx/Bmp.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Bmp.h b/StarsEx/Bmp.h index 7f914b9..5b09b83 100644 --- a/StarsEx/Bmp.h +++ b/StarsEx/Bmp.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Bolt.cpp b/StarsEx/Bolt.cpp index 7483678..3f4240f 100644 --- a/StarsEx/Bolt.cpp +++ b/StarsEx/Bolt.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Bolt.h b/StarsEx/Bolt.h index 07418ac..0e5115a 100644 --- a/StarsEx/Bolt.h +++ b/StarsEx/Bolt.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Button.cpp b/StarsEx/Button.cpp index 72867e8..e48f83f 100644 --- a/StarsEx/Button.cpp +++ b/StarsEx/Button.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Button.h b/StarsEx/Button.h index 4fcaa55..045586f 100644 --- a/StarsEx/Button.h +++ b/StarsEx/Button.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Callsign.cpp b/StarsEx/Callsign.cpp index 7cb7499..8628e75 100644 --- a/StarsEx/Callsign.cpp +++ b/StarsEx/Callsign.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Callsign.h b/StarsEx/Callsign.h index 0d621ac..d71076f 100644 --- a/StarsEx/Callsign.h +++ b/StarsEx/Callsign.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Camera.cpp b/StarsEx/Camera.cpp index c8671e1..69dd95b 100644 --- a/StarsEx/Camera.cpp +++ b/StarsEx/Camera.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Camera.h b/StarsEx/Camera.h index f0988f2..c12893d 100644 --- a/StarsEx/Camera.h +++ b/StarsEx/Camera.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CameraDirector.cpp b/StarsEx/CameraDirector.cpp index 7da704c..511c76b 100644 --- a/StarsEx/CameraDirector.cpp +++ b/StarsEx/CameraDirector.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CameraDirector.h b/StarsEx/CameraDirector.h index 6cd59da..a9d170d 100644 --- a/StarsEx/CameraDirector.h +++ b/StarsEx/CameraDirector.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CameraView.cpp b/StarsEx/CameraView.cpp index 9f58dd8..599b29a 100644 --- a/StarsEx/CameraView.cpp +++ b/StarsEx/CameraView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CameraView.h b/StarsEx/CameraView.h index 4c2b357..394daf6 100644 --- a/StarsEx/CameraView.h +++ b/StarsEx/CameraView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Campaign.cpp b/StarsEx/Campaign.cpp index af1eb86..63c9e3b 100644 --- a/StarsEx/Campaign.cpp +++ b/StarsEx/Campaign.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Campaign.h b/StarsEx/Campaign.h index 1343fec..e443648 100644 --- a/StarsEx/Campaign.h +++ b/StarsEx/Campaign.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignMissionFighter.cpp b/StarsEx/CampaignMissionFighter.cpp index 1e851eb..41207eb 100644 --- a/StarsEx/CampaignMissionFighter.cpp +++ b/StarsEx/CampaignMissionFighter.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignMissionFighter.h b/StarsEx/CampaignMissionFighter.h index 997a760..71d590a 100644 --- a/StarsEx/CampaignMissionFighter.h +++ b/StarsEx/CampaignMissionFighter.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignMissionRequest.cpp b/StarsEx/CampaignMissionRequest.cpp index e8fbc68..7a145c4 100644 --- a/StarsEx/CampaignMissionRequest.cpp +++ b/StarsEx/CampaignMissionRequest.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignMissionRequest.h b/StarsEx/CampaignMissionRequest.h index 1c99b32..e48cde8 100644 --- a/StarsEx/CampaignMissionRequest.h +++ b/StarsEx/CampaignMissionRequest.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignMissionStarship.cpp b/StarsEx/CampaignMissionStarship.cpp index 2857ebb..ae86994 100644 --- a/StarsEx/CampaignMissionStarship.cpp +++ b/StarsEx/CampaignMissionStarship.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignMissionStarship.h b/StarsEx/CampaignMissionStarship.h index 5398c11..c8fa803 100644 --- a/StarsEx/CampaignMissionStarship.h +++ b/StarsEx/CampaignMissionStarship.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlan.h b/StarsEx/CampaignPlan.h index 035e589..8dd1d09 100644 --- a/StarsEx/CampaignPlan.h +++ b/StarsEx/CampaignPlan.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanAssignment.cpp b/StarsEx/CampaignPlanAssignment.cpp index c4381ed..69b0efc 100644 --- a/StarsEx/CampaignPlanAssignment.cpp +++ b/StarsEx/CampaignPlanAssignment.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanAssignment.h b/StarsEx/CampaignPlanAssignment.h index 4427fc0..3b3e699 100644 --- a/StarsEx/CampaignPlanAssignment.h +++ b/StarsEx/CampaignPlanAssignment.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanEvent.cpp b/StarsEx/CampaignPlanEvent.cpp index f487984..8010125 100644 --- a/StarsEx/CampaignPlanEvent.cpp +++ b/StarsEx/CampaignPlanEvent.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanEvent.h b/StarsEx/CampaignPlanEvent.h index 77fbae2..c6e2482 100644 --- a/StarsEx/CampaignPlanEvent.h +++ b/StarsEx/CampaignPlanEvent.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanMission.cpp b/StarsEx/CampaignPlanMission.cpp index fb8b38c..56a75f4 100644 --- a/StarsEx/CampaignPlanMission.cpp +++ b/StarsEx/CampaignPlanMission.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanMission.h b/StarsEx/CampaignPlanMission.h index 903fac5..cd3bd28 100644 --- a/StarsEx/CampaignPlanMission.h +++ b/StarsEx/CampaignPlanMission.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanMovement.cpp b/StarsEx/CampaignPlanMovement.cpp index 8d692aa..91e044a 100644 --- a/StarsEx/CampaignPlanMovement.cpp +++ b/StarsEx/CampaignPlanMovement.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanMovement.h b/StarsEx/CampaignPlanMovement.h index 4f5f0d1..45dfd19 100644 --- a/StarsEx/CampaignPlanMovement.h +++ b/StarsEx/CampaignPlanMovement.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanStrategic.cpp b/StarsEx/CampaignPlanStrategic.cpp index 209c888..cc91cc4 100644 --- a/StarsEx/CampaignPlanStrategic.cpp +++ b/StarsEx/CampaignPlanStrategic.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignPlanStrategic.h b/StarsEx/CampaignPlanStrategic.h index 6df1ba7..89b07db 100644 --- a/StarsEx/CampaignPlanStrategic.h +++ b/StarsEx/CampaignPlanStrategic.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignSaveGame.cpp b/StarsEx/CampaignSaveGame.cpp index b151dce..cc64dbf 100644 --- a/StarsEx/CampaignSaveGame.cpp +++ b/StarsEx/CampaignSaveGame.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignSaveGame.h b/StarsEx/CampaignSaveGame.h index 3f4e895..2122715 100644 --- a/StarsEx/CampaignSaveGame.h +++ b/StarsEx/CampaignSaveGame.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignSituationReport.cpp b/StarsEx/CampaignSituationReport.cpp index c83ad8d..0c4b72d 100644 --- a/StarsEx/CampaignSituationReport.cpp +++ b/StarsEx/CampaignSituationReport.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CampaignSituationReport.h b/StarsEx/CampaignSituationReport.h index f169923..4068552 100644 --- a/StarsEx/CampaignSituationReport.h +++ b/StarsEx/CampaignSituationReport.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CarrierAI.cpp b/StarsEx/CarrierAI.cpp index 92ac561..6bf759f 100644 --- a/StarsEx/CarrierAI.cpp +++ b/StarsEx/CarrierAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CarrierAI.h b/StarsEx/CarrierAI.h index cd5a732..ed99a5e 100644 --- a/StarsEx/CarrierAI.h +++ b/StarsEx/CarrierAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Clock.cpp b/StarsEx/Clock.cpp index 4a321d8..60e6f67 100644 --- a/StarsEx/Clock.cpp +++ b/StarsEx/Clock.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/Clock.h b/StarsEx/Clock.h index 238616d..40b5262 100644 --- a/StarsEx/Clock.h +++ b/StarsEx/Clock.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/Clock.inl.h b/StarsEx/Clock.inl.h index 42a2693..7a2a765 100644 --- a/StarsEx/Clock.inl.h +++ b/StarsEx/Clock.inl.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/CmdDlg.cpp b/StarsEx/CmdDlg.cpp index e84defd..e496545 100644 --- a/StarsEx/CmdDlg.cpp +++ b/StarsEx/CmdDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdDlg.h b/StarsEx/CmdDlg.h index 5bdc3d1..194a6f2 100644 --- a/StarsEx/CmdDlg.h +++ b/StarsEx/CmdDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdForceDlg.cpp b/StarsEx/CmdForceDlg.cpp index d07223e..0b6e3e6 100644 --- a/StarsEx/CmdForceDlg.cpp +++ b/StarsEx/CmdForceDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdForceDlg.h b/StarsEx/CmdForceDlg.h index 9e5e5c1..c1ad315 100644 --- a/StarsEx/CmdForceDlg.h +++ b/StarsEx/CmdForceDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdIntelDlg.cpp b/StarsEx/CmdIntelDlg.cpp index 2151cc8..fb0c83b 100644 --- a/StarsEx/CmdIntelDlg.cpp +++ b/StarsEx/CmdIntelDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdIntelDlg.h b/StarsEx/CmdIntelDlg.h index b0783c4..8ff5fe7 100644 --- a/StarsEx/CmdIntelDlg.h +++ b/StarsEx/CmdIntelDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdMissionsDlg.cpp b/StarsEx/CmdMissionsDlg.cpp index 0e5b7e1..f8d5681 100644 --- a/StarsEx/CmdMissionsDlg.cpp +++ b/StarsEx/CmdMissionsDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdMissionsDlg.h b/StarsEx/CmdMissionsDlg.h index 9098735..fb014a1 100644 --- a/StarsEx/CmdMissionsDlg.h +++ b/StarsEx/CmdMissionsDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdMsgDlg.cpp b/StarsEx/CmdMsgDlg.cpp index 81766fb..d5f1050 100644 --- a/StarsEx/CmdMsgDlg.cpp +++ b/StarsEx/CmdMsgDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdMsgDlg.h b/StarsEx/CmdMsgDlg.h index cc9e466..cc88a12 100644 --- a/StarsEx/CmdMsgDlg.h +++ b/StarsEx/CmdMsgDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdOrdersDlg.cpp b/StarsEx/CmdOrdersDlg.cpp index 8a6b212..4012506 100644 --- a/StarsEx/CmdOrdersDlg.cpp +++ b/StarsEx/CmdOrdersDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdOrdersDlg.h b/StarsEx/CmdOrdersDlg.h index 3b02cca..a935e70 100644 --- a/StarsEx/CmdOrdersDlg.h +++ b/StarsEx/CmdOrdersDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdTheaterDlg.cpp b/StarsEx/CmdTheaterDlg.cpp index 0aee3d9..cf8a09d 100644 --- a/StarsEx/CmdTheaterDlg.cpp +++ b/StarsEx/CmdTheaterDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdTheaterDlg.h b/StarsEx/CmdTheaterDlg.h index aba1057..0b4f766 100644 --- a/StarsEx/CmdTheaterDlg.h +++ b/StarsEx/CmdTheaterDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdTitleDlg.cpp b/StarsEx/CmdTitleDlg.cpp index 5626fde..58de2b3 100644 --- a/StarsEx/CmdTitleDlg.cpp +++ b/StarsEx/CmdTitleDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmdTitleDlg.h b/StarsEx/CmdTitleDlg.h index 9ab2563..262a349 100644 --- a/StarsEx/CmdTitleDlg.h +++ b/StarsEx/CmdTitleDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpCompleteDlg.cpp b/StarsEx/CmpCompleteDlg.cpp index 9047ac7..421093d 100644 --- a/StarsEx/CmpCompleteDlg.cpp +++ b/StarsEx/CmpCompleteDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpCompleteDlg.h b/StarsEx/CmpCompleteDlg.h index 95cbc07..2a5f36a 100644 --- a/StarsEx/CmpCompleteDlg.h +++ b/StarsEx/CmpCompleteDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpFileDlg.cpp b/StarsEx/CmpFileDlg.cpp index f350a71..c7aa340 100644 --- a/StarsEx/CmpFileDlg.cpp +++ b/StarsEx/CmpFileDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpFileDlg.h b/StarsEx/CmpFileDlg.h index f9f60fc..e60b727 100644 --- a/StarsEx/CmpFileDlg.h +++ b/StarsEx/CmpFileDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpLoadDlg.cpp b/StarsEx/CmpLoadDlg.cpp index 52eac31..27995d5 100644 --- a/StarsEx/CmpLoadDlg.cpp +++ b/StarsEx/CmpLoadDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpLoadDlg.h b/StarsEx/CmpLoadDlg.h index 5357a46..67fdba5 100644 --- a/StarsEx/CmpLoadDlg.h +++ b/StarsEx/CmpLoadDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpSceneDlg.cpp b/StarsEx/CmpSceneDlg.cpp index 4cedc21..866eb43 100644 --- a/StarsEx/CmpSceneDlg.cpp +++ b/StarsEx/CmpSceneDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpSceneDlg.h b/StarsEx/CmpSceneDlg.h index 70dd24d..81336d6 100644 --- a/StarsEx/CmpSceneDlg.h +++ b/StarsEx/CmpSceneDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpSelectDlg.cpp b/StarsEx/CmpSelectDlg.cpp index 3dacf6b..941c53a 100644 --- a/StarsEx/CmpSelectDlg.cpp +++ b/StarsEx/CmpSelectDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpSelectDlg.h b/StarsEx/CmpSelectDlg.h index ee52425..4772463 100644 --- a/StarsEx/CmpSelectDlg.h +++ b/StarsEx/CmpSelectDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpnScreen.cpp b/StarsEx/CmpnScreen.cpp index 7faffb6..c5cbbee 100644 --- a/StarsEx/CmpnScreen.cpp +++ b/StarsEx/CmpnScreen.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CmpnScreen.h b/StarsEx/CmpnScreen.h index 443de9e..4f72ec0 100644 --- a/StarsEx/CmpnScreen.h +++ b/StarsEx/CmpnScreen.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Color.cpp b/StarsEx/Color.cpp index 15687be..8c468dd 100644 --- a/StarsEx/Color.cpp +++ b/StarsEx/Color.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Color.h b/StarsEx/Color.h index cecdb4b..e451e91 100644 --- a/StarsEx/Color.h +++ b/StarsEx/Color.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatAction.cpp b/StarsEx/CombatAction.cpp index 2f2a748..c4ed9d0 100644 --- a/StarsEx/CombatAction.cpp +++ b/StarsEx/CombatAction.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatAction.h b/StarsEx/CombatAction.h index 4ad544d..e54f938 100644 --- a/StarsEx/CombatAction.h +++ b/StarsEx/CombatAction.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatAssignment.cpp b/StarsEx/CombatAssignment.cpp index e9d931e..d6cf1a6 100644 --- a/StarsEx/CombatAssignment.cpp +++ b/StarsEx/CombatAssignment.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatAssignment.h b/StarsEx/CombatAssignment.h index d917b28..a2d88bd 100644 --- a/StarsEx/CombatAssignment.h +++ b/StarsEx/CombatAssignment.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatEvent.cpp b/StarsEx/CombatEvent.cpp index 8c02142..c97c20b 100644 --- a/StarsEx/CombatEvent.cpp +++ b/StarsEx/CombatEvent.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatEvent.h b/StarsEx/CombatEvent.h index 94f8d8a..5c4c6ff 100644 --- a/StarsEx/CombatEvent.h +++ b/StarsEx/CombatEvent.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatGroup.cpp b/StarsEx/CombatGroup.cpp index 42976bd..57afd7b 100644 --- a/StarsEx/CombatGroup.cpp +++ b/StarsEx/CombatGroup.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatGroup.h b/StarsEx/CombatGroup.h index da34ff0..54115fb 100644 --- a/StarsEx/CombatGroup.h +++ b/StarsEx/CombatGroup.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatRoster.cpp b/StarsEx/CombatRoster.cpp index 9f552a9..c28b916 100644 --- a/StarsEx/CombatRoster.cpp +++ b/StarsEx/CombatRoster.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatRoster.h b/StarsEx/CombatRoster.h index 65b7bd2..e3817f4 100644 --- a/StarsEx/CombatRoster.h +++ b/StarsEx/CombatRoster.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatUnit.cpp b/StarsEx/CombatUnit.cpp index b7af000..599fc78 100644 --- a/StarsEx/CombatUnit.cpp +++ b/StarsEx/CombatUnit.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatUnit.h b/StarsEx/CombatUnit.h index b9e26c2..63d97b5 100644 --- a/StarsEx/CombatUnit.h +++ b/StarsEx/CombatUnit.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatZone.cpp b/StarsEx/CombatZone.cpp index 21dbcd5..cd2ad1b 100644 --- a/StarsEx/CombatZone.cpp +++ b/StarsEx/CombatZone.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CombatZone.h b/StarsEx/CombatZone.h index ff04313..53e2c20 100644 --- a/StarsEx/CombatZone.h +++ b/StarsEx/CombatZone.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Combatant.cpp b/StarsEx/Combatant.cpp index b6d8794..619bdbb 100644 --- a/StarsEx/Combatant.cpp +++ b/StarsEx/Combatant.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Combatant.h b/StarsEx/Combatant.h index cb73285..749f552 100644 --- a/StarsEx/Combatant.h +++ b/StarsEx/Combatant.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ComboBox.cpp b/StarsEx/ComboBox.cpp index cb16723..5944559 100644 --- a/StarsEx/ComboBox.cpp +++ b/StarsEx/ComboBox.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ComboBox.h b/StarsEx/ComboBox.h index a27f827..bf3a0ca 100644 --- a/StarsEx/ComboBox.h +++ b/StarsEx/ComboBox.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ComboList.cpp b/StarsEx/ComboList.cpp index 4d03809..d578606 100644 --- a/StarsEx/ComboList.cpp +++ b/StarsEx/ComboList.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ComboList.h b/StarsEx/ComboList.h index 290b328..9a4f25c 100644 --- a/StarsEx/ComboList.h +++ b/StarsEx/ComboList.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Component.cpp b/StarsEx/Component.cpp index 97e1460..14f97b7 100644 --- a/StarsEx/Component.cpp +++ b/StarsEx/Component.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Component.h b/StarsEx/Component.h index 55763c3..8ae1456 100644 --- a/StarsEx/Component.h +++ b/StarsEx/Component.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Computer.cpp b/StarsEx/Computer.cpp index 60f5ee0..ea3d2b0 100644 --- a/StarsEx/Computer.cpp +++ b/StarsEx/Computer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Computer.h b/StarsEx/Computer.h index 1117799..302aa56 100644 --- a/StarsEx/Computer.h +++ b/StarsEx/Computer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ConfirmDlg.cpp b/StarsEx/ConfirmDlg.cpp index 87a001c..a3ad6a9 100644 --- a/StarsEx/ConfirmDlg.cpp +++ b/StarsEx/ConfirmDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ConfirmDlg.h b/StarsEx/ConfirmDlg.h index d57235c..6f04ddf 100644 --- a/StarsEx/ConfirmDlg.h +++ b/StarsEx/ConfirmDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Contact.cpp b/StarsEx/Contact.cpp index 2dbec5a..ab6e753 100644 --- a/StarsEx/Contact.cpp +++ b/StarsEx/Contact.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Contact.h b/StarsEx/Contact.h index 7177e6b..66acb9c 100644 --- a/StarsEx/Contact.h +++ b/StarsEx/Contact.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ContentBundle.cpp b/StarsEx/ContentBundle.cpp index 99fee45..173b6fd 100644 --- a/StarsEx/ContentBundle.cpp +++ b/StarsEx/ContentBundle.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ContentBundle.h b/StarsEx/ContentBundle.h index da2fb0d..5b52b16 100644 --- a/StarsEx/ContentBundle.h +++ b/StarsEx/ContentBundle.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CtlDlg.cpp b/StarsEx/CtlDlg.cpp index 8aed322..7dc0f0b 100644 --- a/StarsEx/CtlDlg.cpp +++ b/StarsEx/CtlDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/CtlDlg.h b/StarsEx/CtlDlg.h index 9406b1c..ce89401 100644 --- a/StarsEx/CtlDlg.h +++ b/StarsEx/CtlDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/D3DXImage.cpp b/StarsEx/D3DXImage.cpp index 9ab9779..21b1fae 100644 --- a/StarsEx/D3DXImage.cpp +++ b/StarsEx/D3DXImage.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/D3DXImage.h b/StarsEx/D3DXImage.h index 8abc1e2..269c54a 100644 --- a/StarsEx/D3DXImage.h +++ b/StarsEx/D3DXImage.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DataLoader.cpp b/StarsEx/DataLoader.cpp index 69bdb14..695233d 100644 --- a/StarsEx/DataLoader.cpp +++ b/StarsEx/DataLoader.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DataLoader.h b/StarsEx/DataLoader.h index 13595dd..70d34df 100644 --- a/StarsEx/DataLoader.h +++ b/StarsEx/DataLoader.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DataSource.cpp b/StarsEx/DataSource.cpp index 294f4a5..485fab7 100644 --- a/StarsEx/DataSource.cpp +++ b/StarsEx/DataSource.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/DataSource.h b/StarsEx/DataSource.h index 6809a44..5a805e7 100644 --- a/StarsEx/DataSource.h +++ b/StarsEx/DataSource.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/DebriefDlg.cpp b/StarsEx/DebriefDlg.cpp index f6abdd1..1cd919b 100644 --- a/StarsEx/DebriefDlg.cpp +++ b/StarsEx/DebriefDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DebriefDlg.h b/StarsEx/DebriefDlg.h index 5636a4c..8402b79 100644 --- a/StarsEx/DebriefDlg.h +++ b/StarsEx/DebriefDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Debris.cpp b/StarsEx/Debris.cpp index 2fe1a8b..ab081d8 100644 --- a/StarsEx/Debris.cpp +++ b/StarsEx/Debris.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Debris.h b/StarsEx/Debris.h index 7c544b1..47a7f93 100644 --- a/StarsEx/Debris.h +++ b/StarsEx/Debris.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DetailSet.cpp b/StarsEx/DetailSet.cpp index 6edaec4..91de1c6 100644 --- a/StarsEx/DetailSet.cpp +++ b/StarsEx/DetailSet.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DetailSet.h b/StarsEx/DetailSet.h index 1e6887c..70226aa 100644 --- a/StarsEx/DetailSet.h +++ b/StarsEx/DetailSet.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Director.h b/StarsEx/Director.h index dbed513..895fd0c 100644 --- a/StarsEx/Director.h +++ b/StarsEx/Director.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DisplayView.cpp b/StarsEx/DisplayView.cpp index ea3ffe2..45360e1 100644 --- a/StarsEx/DisplayView.cpp +++ b/StarsEx/DisplayView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DisplayView.h b/StarsEx/DisplayView.h index a929970..c526607 100644 --- a/StarsEx/DisplayView.h +++ b/StarsEx/DisplayView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Drive.cpp b/StarsEx/Drive.cpp index bf1966c..5099666 100644 --- a/StarsEx/Drive.cpp +++ b/StarsEx/Drive.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Drive.h b/StarsEx/Drive.h index b47c10e..825ce7a 100644 --- a/StarsEx/Drive.h +++ b/StarsEx/Drive.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DriveSprite.cpp b/StarsEx/DriveSprite.cpp index 804ef4b..8c92129 100644 --- a/StarsEx/DriveSprite.cpp +++ b/StarsEx/DriveSprite.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DriveSprite.h b/StarsEx/DriveSprite.h index 76c8bfb..4c474b4 100644 --- a/StarsEx/DriveSprite.h +++ b/StarsEx/DriveSprite.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Drone.cpp b/StarsEx/Drone.cpp index e3ee920..bea91eb 100644 --- a/StarsEx/Drone.cpp +++ b/StarsEx/Drone.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Drone.h b/StarsEx/Drone.h index d6b89a1..5bb53b4 100644 --- a/StarsEx/Drone.h +++ b/StarsEx/Drone.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DropShipAI.cpp b/StarsEx/DropShipAI.cpp index bc563fc..003c959 100644 --- a/StarsEx/DropShipAI.cpp +++ b/StarsEx/DropShipAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/DropShipAI.h b/StarsEx/DropShipAI.h index 0cacffc..7af26c1 100644 --- a/StarsEx/DropShipAI.h +++ b/StarsEx/DropShipAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/EditBox.cpp b/StarsEx/EditBox.cpp index cf08a4b..0130cc3 100644 --- a/StarsEx/EditBox.cpp +++ b/StarsEx/EditBox.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/EditBox.h b/StarsEx/EditBox.h index c0ffa37..8dc37a6 100644 --- a/StarsEx/EditBox.h +++ b/StarsEx/EditBox.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Element.cpp b/StarsEx/Element.cpp index 9223cbf..23254d5 100644 --- a/StarsEx/Element.cpp +++ b/StarsEx/Element.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Element.h b/StarsEx/Element.h index ddb2c1d..8f188e4 100644 --- a/StarsEx/Element.h +++ b/StarsEx/Element.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Encrypt.cpp b/StarsEx/Encrypt.cpp index 44d07ca..80af797 100644 --- a/StarsEx/Encrypt.cpp +++ b/StarsEx/Encrypt.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Encrypt.h b/StarsEx/Encrypt.h index be925d8..3bfb2da 100644 --- a/StarsEx/Encrypt.h +++ b/StarsEx/Encrypt.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/EngDlg.cpp b/StarsEx/EngDlg.cpp index 595bbc0..88c6bf7 100644 --- a/StarsEx/EngDlg.cpp +++ b/StarsEx/EngDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/EngDlg.h b/StarsEx/EngDlg.h index ae2eedf..b336f64 100644 --- a/StarsEx/EngDlg.h +++ b/StarsEx/EngDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ExceptionHandler.cpp b/StarsEx/ExceptionHandler.cpp index d93a88f..4bd2cc6 100644 --- a/StarsEx/ExceptionHandler.cpp +++ b/StarsEx/ExceptionHandler.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ExitDlg.cpp b/StarsEx/ExitDlg.cpp index 5d42448..5ddfb29 100644 --- a/StarsEx/ExitDlg.cpp +++ b/StarsEx/ExitDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ExitDlg.h b/StarsEx/ExitDlg.h index 46d5552..4e93016 100644 --- a/StarsEx/ExitDlg.h +++ b/StarsEx/ExitDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Explosion.cpp b/StarsEx/Explosion.cpp index 9a47b0b..1f613e7 100644 --- a/StarsEx/Explosion.cpp +++ b/StarsEx/Explosion.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Explosion.h b/StarsEx/Explosion.h index f8dfc19..62cbf2b 100644 --- a/StarsEx/Explosion.h +++ b/StarsEx/Explosion.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FadeView.cpp b/StarsEx/FadeView.cpp index 7abb3bc..7437d9f 100644 --- a/StarsEx/FadeView.cpp +++ b/StarsEx/FadeView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FadeView.h b/StarsEx/FadeView.h index d3e3925..5b4d033 100644 --- a/StarsEx/FadeView.h +++ b/StarsEx/FadeView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Farcaster.cpp b/StarsEx/Farcaster.cpp index a9c9b1f..2950c5f 100644 --- a/StarsEx/Farcaster.cpp +++ b/StarsEx/Farcaster.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Farcaster.h b/StarsEx/Farcaster.h index 9168a90..2a1586b 100644 --- a/StarsEx/Farcaster.h +++ b/StarsEx/Farcaster.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FighterAI.cpp b/StarsEx/FighterAI.cpp index 4160174..cc010f2 100644 --- a/StarsEx/FighterAI.cpp +++ b/StarsEx/FighterAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FighterAI.h b/StarsEx/FighterAI.h index 37da3cf..21bc7f8 100644 --- a/StarsEx/FighterAI.h +++ b/StarsEx/FighterAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FighterTacticalAI.cpp b/StarsEx/FighterTacticalAI.cpp index 433b3a9..5fa2f26 100644 --- a/StarsEx/FighterTacticalAI.cpp +++ b/StarsEx/FighterTacticalAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FighterTacticalAI.h b/StarsEx/FighterTacticalAI.h index 7d8ba71..bda69ec 100644 --- a/StarsEx/FighterTacticalAI.h +++ b/StarsEx/FighterTacticalAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FirstTimeDlg.cpp b/StarsEx/FirstTimeDlg.cpp index f410f3a..8d2eaa0 100644 --- a/StarsEx/FirstTimeDlg.cpp +++ b/StarsEx/FirstTimeDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FirstTimeDlg.h b/StarsEx/FirstTimeDlg.h index 60c735c..5450ff0 100644 --- a/StarsEx/FirstTimeDlg.h +++ b/StarsEx/FirstTimeDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Fix.cpp b/StarsEx/Fix.cpp index 67b3782..e73fba7 100644 --- a/StarsEx/Fix.cpp +++ b/StarsEx/Fix.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Fix.h b/StarsEx/Fix.h index de8e01d..84c5ac3 100644 --- a/StarsEx/Fix.h +++ b/StarsEx/Fix.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FlightComp.cpp b/StarsEx/FlightComp.cpp index bbb38b6..06df132 100644 --- a/StarsEx/FlightComp.cpp +++ b/StarsEx/FlightComp.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FlightComp.h b/StarsEx/FlightComp.h index 07797a2..e8d5dee 100644 --- a/StarsEx/FlightComp.h +++ b/StarsEx/FlightComp.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FlightDeck.cpp b/StarsEx/FlightDeck.cpp index 8b2d070..9f354e3 100644 --- a/StarsEx/FlightDeck.cpp +++ b/StarsEx/FlightDeck.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FlightDeck.h b/StarsEx/FlightDeck.h index b3988c8..6788f55 100644 --- a/StarsEx/FlightDeck.h +++ b/StarsEx/FlightDeck.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FlightPlanner.cpp b/StarsEx/FlightPlanner.cpp index e8d11c8..e1b7452 100644 --- a/StarsEx/FlightPlanner.cpp +++ b/StarsEx/FlightPlanner.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FlightPlanner.h b/StarsEx/FlightPlanner.h index cef9a79..6aab4be 100644 --- a/StarsEx/FlightPlanner.h +++ b/StarsEx/FlightPlanner.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FltDlg.cpp b/StarsEx/FltDlg.cpp index 5c3fe1b..4dbc2dc 100644 --- a/StarsEx/FltDlg.cpp +++ b/StarsEx/FltDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FltDlg.h b/StarsEx/FltDlg.h index 2b7872a..aeb5115 100644 --- a/StarsEx/FltDlg.h +++ b/StarsEx/FltDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Font.cpp b/StarsEx/Font.cpp index c3ba23b..9dca717 100644 --- a/StarsEx/Font.cpp +++ b/StarsEx/Font.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Font.h b/StarsEx/Font.h index 6bc85f5..e50ce70 100644 --- a/StarsEx/Font.h +++ b/StarsEx/Font.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FontMgr.cpp b/StarsEx/FontMgr.cpp index 2e1529a..8fe51a5 100644 --- a/StarsEx/FontMgr.cpp +++ b/StarsEx/FontMgr.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FontMgr.h b/StarsEx/FontMgr.h index 5b462a8..b49b938 100644 --- a/StarsEx/FontMgr.h +++ b/StarsEx/FontMgr.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FormDef.cpp b/StarsEx/FormDef.cpp index 853003c..7a521ff 100644 --- a/StarsEx/FormDef.cpp +++ b/StarsEx/FormDef.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FormDef.h b/StarsEx/FormDef.h index b5a7f15..07c817c 100644 --- a/StarsEx/FormDef.h +++ b/StarsEx/FormDef.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FormWindow.cpp b/StarsEx/FormWindow.cpp index e58042d..781a6a5 100644 --- a/StarsEx/FormWindow.cpp +++ b/StarsEx/FormWindow.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FormWindow.h b/StarsEx/FormWindow.h index 23681ca..5118283 100644 --- a/StarsEx/FormWindow.h +++ b/StarsEx/FormWindow.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FormatUtil.cpp b/StarsEx/FormatUtil.cpp index fd3ce66..12bc992 100644 --- a/StarsEx/FormatUtil.cpp +++ b/StarsEx/FormatUtil.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/FormatUtil.h b/StarsEx/FormatUtil.h index f0d6b42..704bbf3 100644 --- a/StarsEx/FormatUtil.h +++ b/StarsEx/FormatUtil.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Galaxy.cpp b/StarsEx/Galaxy.cpp index 1b5bb6f..3d4e02d 100644 --- a/StarsEx/Galaxy.cpp +++ b/StarsEx/Galaxy.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Galaxy.h b/StarsEx/Galaxy.h index 1c9c667..b9bb41e 100644 --- a/StarsEx/Galaxy.h +++ b/StarsEx/Galaxy.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Game.cpp b/StarsEx/Game.cpp index 90fcf62..d0ad751 100644 --- a/StarsEx/Game.cpp +++ b/StarsEx/Game.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Game.h b/StarsEx/Game.h index 878f2d0..1419048 100644 --- a/StarsEx/Game.h +++ b/StarsEx/Game.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/GameScreen.cpp b/StarsEx/GameScreen.cpp index 82e9ffd..e62abd5 100644 --- a/StarsEx/GameScreen.cpp +++ b/StarsEx/GameScreen.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/GameScreen.h b/StarsEx/GameScreen.h index 597c6d2..2424917 100644 --- a/StarsEx/GameScreen.h +++ b/StarsEx/GameScreen.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/GameWinDX9.cpp b/StarsEx/GameWinDX9.cpp index 236c512..de4b0d8 100644 --- a/StarsEx/GameWinDX9.cpp +++ b/StarsEx/GameWinDX9.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/GameWinDX9.h b/StarsEx/GameWinDX9.h index 99b1a39..14cba92 100644 --- a/StarsEx/GameWinDX9.h +++ b/StarsEx/GameWinDX9.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/Geometry.cpp b/StarsEx/Geometry.cpp index 60b5c4d..1d146ea 100644 --- a/StarsEx/Geometry.cpp +++ b/StarsEx/Geometry.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Geometry.h b/StarsEx/Geometry.h index 7170c6c..739127e 100644 --- a/StarsEx/Geometry.h +++ b/StarsEx/Geometry.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Graphic.cpp b/StarsEx/Graphic.cpp index ff8115b..9974679 100644 --- a/StarsEx/Graphic.cpp +++ b/StarsEx/Graphic.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Graphic.h b/StarsEx/Graphic.h index fac4f59..40299a7 100644 --- a/StarsEx/Graphic.h +++ b/StarsEx/Graphic.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Grid.cpp b/StarsEx/Grid.cpp index f65b483..d2bb547 100644 --- a/StarsEx/Grid.cpp +++ b/StarsEx/Grid.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Grid.h b/StarsEx/Grid.h index eb426bb..31f028e 100644 --- a/StarsEx/Grid.h +++ b/StarsEx/Grid.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/GroundAI.cpp b/StarsEx/GroundAI.cpp index 4435742..5f5e4fe 100644 --- a/StarsEx/GroundAI.cpp +++ b/StarsEx/GroundAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/GroundAI.h b/StarsEx/GroundAI.h index ca135ef..9d53019 100644 --- a/StarsEx/GroundAI.h +++ b/StarsEx/GroundAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/HUDSounds.cpp b/StarsEx/HUDSounds.cpp index 3dcab0b..4b69af5 100644 --- a/StarsEx/HUDSounds.cpp +++ b/StarsEx/HUDSounds.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/HUDSounds.h b/StarsEx/HUDSounds.h index bc10ce2..aed3ef4 100644 --- a/StarsEx/HUDSounds.h +++ b/StarsEx/HUDSounds.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/HUDView.cpp b/StarsEx/HUDView.cpp index 595bc38..6c2b145 100644 --- a/StarsEx/HUDView.cpp +++ b/StarsEx/HUDView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/HUDView.h b/StarsEx/HUDView.h index 4274ac9..3632e27 100644 --- a/StarsEx/HUDView.h +++ b/StarsEx/HUDView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Hangar.cpp b/StarsEx/Hangar.cpp index 7e7f7d8..01a8894 100644 --- a/StarsEx/Hangar.cpp +++ b/StarsEx/Hangar.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Hangar.h b/StarsEx/Hangar.h index 41f7892..1305c31 100644 --- a/StarsEx/Hangar.h +++ b/StarsEx/Hangar.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/HardPoint.cpp b/StarsEx/HardPoint.cpp index 2fa15f0..03cf4c9 100644 --- a/StarsEx/HardPoint.cpp +++ b/StarsEx/HardPoint.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/HardPoint.h b/StarsEx/HardPoint.h index 3fbeda4..84e2914 100644 --- a/StarsEx/HardPoint.h +++ b/StarsEx/HardPoint.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Hoop.cpp b/StarsEx/Hoop.cpp index cfd2a65..abe69bf 100644 --- a/StarsEx/Hoop.cpp +++ b/StarsEx/Hoop.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Hoop.h b/StarsEx/Hoop.h index 9577b29..2a726d7 100644 --- a/StarsEx/Hoop.h +++ b/StarsEx/Hoop.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ImageBox.cpp b/StarsEx/ImageBox.cpp index 0a98cfe..ba1de27 100644 --- a/StarsEx/ImageBox.cpp +++ b/StarsEx/ImageBox.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ImageBox.h b/StarsEx/ImageBox.h index 24e2e53..f60eeda 100644 --- a/StarsEx/ImageBox.h +++ b/StarsEx/ImageBox.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ImgView.cpp b/StarsEx/ImgView.cpp index e2c8bba..841df8e 100644 --- a/StarsEx/ImgView.cpp +++ b/StarsEx/ImgView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ImgView.h b/StarsEx/ImgView.h index d000abf..2f280d3 100644 --- a/StarsEx/ImgView.h +++ b/StarsEx/ImgView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Instruction.cpp b/StarsEx/Instruction.cpp index 18ef168..7bf57c5 100644 --- a/StarsEx/Instruction.cpp +++ b/StarsEx/Instruction.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Instruction.h b/StarsEx/Instruction.h index d1ca0eb..b598883 100644 --- a/StarsEx/Instruction.h +++ b/StarsEx/Instruction.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Intel.cpp b/StarsEx/Intel.cpp index 986d9f4..e59a6c8 100644 --- a/StarsEx/Intel.cpp +++ b/StarsEx/Intel.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Intel.h b/StarsEx/Intel.h index 5ed1675..682e957 100644 --- a/StarsEx/Intel.h +++ b/StarsEx/Intel.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/JoyDlg.cpp b/StarsEx/JoyDlg.cpp index b0ac318..77f1cd0 100644 --- a/StarsEx/JoyDlg.cpp +++ b/StarsEx/JoyDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/JoyDlg.h b/StarsEx/JoyDlg.h index 83ceda9..68e2395 100644 --- a/StarsEx/JoyDlg.h +++ b/StarsEx/JoyDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Joystick.cpp b/StarsEx/Joystick.cpp index b4166a1..ad614c0 100644 --- a/StarsEx/Joystick.cpp +++ b/StarsEx/Joystick.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Joystick.h b/StarsEx/Joystick.h index 5e645c8..b024f83 100644 --- a/StarsEx/Joystick.h +++ b/StarsEx/Joystick.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/KeyDlg.cpp b/StarsEx/KeyDlg.cpp index cbd7c68..185a888 100644 --- a/StarsEx/KeyDlg.cpp +++ b/StarsEx/KeyDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/KeyDlg.h b/StarsEx/KeyDlg.h index 198f3ab..870a16a 100644 --- a/StarsEx/KeyDlg.h +++ b/StarsEx/KeyDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/KeyMap.cpp b/StarsEx/KeyMap.cpp index 15ec749..26b6c01 100644 --- a/StarsEx/KeyMap.cpp +++ b/StarsEx/KeyMap.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/KeyMap.h b/StarsEx/KeyMap.h index 1ec7bbc..4452cbd 100644 --- a/StarsEx/KeyMap.h +++ b/StarsEx/KeyMap.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Keyboard.cpp b/StarsEx/Keyboard.cpp index c4e2d26..1b35ad2 100644 --- a/StarsEx/Keyboard.cpp +++ b/StarsEx/Keyboard.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Keyboard.h b/StarsEx/Keyboard.h index b218160..4058c2b 100644 --- a/StarsEx/Keyboard.h +++ b/StarsEx/Keyboard.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/LandingGear.cpp b/StarsEx/LandingGear.cpp index f5fa00b..779b725 100644 --- a/StarsEx/LandingGear.cpp +++ b/StarsEx/LandingGear.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/LandingGear.h b/StarsEx/LandingGear.h index b753106..df9ec1a 100644 --- a/StarsEx/LandingGear.h +++ b/StarsEx/LandingGear.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Layout.cpp b/StarsEx/Layout.cpp index 5637831..3761a5d 100644 --- a/StarsEx/Layout.cpp +++ b/StarsEx/Layout.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Layout.h b/StarsEx/Layout.h index 51402d7..e5fc5f0 100644 --- a/StarsEx/Layout.h +++ b/StarsEx/Layout.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Light.cpp b/StarsEx/Light.cpp index c0c3a26..4eb60a1 100644 --- a/StarsEx/Light.cpp +++ b/StarsEx/Light.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Light.h b/StarsEx/Light.h index 2f42e91..446f464 100644 --- a/StarsEx/Light.h +++ b/StarsEx/Light.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ListBox.cpp b/StarsEx/ListBox.cpp index 8b4eeeb..8d52cfe 100644 --- a/StarsEx/ListBox.cpp +++ b/StarsEx/ListBox.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ListBox.h b/StarsEx/ListBox.h index 6d94d74..fb44177 100644 --- a/StarsEx/ListBox.h +++ b/StarsEx/ListBox.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/LoadDlg.cpp b/StarsEx/LoadDlg.cpp index 7028718..7796338 100644 --- a/StarsEx/LoadDlg.cpp +++ b/StarsEx/LoadDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/LoadDlg.h b/StarsEx/LoadDlg.h index 8b79e28..9e82c2c 100644 --- a/StarsEx/LoadDlg.h +++ b/StarsEx/LoadDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/LoadScreen.cpp b/StarsEx/LoadScreen.cpp index 56234c6..e9b3d25 100644 --- a/StarsEx/LoadScreen.cpp +++ b/StarsEx/LoadScreen.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/LoadScreen.h b/StarsEx/LoadScreen.h index 349703b..c0824f8 100644 --- a/StarsEx/LoadScreen.h +++ b/StarsEx/LoadScreen.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Locale_ss.cpp b/StarsEx/Locale_ss.cpp index 427753c..cacfc57 100644 --- a/StarsEx/Locale_ss.cpp +++ b/StarsEx/Locale_ss.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Locale_ss.h b/StarsEx/Locale_ss.h index be161ff..fdecaeb 100644 --- a/StarsEx/Locale_ss.h +++ b/StarsEx/Locale_ss.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MCIWave.cpp b/StarsEx/MCIWave.cpp index a8c0a0b..f157d35 100644 --- a/StarsEx/MCIWave.cpp +++ b/StarsEx/MCIWave.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MCIWave.h b/StarsEx/MCIWave.h index bef5ae2..9fd0f9d 100644 --- a/StarsEx/MCIWave.h +++ b/StarsEx/MCIWave.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MapView.cpp b/StarsEx/MapView.cpp index 930a762..2b1068f 100644 --- a/StarsEx/MapView.cpp +++ b/StarsEx/MapView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MapView.h b/StarsEx/MapView.h index d89ac92..5518ed3 100644 --- a/StarsEx/MapView.h +++ b/StarsEx/MapView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Menu.cpp b/StarsEx/Menu.cpp index 35f5715..18dc7e7 100644 --- a/StarsEx/Menu.cpp +++ b/StarsEx/Menu.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Menu.h b/StarsEx/Menu.h index b74099f..111425c 100644 --- a/StarsEx/Menu.h +++ b/StarsEx/Menu.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MenuDlg.cpp b/StarsEx/MenuDlg.cpp index 4cd7704..bfe1575 100644 --- a/StarsEx/MenuDlg.cpp +++ b/StarsEx/MenuDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MenuDlg.h b/StarsEx/MenuDlg.h index f380acc..d99104e 100644 --- a/StarsEx/MenuDlg.h +++ b/StarsEx/MenuDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MenuScreen.cpp b/StarsEx/MenuScreen.cpp index 3f4ebbd..f8c919a 100644 --- a/StarsEx/MenuScreen.cpp +++ b/StarsEx/MenuScreen.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MenuScreen.h b/StarsEx/MenuScreen.h index 6642e16..aea0de1 100644 --- a/StarsEx/MenuScreen.h +++ b/StarsEx/MenuScreen.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MenuView.cpp b/StarsEx/MenuView.cpp index b672563..06a5844 100644 --- a/StarsEx/MenuView.cpp +++ b/StarsEx/MenuView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MenuView.h b/StarsEx/MenuView.h index f5890b2..8aa1107 100644 --- a/StarsEx/MenuView.h +++ b/StarsEx/MenuView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Mfd.cpp b/StarsEx/Mfd.cpp index 1b15636..3c677c2 100644 --- a/StarsEx/Mfd.cpp +++ b/StarsEx/Mfd.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Mfd.h b/StarsEx/Mfd.h index 66bfe85..84d1414 100644 --- a/StarsEx/Mfd.h +++ b/StarsEx/Mfd.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Mission.cpp b/StarsEx/Mission.cpp index 64d5948..cb3ef86 100644 --- a/StarsEx/Mission.cpp +++ b/StarsEx/Mission.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Mission.h b/StarsEx/Mission.h index 956bb5b..5bcffa7 100644 --- a/StarsEx/Mission.h +++ b/StarsEx/Mission.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MissionEvent.cpp b/StarsEx/MissionEvent.cpp index af34bd7..d07f112 100644 --- a/StarsEx/MissionEvent.cpp +++ b/StarsEx/MissionEvent.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MissionEvent.h b/StarsEx/MissionEvent.h index 5fe4f10..9667f45 100644 --- a/StarsEx/MissionEvent.h +++ b/StarsEx/MissionEvent.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MissionTemplate.cpp b/StarsEx/MissionTemplate.cpp index 54efbe6..55bec50 100644 --- a/StarsEx/MissionTemplate.cpp +++ b/StarsEx/MissionTemplate.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MissionTemplate.h b/StarsEx/MissionTemplate.h index 44ef0ca..38629e4 100644 --- a/StarsEx/MissionTemplate.h +++ b/StarsEx/MissionTemplate.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ModConfig.cpp b/StarsEx/ModConfig.cpp index 9cbd1c7..ad7e852 100644 --- a/StarsEx/ModConfig.cpp +++ b/StarsEx/ModConfig.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ModConfig.h b/StarsEx/ModConfig.h index 5b57589..5811639 100644 --- a/StarsEx/ModConfig.h +++ b/StarsEx/ModConfig.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ModDlg.cpp b/StarsEx/ModDlg.cpp index c989bbc..a78da4b 100644 --- a/StarsEx/ModDlg.cpp +++ b/StarsEx/ModDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ModDlg.h b/StarsEx/ModDlg.h index 1ebdf87..74d8572 100644 --- a/StarsEx/ModDlg.h +++ b/StarsEx/ModDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ModInfo.cpp b/StarsEx/ModInfo.cpp index d884dec..7f025b7 100644 --- a/StarsEx/ModInfo.cpp +++ b/StarsEx/ModInfo.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ModInfo.h b/StarsEx/ModInfo.h index 4e1ff47..458a721 100644 --- a/StarsEx/ModInfo.h +++ b/StarsEx/ModInfo.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ModInfoDlg.cpp b/StarsEx/ModInfoDlg.cpp index 88127fc..0b323f9 100644 --- a/StarsEx/ModInfoDlg.cpp +++ b/StarsEx/ModInfoDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ModInfoDlg.h b/StarsEx/ModInfoDlg.h index 656e012..23f68c0 100644 --- a/StarsEx/ModInfoDlg.h +++ b/StarsEx/ModInfoDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MotionController.h b/StarsEx/MotionController.h index 11c0977..0214d14 100644 --- a/StarsEx/MotionController.h +++ b/StarsEx/MotionController.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Mouse.cpp b/StarsEx/Mouse.cpp index c772bc2..d756e6e 100644 --- a/StarsEx/Mouse.cpp +++ b/StarsEx/Mouse.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Mouse.h b/StarsEx/Mouse.h index e9f6a18..1c20b95 100644 --- a/StarsEx/Mouse.h +++ b/StarsEx/Mouse.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MouseController.cpp b/StarsEx/MouseController.cpp index 75fd0f5..f6f7da1 100644 --- a/StarsEx/MouseController.cpp +++ b/StarsEx/MouseController.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MouseController.h b/StarsEx/MouseController.h index 7d66329..12192e1 100644 --- a/StarsEx/MouseController.h +++ b/StarsEx/MouseController.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnDlg.cpp b/StarsEx/MsnDlg.cpp index f332b3d..dbdb0cf 100644 --- a/StarsEx/MsnDlg.cpp +++ b/StarsEx/MsnDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnDlg.h b/StarsEx/MsnDlg.h index 44b3231..8b5f9b8 100644 --- a/StarsEx/MsnDlg.h +++ b/StarsEx/MsnDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnEditDlg.cpp b/StarsEx/MsnEditDlg.cpp index 9658a51..5711652 100644 --- a/StarsEx/MsnEditDlg.cpp +++ b/StarsEx/MsnEditDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnEditDlg.h b/StarsEx/MsnEditDlg.h index b0eaaf0..01c8330 100644 --- a/StarsEx/MsnEditDlg.h +++ b/StarsEx/MsnEditDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnEditNavDlg.cpp b/StarsEx/MsnEditNavDlg.cpp index eab1d13..f553af9 100644 --- a/StarsEx/MsnEditNavDlg.cpp +++ b/StarsEx/MsnEditNavDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnEditNavDlg.h b/StarsEx/MsnEditNavDlg.h index 87a9c38..e57b398 100644 --- a/StarsEx/MsnEditNavDlg.h +++ b/StarsEx/MsnEditNavDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnElemDlg.cpp b/StarsEx/MsnElemDlg.cpp index 34f205c..7aca63c 100644 --- a/StarsEx/MsnElemDlg.cpp +++ b/StarsEx/MsnElemDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnElemDlg.h b/StarsEx/MsnElemDlg.h index d433006..0d3091e 100644 --- a/StarsEx/MsnElemDlg.h +++ b/StarsEx/MsnElemDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnEventDlg.cpp b/StarsEx/MsnEventDlg.cpp index 5c13839..268c70c 100644 --- a/StarsEx/MsnEventDlg.cpp +++ b/StarsEx/MsnEventDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnEventDlg.h b/StarsEx/MsnEventDlg.h index bd3180e..3f8ab1e 100644 --- a/StarsEx/MsnEventDlg.h +++ b/StarsEx/MsnEventDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnNavDlg.cpp b/StarsEx/MsnNavDlg.cpp index 7858aaf..df38ef3 100644 --- a/StarsEx/MsnNavDlg.cpp +++ b/StarsEx/MsnNavDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnNavDlg.h b/StarsEx/MsnNavDlg.h index a5d60ab..91997e4 100644 --- a/StarsEx/MsnNavDlg.h +++ b/StarsEx/MsnNavDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnObjDlg.cpp b/StarsEx/MsnObjDlg.cpp index 384f83e..bd91a00 100644 --- a/StarsEx/MsnObjDlg.cpp +++ b/StarsEx/MsnObjDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnObjDlg.h b/StarsEx/MsnObjDlg.h index d3ff7a1..fa6625f 100644 --- a/StarsEx/MsnObjDlg.h +++ b/StarsEx/MsnObjDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnPkgDlg.cpp b/StarsEx/MsnPkgDlg.cpp index 6616fd2..8576880 100644 --- a/StarsEx/MsnPkgDlg.cpp +++ b/StarsEx/MsnPkgDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnPkgDlg.h b/StarsEx/MsnPkgDlg.h index d42261d..2e4fc3b 100644 --- a/StarsEx/MsnPkgDlg.h +++ b/StarsEx/MsnPkgDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnSelectDlg.cpp b/StarsEx/MsnSelectDlg.cpp index 847f06f..8c720c8 100644 --- a/StarsEx/MsnSelectDlg.cpp +++ b/StarsEx/MsnSelectDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnSelectDlg.h b/StarsEx/MsnSelectDlg.h index 6fbc298..94298a4 100644 --- a/StarsEx/MsnSelectDlg.h +++ b/StarsEx/MsnSelectDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnWepDlg.cpp b/StarsEx/MsnWepDlg.cpp index 2249d48..8a9d03f 100644 --- a/StarsEx/MsnWepDlg.cpp +++ b/StarsEx/MsnWepDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MsnWepDlg.h b/StarsEx/MsnWepDlg.h index 975595b..e54133f 100644 --- a/StarsEx/MsnWepDlg.h +++ b/StarsEx/MsnWepDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MultiController.cpp b/StarsEx/MultiController.cpp index 3df791b..531874a 100644 --- a/StarsEx/MultiController.cpp +++ b/StarsEx/MultiController.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MultiController.h b/StarsEx/MultiController.h index 455a577..151f43a 100644 --- a/StarsEx/MultiController.h +++ b/StarsEx/MultiController.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MusicDirector.cpp b/StarsEx/MusicDirector.cpp index b2ff7ef..eef35d7 100644 --- a/StarsEx/MusicDirector.cpp +++ b/StarsEx/MusicDirector.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MusicDirector.h b/StarsEx/MusicDirector.h index 8fc6812..4fe924b 100644 --- a/StarsEx/MusicDirector.h +++ b/StarsEx/MusicDirector.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MusicTrack.cpp b/StarsEx/MusicTrack.cpp index 01d7082..e6d4b1c 100644 --- a/StarsEx/MusicTrack.cpp +++ b/StarsEx/MusicTrack.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/MusicTrack.h b/StarsEx/MusicTrack.h index 30af277..d353249 100644 --- a/StarsEx/MusicTrack.h +++ b/StarsEx/MusicTrack.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NavAI.cpp b/StarsEx/NavAI.cpp index 609c4ab..d73ec31 100644 --- a/StarsEx/NavAI.cpp +++ b/StarsEx/NavAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NavAI.h b/StarsEx/NavAI.h index 0eeea2e..32a258a 100644 --- a/StarsEx/NavAI.h +++ b/StarsEx/NavAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NavDlg.cpp b/StarsEx/NavDlg.cpp index 8847957..be21a7a 100644 --- a/StarsEx/NavDlg.cpp +++ b/StarsEx/NavDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NavDlg.h b/StarsEx/NavDlg.h index 1bc4eb7..27d803d 100644 --- a/StarsEx/NavDlg.h +++ b/StarsEx/NavDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NavLight.cpp b/StarsEx/NavLight.cpp index 1be4fd5..31c7c3b 100644 --- a/StarsEx/NavLight.cpp +++ b/StarsEx/NavLight.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NavLight.h b/StarsEx/NavLight.h index b0be265..25ef837 100644 --- a/StarsEx/NavLight.h +++ b/StarsEx/NavLight.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NavSystem.cpp b/StarsEx/NavSystem.cpp index da5a3d6..d54f156 100644 --- a/StarsEx/NavSystem.cpp +++ b/StarsEx/NavSystem.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NavSystem.h b/StarsEx/NavSystem.h index 3727c19..8ce7981 100644 --- a/StarsEx/NavSystem.h +++ b/StarsEx/NavSystem.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetAddrDlg.cpp b/StarsEx/NetAddrDlg.cpp index a9ea308..627ad5e 100644 --- a/StarsEx/NetAddrDlg.cpp +++ b/StarsEx/NetAddrDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetAddrDlg.h b/StarsEx/NetAddrDlg.h index ca2e6e9..c5caab9 100644 --- a/StarsEx/NetAddrDlg.h +++ b/StarsEx/NetAddrDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetAuth.cpp b/StarsEx/NetAuth.cpp index f9e4d02..a8fa965 100644 --- a/StarsEx/NetAuth.cpp +++ b/StarsEx/NetAuth.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetAuth.h b/StarsEx/NetAuth.h index 42103fc..fb45fac 100644 --- a/StarsEx/NetAuth.h +++ b/StarsEx/NetAuth.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetBrokerClient.cpp b/StarsEx/NetBrokerClient.cpp index 043c580..7f6c912 100644 --- a/StarsEx/NetBrokerClient.cpp +++ b/StarsEx/NetBrokerClient.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetBrokerClient.h b/StarsEx/NetBrokerClient.h index e05e89d..072672a 100644 --- a/StarsEx/NetBrokerClient.h +++ b/StarsEx/NetBrokerClient.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetChat.cpp b/StarsEx/NetChat.cpp index 7c1f4d2..d296b0c 100644 --- a/StarsEx/NetChat.cpp +++ b/StarsEx/NetChat.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetChat.h b/StarsEx/NetChat.h index 97e5dd8..2aacc62 100644 --- a/StarsEx/NetChat.h +++ b/StarsEx/NetChat.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetClientConfig.cpp b/StarsEx/NetClientConfig.cpp index 8fc97be..97cd11c 100644 --- a/StarsEx/NetClientConfig.cpp +++ b/StarsEx/NetClientConfig.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetClientConfig.h b/StarsEx/NetClientConfig.h index 13a8bff..bce0cf5 100644 --- a/StarsEx/NetClientConfig.h +++ b/StarsEx/NetClientConfig.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetClientDlg.cpp b/StarsEx/NetClientDlg.cpp index 17a36e0..ea30f5e 100644 --- a/StarsEx/NetClientDlg.cpp +++ b/StarsEx/NetClientDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetClientDlg.h b/StarsEx/NetClientDlg.h index 3506e9c..131b59d 100644 --- a/StarsEx/NetClientDlg.h +++ b/StarsEx/NetClientDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetData.cpp b/StarsEx/NetData.cpp index 4d625b9..d8c424f 100644 --- a/StarsEx/NetData.cpp +++ b/StarsEx/NetData.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetData.h b/StarsEx/NetData.h index ebb7fd0..f6878db 100644 --- a/StarsEx/NetData.h +++ b/StarsEx/NetData.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetGame.cpp b/StarsEx/NetGame.cpp index c02b390..acd50eb 100644 --- a/StarsEx/NetGame.cpp +++ b/StarsEx/NetGame.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetGame.h b/StarsEx/NetGame.h index 1a79d30..db10444 100644 --- a/StarsEx/NetGame.h +++ b/StarsEx/NetGame.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetGameClient.cpp b/StarsEx/NetGameClient.cpp index 5b1440f..f317447 100644 --- a/StarsEx/NetGameClient.cpp +++ b/StarsEx/NetGameClient.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetGameClient.h b/StarsEx/NetGameClient.h index 3ec397b..8ad138b 100644 --- a/StarsEx/NetGameClient.h +++ b/StarsEx/NetGameClient.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetGameServer.cpp b/StarsEx/NetGameServer.cpp index ef33a90..b8f21c0 100644 --- a/StarsEx/NetGameServer.cpp +++ b/StarsEx/NetGameServer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetGameServer.h b/StarsEx/NetGameServer.h index 12b5827..507cf94 100644 --- a/StarsEx/NetGameServer.h +++ b/StarsEx/NetGameServer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetLobby.cpp b/StarsEx/NetLobby.cpp index 81eecae..8222c75 100644 --- a/StarsEx/NetLobby.cpp +++ b/StarsEx/NetLobby.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetLobby.h b/StarsEx/NetLobby.h index 028e931..55e7ee8 100644 --- a/StarsEx/NetLobby.h +++ b/StarsEx/NetLobby.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetLobbyClient.cpp b/StarsEx/NetLobbyClient.cpp index df66900..603c1cb 100644 --- a/StarsEx/NetLobbyClient.cpp +++ b/StarsEx/NetLobbyClient.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetLobbyClient.h b/StarsEx/NetLobbyClient.h index c54cea7..594d374 100644 --- a/StarsEx/NetLobbyClient.h +++ b/StarsEx/NetLobbyClient.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetLobbyDlg.cpp b/StarsEx/NetLobbyDlg.cpp index b5c9d84..8cb2588 100644 --- a/StarsEx/NetLobbyDlg.cpp +++ b/StarsEx/NetLobbyDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetLobbyDlg.h b/StarsEx/NetLobbyDlg.h index c8b9b5d..6fee140 100644 --- a/StarsEx/NetLobbyDlg.h +++ b/StarsEx/NetLobbyDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetLobbyServer.cpp b/StarsEx/NetLobbyServer.cpp index 2039fff..dfb0422 100644 --- a/StarsEx/NetLobbyServer.cpp +++ b/StarsEx/NetLobbyServer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetLobbyServer.h b/StarsEx/NetLobbyServer.h index 0b1327a..2f08f83 100644 --- a/StarsEx/NetLobbyServer.h +++ b/StarsEx/NetLobbyServer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetPacket.cpp b/StarsEx/NetPacket.cpp index 1056e11..e8964c2 100644 --- a/StarsEx/NetPacket.cpp +++ b/StarsEx/NetPacket.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetPacket.h b/StarsEx/NetPacket.h index 910eaab..c527c1e 100644 --- a/StarsEx/NetPacket.h +++ b/StarsEx/NetPacket.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetPassDlg.cpp b/StarsEx/NetPassDlg.cpp index efe6141..1eb8077 100644 --- a/StarsEx/NetPassDlg.cpp +++ b/StarsEx/NetPassDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetPassDlg.h b/StarsEx/NetPassDlg.h index de66b7e..be03721 100644 --- a/StarsEx/NetPassDlg.h +++ b/StarsEx/NetPassDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetPlayer.cpp b/StarsEx/NetPlayer.cpp index 9632b94..d098e5c 100644 --- a/StarsEx/NetPlayer.cpp +++ b/StarsEx/NetPlayer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetPlayer.h b/StarsEx/NetPlayer.h index 5867669..143a8be 100644 --- a/StarsEx/NetPlayer.h +++ b/StarsEx/NetPlayer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetServerConfig.cpp b/StarsEx/NetServerConfig.cpp index 960028d..831c4da 100644 --- a/StarsEx/NetServerConfig.cpp +++ b/StarsEx/NetServerConfig.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetServerConfig.h b/StarsEx/NetServerConfig.h index fb8418f..40741cd 100644 --- a/StarsEx/NetServerConfig.h +++ b/StarsEx/NetServerConfig.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetServerDlg.cpp b/StarsEx/NetServerDlg.cpp index 7747aba..552e7ee 100644 --- a/StarsEx/NetServerDlg.cpp +++ b/StarsEx/NetServerDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetServerDlg.h b/StarsEx/NetServerDlg.h index 4c70323..edc4d1b 100644 --- a/StarsEx/NetServerDlg.h +++ b/StarsEx/NetServerDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetUnitDlg.cpp b/StarsEx/NetUnitDlg.cpp index 5c4675c..26b2af7 100644 --- a/StarsEx/NetUnitDlg.cpp +++ b/StarsEx/NetUnitDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetUnitDlg.h b/StarsEx/NetUnitDlg.h index 8278426..f802d59 100644 --- a/StarsEx/NetUnitDlg.h +++ b/StarsEx/NetUnitDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetUser.cpp b/StarsEx/NetUser.cpp index d8a8ba9..d7ba9eb 100644 --- a/StarsEx/NetUser.cpp +++ b/StarsEx/NetUser.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetUser.h b/StarsEx/NetUser.h index 79b0d2c..e218aca 100644 --- a/StarsEx/NetUser.h +++ b/StarsEx/NetUser.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetUtil.cpp b/StarsEx/NetUtil.cpp index 4b3fb97..ff212c5 100644 --- a/StarsEx/NetUtil.cpp +++ b/StarsEx/NetUtil.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/NetUtil.h b/StarsEx/NetUtil.h index d64f56f..3f02f49 100644 --- a/StarsEx/NetUtil.h +++ b/StarsEx/NetUtil.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/OptDlg.cpp b/StarsEx/OptDlg.cpp index ffd53a7..a9cc524 100644 --- a/StarsEx/OptDlg.cpp +++ b/StarsEx/OptDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/OptDlg.h b/StarsEx/OptDlg.h index ab0202c..c7f2386 100644 --- a/StarsEx/OptDlg.h +++ b/StarsEx/OptDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Panic.cpp b/StarsEx/Panic.cpp index 67c29b7..ec68afb 100644 --- a/StarsEx/Panic.cpp +++ b/StarsEx/Panic.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/Panic.h b/StarsEx/Panic.h index 431a1f6..b77fee5 100644 --- a/StarsEx/Panic.h +++ b/StarsEx/Panic.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/ParseUtil.cpp b/StarsEx/ParseUtil.cpp index 485d7ce..2a7ad65 100644 --- a/StarsEx/ParseUtil.cpp +++ b/StarsEx/ParseUtil.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ParseUtil.h b/StarsEx/ParseUtil.h index 43ddab3..947b4c7 100644 --- a/StarsEx/ParseUtil.h +++ b/StarsEx/ParseUtil.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Particles.cpp b/StarsEx/Particles.cpp index 911b06f..49edd8d 100644 --- a/StarsEx/Particles.cpp +++ b/StarsEx/Particles.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Particles.h b/StarsEx/Particles.h index af540da..8a22f4c 100644 --- a/StarsEx/Particles.h +++ b/StarsEx/Particles.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Pcx.cpp b/StarsEx/Pcx.cpp index 91ae59a..fdae1c2 100644 --- a/StarsEx/Pcx.cpp +++ b/StarsEx/Pcx.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Pcx.h b/StarsEx/Pcx.h index 86c8bc3..fdfbf0b 100644 --- a/StarsEx/Pcx.h +++ b/StarsEx/Pcx.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Physical.cpp b/StarsEx/Physical.cpp index 6c2e90e..2c5fb85 100644 --- a/StarsEx/Physical.cpp +++ b/StarsEx/Physical.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Physical.h b/StarsEx/Physical.h index b9a9be5..1146bb9 100644 --- a/StarsEx/Physical.h +++ b/StarsEx/Physical.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/PlanScreen.cpp b/StarsEx/PlanScreen.cpp index 47f1c73..058ea1f 100644 --- a/StarsEx/PlanScreen.cpp +++ b/StarsEx/PlanScreen.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/PlanScreen.h b/StarsEx/PlanScreen.h index d033ed6..2f2b5da 100644 --- a/StarsEx/PlanScreen.h +++ b/StarsEx/PlanScreen.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Player.cpp b/StarsEx/Player.cpp index bb4a6d3..a5e31b0 100644 --- a/StarsEx/Player.cpp +++ b/StarsEx/Player.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Player.h b/StarsEx/Player.h index 91f5025..7cbebad 100644 --- a/StarsEx/Player.h +++ b/StarsEx/Player.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/PlayerDlg.cpp b/StarsEx/PlayerDlg.cpp index cdf7bba..2b321ac 100644 --- a/StarsEx/PlayerDlg.cpp +++ b/StarsEx/PlayerDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/PlayerDlg.h b/StarsEx/PlayerDlg.h index eace5a4..384b757 100644 --- a/StarsEx/PlayerDlg.h +++ b/StarsEx/PlayerDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/PngImage.cpp b/StarsEx/PngImage.cpp index d8f1244..1dddd1e 100644 --- a/StarsEx/PngImage.cpp +++ b/StarsEx/PngImage.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/PngImage.h b/StarsEx/PngImage.h index f712461..f62e979 100644 --- a/StarsEx/PngImage.h +++ b/StarsEx/PngImage.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Polygon.cpp b/StarsEx/Polygon.cpp index d3e3b27..d22b4fa 100644 --- a/StarsEx/Polygon.cpp +++ b/StarsEx/Polygon.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Polygon.h b/StarsEx/Polygon.h index e011afc..b034856 100644 --- a/StarsEx/Polygon.h +++ b/StarsEx/Polygon.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Power.cpp b/StarsEx/Power.cpp index f86c5af..846f31f 100644 --- a/StarsEx/Power.cpp +++ b/StarsEx/Power.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Power.h b/StarsEx/Power.h index 3037f3a..ee73f58 100644 --- a/StarsEx/Power.h +++ b/StarsEx/Power.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Projector.cpp b/StarsEx/Projector.cpp index afa456e..55f50b4 100644 --- a/StarsEx/Projector.cpp +++ b/StarsEx/Projector.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Projector.h b/StarsEx/Projector.h index 20f0f7b..beeef09 100644 --- a/StarsEx/Projector.h +++ b/StarsEx/Projector.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/QuantumDrive.cpp b/StarsEx/QuantumDrive.cpp index bcc8356..b2427e2 100644 --- a/StarsEx/QuantumDrive.cpp +++ b/StarsEx/QuantumDrive.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/QuantumDrive.h b/StarsEx/QuantumDrive.h index 36adb64..3065f1d 100644 --- a/StarsEx/QuantumDrive.h +++ b/StarsEx/QuantumDrive.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/QuantumFlash.cpp b/StarsEx/QuantumFlash.cpp index 53c834c..452e511 100644 --- a/StarsEx/QuantumFlash.cpp +++ b/StarsEx/QuantumFlash.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/QuantumFlash.h b/StarsEx/QuantumFlash.h index 6141970..ee9bb01 100644 --- a/StarsEx/QuantumFlash.h +++ b/StarsEx/QuantumFlash.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/QuantumView.cpp b/StarsEx/QuantumView.cpp index 32feee0..5d20e5e 100644 --- a/StarsEx/QuantumView.cpp +++ b/StarsEx/QuantumView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/QuantumView.h b/StarsEx/QuantumView.h index 3d07480..599592a 100644 --- a/StarsEx/QuantumView.h +++ b/StarsEx/QuantumView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/QuitView.cpp b/StarsEx/QuitView.cpp index 8bee3e4..e3a453e 100644 --- a/StarsEx/QuitView.cpp +++ b/StarsEx/QuitView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/QuitView.h b/StarsEx/QuitView.h index d893efc..733558a 100644 --- a/StarsEx/QuitView.h +++ b/StarsEx/QuitView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RLoc.cpp b/StarsEx/RLoc.cpp index 911c4ea..8f227eb 100644 --- a/StarsEx/RLoc.cpp +++ b/StarsEx/RLoc.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RLoc.h b/StarsEx/RLoc.h index eedc5ac..97d6976 100644 --- a/StarsEx/RLoc.h +++ b/StarsEx/RLoc.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioHandler.cpp b/StarsEx/RadioHandler.cpp index b395c6e..78effd3 100644 --- a/StarsEx/RadioHandler.cpp +++ b/StarsEx/RadioHandler.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioHandler.h b/StarsEx/RadioHandler.h index 2e43611..938865d 100644 --- a/StarsEx/RadioHandler.h +++ b/StarsEx/RadioHandler.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioMessage.cpp b/StarsEx/RadioMessage.cpp index ecf3e04..32d8cd7 100644 --- a/StarsEx/RadioMessage.cpp +++ b/StarsEx/RadioMessage.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioMessage.h b/StarsEx/RadioMessage.h index 0a04daf..7a73809 100644 --- a/StarsEx/RadioMessage.h +++ b/StarsEx/RadioMessage.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioTraffic.cpp b/StarsEx/RadioTraffic.cpp index a67cd9f..13fd7e9 100644 --- a/StarsEx/RadioTraffic.cpp +++ b/StarsEx/RadioTraffic.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioTraffic.h b/StarsEx/RadioTraffic.h index 5ffd1ec..c400d37 100644 --- a/StarsEx/RadioTraffic.h +++ b/StarsEx/RadioTraffic.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioView.cpp b/StarsEx/RadioView.cpp index c336f4d..360dcbc 100644 --- a/StarsEx/RadioView.cpp +++ b/StarsEx/RadioView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioView.h b/StarsEx/RadioView.h index 1d25459..5bb5d78 100644 --- a/StarsEx/RadioView.h +++ b/StarsEx/RadioView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioVox.cpp b/StarsEx/RadioVox.cpp index 8942caf..4725f8a 100644 --- a/StarsEx/RadioVox.cpp +++ b/StarsEx/RadioVox.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RadioVox.h b/StarsEx/RadioVox.h index 447b854..e85224f 100644 --- a/StarsEx/RadioVox.h +++ b/StarsEx/RadioVox.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Random.cpp b/StarsEx/Random.cpp index 18f6031..f0786a5 100644 --- a/StarsEx/Random.cpp +++ b/StarsEx/Random.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Random.h b/StarsEx/Random.h index 01f4f57..f40b165 100644 --- a/StarsEx/Random.h +++ b/StarsEx/Random.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Res.cpp b/StarsEx/Res.cpp index f6a160e..3469748 100644 --- a/StarsEx/Res.cpp +++ b/StarsEx/Res.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Res.h b/StarsEx/Res.h index dbd1295..bc56088 100644 --- a/StarsEx/Res.h +++ b/StarsEx/Res.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RichTextBox.cpp b/StarsEx/RichTextBox.cpp index 5f29867..6e1b750 100644 --- a/StarsEx/RichTextBox.cpp +++ b/StarsEx/RichTextBox.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/RichTextBox.h b/StarsEx/RichTextBox.h index 96838d1..06b93fc 100644 --- a/StarsEx/RichTextBox.h +++ b/StarsEx/RichTextBox.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Scene.cpp b/StarsEx/Scene.cpp index 4f977f4..e5f4acd 100644 --- a/StarsEx/Scene.cpp +++ b/StarsEx/Scene.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Scene.h b/StarsEx/Scene.h index c1c955b..70ee759 100644 --- a/StarsEx/Scene.h +++ b/StarsEx/Scene.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Screen.cpp b/StarsEx/Screen.cpp index 36dd577..3c43111 100644 --- a/StarsEx/Screen.cpp +++ b/StarsEx/Screen.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Screen.h b/StarsEx/Screen.h index 3fe966a..01acab9 100644 --- a/StarsEx/Screen.h +++ b/StarsEx/Screen.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ScrollWindow.cpp b/StarsEx/ScrollWindow.cpp index 6425ff8..13df683 100644 --- a/StarsEx/ScrollWindow.cpp +++ b/StarsEx/ScrollWindow.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ScrollWindow.h b/StarsEx/ScrollWindow.h index 910b117..85b4b4d 100644 --- a/StarsEx/ScrollWindow.h +++ b/StarsEx/ScrollWindow.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SeekerAI.cpp b/StarsEx/SeekerAI.cpp index 7976dfd..148fb30 100644 --- a/StarsEx/SeekerAI.cpp +++ b/StarsEx/SeekerAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SeekerAI.h b/StarsEx/SeekerAI.h index f1a4a52..8a3e6d6 100644 --- a/StarsEx/SeekerAI.h +++ b/StarsEx/SeekerAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sensor.cpp b/StarsEx/Sensor.cpp index e5a4932..fcbce77 100644 --- a/StarsEx/Sensor.cpp +++ b/StarsEx/Sensor.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sensor.h b/StarsEx/Sensor.h index 5462c18..1073376 100644 --- a/StarsEx/Sensor.h +++ b/StarsEx/Sensor.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Shadow.cpp b/StarsEx/Shadow.cpp index f64c033..b50950a 100644 --- a/StarsEx/Shadow.cpp +++ b/StarsEx/Shadow.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Shadow.h b/StarsEx/Shadow.h index 5427f64..4fcf34e 100644 --- a/StarsEx/Shadow.h +++ b/StarsEx/Shadow.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Shield.cpp b/StarsEx/Shield.cpp index e7c8fb8..4a2f905 100644 --- a/StarsEx/Shield.cpp +++ b/StarsEx/Shield.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Shield.h b/StarsEx/Shield.h index 57dc7dc..cb59bf0 100644 --- a/StarsEx/Shield.h +++ b/StarsEx/Shield.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShieldRep.cpp b/StarsEx/ShieldRep.cpp index 3619fe8..dc8ed7e 100644 --- a/StarsEx/ShieldRep.cpp +++ b/StarsEx/ShieldRep.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShieldRep.h b/StarsEx/ShieldRep.h index b034c0d..b148440 100644 --- a/StarsEx/ShieldRep.h +++ b/StarsEx/ShieldRep.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Ship.cpp b/StarsEx/Ship.cpp index bc30e88..aebb1f0 100644 --- a/StarsEx/Ship.cpp +++ b/StarsEx/Ship.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Ship.h b/StarsEx/Ship.h index 26cf971..cdf38bd 100644 --- a/StarsEx/Ship.h +++ b/StarsEx/Ship.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipAI.cpp b/StarsEx/ShipAI.cpp index 4030f34..bc0fc76 100644 --- a/StarsEx/ShipAI.cpp +++ b/StarsEx/ShipAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipAI.h b/StarsEx/ShipAI.h index 610a5a9..e706c4b 100644 --- a/StarsEx/ShipAI.h +++ b/StarsEx/ShipAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipCtrl.cpp b/StarsEx/ShipCtrl.cpp index aaa583d..bcd5a47 100644 --- a/StarsEx/ShipCtrl.cpp +++ b/StarsEx/ShipCtrl.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipCtrl.h b/StarsEx/ShipCtrl.h index 69391ae..5bb0218 100644 --- a/StarsEx/ShipCtrl.h +++ b/StarsEx/ShipCtrl.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipDesign.cpp b/StarsEx/ShipDesign.cpp index 9cb2fa0..9b4be4c 100644 --- a/StarsEx/ShipDesign.cpp +++ b/StarsEx/ShipDesign.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipDesign.h b/StarsEx/ShipDesign.h index 80d8ea4..b8dffc5 100644 --- a/StarsEx/ShipDesign.h +++ b/StarsEx/ShipDesign.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipKiller.cpp b/StarsEx/ShipKiller.cpp index f071115..325ca83 100644 --- a/StarsEx/ShipKiller.cpp +++ b/StarsEx/ShipKiller.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipKiller.h b/StarsEx/ShipKiller.h index 9e3d430..bfbe8f7 100644 --- a/StarsEx/ShipKiller.h +++ b/StarsEx/ShipKiller.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipSolid.cpp b/StarsEx/ShipSolid.cpp index bffcc54..8254d6b 100644 --- a/StarsEx/ShipSolid.cpp +++ b/StarsEx/ShipSolid.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/ShipSolid.h b/StarsEx/ShipSolid.h index 02d2322..aace5d8 100644 --- a/StarsEx/ShipSolid.h +++ b/StarsEx/ShipSolid.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Shot.cpp b/StarsEx/Shot.cpp index 8a83d1c..dc49189 100644 --- a/StarsEx/Shot.cpp +++ b/StarsEx/Shot.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Shot.h b/StarsEx/Shot.h index aae242c..35fc1dd 100644 --- a/StarsEx/Shot.h +++ b/StarsEx/Shot.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sim.cpp b/StarsEx/Sim.cpp index 6929e44..23b01c9 100644 --- a/StarsEx/Sim.cpp +++ b/StarsEx/Sim.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sim.h b/StarsEx/Sim.h index cf8696b..912a420 100644 --- a/StarsEx/Sim.h +++ b/StarsEx/Sim.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SimEvent.cpp b/StarsEx/SimEvent.cpp index 4fad773..35eb117 100644 --- a/StarsEx/SimEvent.cpp +++ b/StarsEx/SimEvent.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SimEvent.h b/StarsEx/SimEvent.h index d4fe795..66d6342 100644 --- a/StarsEx/SimEvent.h +++ b/StarsEx/SimEvent.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SimObject.cpp b/StarsEx/SimObject.cpp index 24fac59..60c2295 100644 --- a/StarsEx/SimObject.cpp +++ b/StarsEx/SimObject.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SimObject.h b/StarsEx/SimObject.h index 10fcfbf..0985e99 100644 --- a/StarsEx/SimObject.h +++ b/StarsEx/SimObject.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Skin.cpp b/StarsEx/Skin.cpp index b5bd8ab..2703738 100644 --- a/StarsEx/Skin.cpp +++ b/StarsEx/Skin.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Skin.h b/StarsEx/Skin.h index a0478f4..45a500a 100644 --- a/StarsEx/Skin.h +++ b/StarsEx/Skin.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sky.cpp b/StarsEx/Sky.cpp index ff25044..76f31a8 100644 --- a/StarsEx/Sky.cpp +++ b/StarsEx/Sky.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sky.h b/StarsEx/Sky.h index 2ea0c59..b446c6b 100644 --- a/StarsEx/Sky.h +++ b/StarsEx/Sky.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Slider.cpp b/StarsEx/Slider.cpp index 2970ac6..9238623 100644 --- a/StarsEx/Slider.cpp +++ b/StarsEx/Slider.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Slider.h b/StarsEx/Slider.h index 6221803..e824f36 100644 --- a/StarsEx/Slider.h +++ b/StarsEx/Slider.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Solid.cpp b/StarsEx/Solid.cpp index ff4f610..39b6882 100644 --- a/StarsEx/Solid.cpp +++ b/StarsEx/Solid.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Solid.h b/StarsEx/Solid.h index e02d8b2..1b51a68 100644 --- a/StarsEx/Solid.h +++ b/StarsEx/Solid.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sound.cpp b/StarsEx/Sound.cpp index 01537e9..5338387 100644 --- a/StarsEx/Sound.cpp +++ b/StarsEx/Sound.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sound.h b/StarsEx/Sound.h index 3837a7b..1b86b65 100644 --- a/StarsEx/Sound.h +++ b/StarsEx/Sound.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SoundCard.cpp b/StarsEx/SoundCard.cpp index 1e54cce..4eb38ee 100644 --- a/StarsEx/SoundCard.cpp +++ b/StarsEx/SoundCard.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SoundCard.h b/StarsEx/SoundCard.h index a791c81..bd809c0 100644 --- a/StarsEx/SoundCard.h +++ b/StarsEx/SoundCard.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SoundD3D.cpp b/StarsEx/SoundD3D.cpp index 803b85a..68c1dca 100644 --- a/StarsEx/SoundD3D.cpp +++ b/StarsEx/SoundD3D.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SoundD3D.h b/StarsEx/SoundD3D.h index a667182..db75208 100644 --- a/StarsEx/SoundD3D.h +++ b/StarsEx/SoundD3D.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sprite.cpp b/StarsEx/Sprite.cpp index a845344..f96d7d8 100644 --- a/StarsEx/Sprite.cpp +++ b/StarsEx/Sprite.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Sprite.h b/StarsEx/Sprite.h index e3e3915..537dee4 100644 --- a/StarsEx/Sprite.h +++ b/StarsEx/Sprite.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/StarSystem.cpp b/StarsEx/StarSystem.cpp index 4409023..b6037b5 100644 --- a/StarsEx/StarSystem.cpp +++ b/StarsEx/StarSystem.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/StarSystem.h b/StarsEx/StarSystem.h index f5cd92c..0dd2db1 100644 --- a/StarsEx/StarSystem.h +++ b/StarsEx/StarSystem.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Starshatter.cpp b/StarsEx/Starshatter.cpp index 0d448f1..3decdae 100644 --- a/StarsEx/Starshatter.cpp +++ b/StarsEx/Starshatter.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Starshatter.h b/StarsEx/Starshatter.h index 78673cb..f6e5cfd 100644 --- a/StarsEx/Starshatter.h +++ b/StarsEx/Starshatter.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/StarshipAI.cpp b/StarsEx/StarshipAI.cpp index 69abdae..8b10a49 100644 --- a/StarsEx/StarshipAI.cpp +++ b/StarsEx/StarshipAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/StarshipAI.h b/StarsEx/StarshipAI.h index 59a27a9..d84380e 100644 --- a/StarsEx/StarshipAI.h +++ b/StarsEx/StarshipAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/StarshipTacticalAI.cpp b/StarsEx/StarshipTacticalAI.cpp index 4e20c1b..b57cc87 100644 --- a/StarsEx/StarshipTacticalAI.cpp +++ b/StarsEx/StarshipTacticalAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/StarshipTacticalAI.h b/StarsEx/StarshipTacticalAI.h index d58b639..afe2616 100644 --- a/StarsEx/StarshipTacticalAI.h +++ b/StarsEx/StarshipTacticalAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SteerAI.cpp b/StarsEx/SteerAI.cpp index 6bc758a..043cd80 100644 --- a/StarsEx/SteerAI.cpp +++ b/StarsEx/SteerAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SteerAI.h b/StarsEx/SteerAI.h index 3227db4..d33e492 100644 --- a/StarsEx/SteerAI.h +++ b/StarsEx/SteerAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/System.cpp b/StarsEx/System.cpp index 111addc..201c926 100644 --- a/StarsEx/System.cpp +++ b/StarsEx/System.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/System.h b/StarsEx/System.h index d56c502..70262a8 100644 --- a/StarsEx/System.h +++ b/StarsEx/System.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SystemDesign.cpp b/StarsEx/SystemDesign.cpp index 97b65a3..4c64f57 100644 --- a/StarsEx/SystemDesign.cpp +++ b/StarsEx/SystemDesign.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/SystemDesign.h b/StarsEx/SystemDesign.h index 3219e8a..ec09bc2 100644 --- a/StarsEx/SystemDesign.h +++ b/StarsEx/SystemDesign.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TacRefDlg.cpp b/StarsEx/TacRefDlg.cpp index 6afa3ed..9711bf1 100644 --- a/StarsEx/TacRefDlg.cpp +++ b/StarsEx/TacRefDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TacRefDlg.h b/StarsEx/TacRefDlg.h index 07f1f27..b959b47 100644 --- a/StarsEx/TacRefDlg.h +++ b/StarsEx/TacRefDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TacticalAI.cpp b/StarsEx/TacticalAI.cpp index 7f4e64d..474c24f 100644 --- a/StarsEx/TacticalAI.cpp +++ b/StarsEx/TacticalAI.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TacticalAI.h b/StarsEx/TacticalAI.h index 116070c..166d690 100644 --- a/StarsEx/TacticalAI.h +++ b/StarsEx/TacticalAI.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TacticalView.cpp b/StarsEx/TacticalView.cpp index 5bf7653..11cafa5 100644 --- a/StarsEx/TacticalView.cpp +++ b/StarsEx/TacticalView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TacticalView.h b/StarsEx/TacticalView.h index 448a5cc..f6f7bcd 100644 --- a/StarsEx/TacticalView.h +++ b/StarsEx/TacticalView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Terrain.cpp b/StarsEx/Terrain.cpp index 94035a0..d902922 100644 --- a/StarsEx/Terrain.cpp +++ b/StarsEx/Terrain.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Terrain.h b/StarsEx/Terrain.h index 2420dca..4f1cefd 100644 --- a/StarsEx/Terrain.h +++ b/StarsEx/Terrain.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainApron.cpp b/StarsEx/TerrainApron.cpp index 321bcaf..aeb4046 100644 --- a/StarsEx/TerrainApron.cpp +++ b/StarsEx/TerrainApron.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainApron.h b/StarsEx/TerrainApron.h index b83089b..72b265b 100644 --- a/StarsEx/TerrainApron.h +++ b/StarsEx/TerrainApron.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainClouds.cpp b/StarsEx/TerrainClouds.cpp index c8e3b69..6f1ae73 100644 --- a/StarsEx/TerrainClouds.cpp +++ b/StarsEx/TerrainClouds.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainClouds.h b/StarsEx/TerrainClouds.h index dcabaa3..29cf28e 100644 --- a/StarsEx/TerrainClouds.h +++ b/StarsEx/TerrainClouds.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainHaze.cpp b/StarsEx/TerrainHaze.cpp index f10ddc2..b058487 100644 --- a/StarsEx/TerrainHaze.cpp +++ b/StarsEx/TerrainHaze.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainHaze.h b/StarsEx/TerrainHaze.h index 3cf0d44..ab70aa8 100644 --- a/StarsEx/TerrainHaze.h +++ b/StarsEx/TerrainHaze.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainLayer.h b/StarsEx/TerrainLayer.h index 8327da4..bbafc7f 100644 --- a/StarsEx/TerrainLayer.h +++ b/StarsEx/TerrainLayer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainPatch.cpp b/StarsEx/TerrainPatch.cpp index ee2f6d6..0173f58 100644 --- a/StarsEx/TerrainPatch.cpp +++ b/StarsEx/TerrainPatch.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainPatch.h b/StarsEx/TerrainPatch.h index db91833..6f1ee6b 100644 --- a/StarsEx/TerrainPatch.h +++ b/StarsEx/TerrainPatch.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainRegion.cpp b/StarsEx/TerrainRegion.cpp index 0a05df0..9e6d6ad 100644 --- a/StarsEx/TerrainRegion.cpp +++ b/StarsEx/TerrainRegion.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TerrainRegion.h b/StarsEx/TerrainRegion.h index 5f84bab..bd7598e 100644 --- a/StarsEx/TerrainRegion.h +++ b/StarsEx/TerrainRegion.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TexCubeDX9.cpp b/StarsEx/TexCubeDX9.cpp index c2e5a89..c651b29 100644 --- a/StarsEx/TexCubeDX9.cpp +++ b/StarsEx/TexCubeDX9.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TexCubeDX9.h b/StarsEx/TexCubeDX9.h index 0b1b5ee..800481d 100644 --- a/StarsEx/TexCubeDX9.h +++ b/StarsEx/TexCubeDX9.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TexDX9.cpp b/StarsEx/TexDX9.cpp index b2c5b2b..dc38904 100644 --- a/StarsEx/TexDX9.cpp +++ b/StarsEx/TexDX9.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TexDX9.h b/StarsEx/TexDX9.h index 247b1ad..9b1b11e 100644 --- a/StarsEx/TexDX9.h +++ b/StarsEx/TexDX9.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Thruster.cpp b/StarsEx/Thruster.cpp index 3852516..16f3710 100644 --- a/StarsEx/Thruster.cpp +++ b/StarsEx/Thruster.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Thruster.h b/StarsEx/Thruster.h index 7db4a8f..ea98fd9 100644 --- a/StarsEx/Thruster.h +++ b/StarsEx/Thruster.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TrackIR.cpp b/StarsEx/TrackIR.cpp index 87dd937..3185909 100644 --- a/StarsEx/TrackIR.cpp +++ b/StarsEx/TrackIR.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/TrackIR.h b/StarsEx/TrackIR.h index c402f10..58c23e9 100644 --- a/StarsEx/TrackIR.h +++ b/StarsEx/TrackIR.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Trail.cpp b/StarsEx/Trail.cpp index 025bc81..c30f5fd 100644 --- a/StarsEx/Trail.cpp +++ b/StarsEx/Trail.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Trail.h b/StarsEx/Trail.h index 8f90470..ead1e40 100644 --- a/StarsEx/Trail.h +++ b/StarsEx/Trail.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Types.h b/StarsEx/Types.h index edd47ba..20ac1ac 100644 --- a/StarsEx/Types.h +++ b/StarsEx/Types.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/UIEventDispatch.cpp b/StarsEx/UIEventDispatch.cpp index 8c69bea..d4d3e64 100644 --- a/StarsEx/UIEventDispatch.cpp +++ b/StarsEx/UIEventDispatch.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/UIEventDispatch.h b/StarsEx/UIEventDispatch.h index 442a539..b165ed2 100644 --- a/StarsEx/UIEventDispatch.h +++ b/StarsEx/UIEventDispatch.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/UIEventTarget.h b/StarsEx/UIEventTarget.h index c8acd4c..72e602c 100644 --- a/StarsEx/UIEventTarget.h +++ b/StarsEx/UIEventTarget.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Universe.h b/StarsEx/Universe.h index f8e9fdd..17ca4a4 100644 --- a/StarsEx/Universe.h +++ b/StarsEx/Universe.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VersionInfo.h b/StarsEx/VersionInfo.h index 44c55dc..0ae40e8 100644 --- a/StarsEx/VersionInfo.h +++ b/StarsEx/VersionInfo.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/VidDlg.cpp b/StarsEx/VidDlg.cpp index 5bed504..60e793b 100644 --- a/StarsEx/VidDlg.cpp +++ b/StarsEx/VidDlg.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VidDlg.h b/StarsEx/VidDlg.h index 8b30dcb..cfc4d9d 100644 --- a/StarsEx/VidDlg.h +++ b/StarsEx/VidDlg.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Video.cpp b/StarsEx/Video.cpp index 368f50c..7add62a 100644 --- a/StarsEx/Video.cpp +++ b/StarsEx/Video.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Video.h b/StarsEx/Video.h index 8729581..607a9e1 100644 --- a/StarsEx/Video.h +++ b/StarsEx/Video.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoDX9.cpp b/StarsEx/VideoDX9.cpp index 06a02a0..4d1a14e 100644 --- a/StarsEx/VideoDX9.cpp +++ b/StarsEx/VideoDX9.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoDX9.h b/StarsEx/VideoDX9.h index f740a20..31f99be 100644 --- a/StarsEx/VideoDX9.h +++ b/StarsEx/VideoDX9.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoDX9Enum.cpp b/StarsEx/VideoDX9Enum.cpp index c254513..1cbf67c 100644 --- a/StarsEx/VideoDX9Enum.cpp +++ b/StarsEx/VideoDX9Enum.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoDX9Enum.h b/StarsEx/VideoDX9Enum.h index 91279aa..072dd95 100644 --- a/StarsEx/VideoDX9Enum.h +++ b/StarsEx/VideoDX9Enum.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoDX9VertexBuffer.cpp b/StarsEx/VideoDX9VertexBuffer.cpp index 6febba5..223f971 100644 --- a/StarsEx/VideoDX9VertexBuffer.cpp +++ b/StarsEx/VideoDX9VertexBuffer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoDX9VertexBuffer.h b/StarsEx/VideoDX9VertexBuffer.h index 035bb88..080dc91 100644 --- a/StarsEx/VideoDX9VertexBuffer.h +++ b/StarsEx/VideoDX9VertexBuffer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoFactory.cpp b/StarsEx/VideoFactory.cpp index 68da591..f6d7ba1 100644 --- a/StarsEx/VideoFactory.cpp +++ b/StarsEx/VideoFactory.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoFactory.h b/StarsEx/VideoFactory.h index 8c1c50d..a0db270 100644 --- a/StarsEx/VideoFactory.h +++ b/StarsEx/VideoFactory.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoSettings.cpp b/StarsEx/VideoSettings.cpp index 3c8c768..0de2b4b 100644 --- a/StarsEx/VideoSettings.cpp +++ b/StarsEx/VideoSettings.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/VideoSettings.h b/StarsEx/VideoSettings.h index a4b7396..2919874 100644 --- a/StarsEx/VideoSettings.h +++ b/StarsEx/VideoSettings.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/View.h b/StarsEx/View.h index e986417..222a65e 100644 --- a/StarsEx/View.h +++ b/StarsEx/View.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Water.cpp b/StarsEx/Water.cpp index 5509938..04631d9 100644 --- a/StarsEx/Water.cpp +++ b/StarsEx/Water.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Water.h b/StarsEx/Water.h index 0dfe6eb..5612abf 100644 --- a/StarsEx/Water.h +++ b/StarsEx/Water.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Wave.h b/StarsEx/Wave.h index 441f323..43b982a 100644 --- a/StarsEx/Wave.h +++ b/StarsEx/Wave.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Weapon.cpp b/StarsEx/Weapon.cpp index b5a0fd3..77ac1fa 100644 --- a/StarsEx/Weapon.cpp +++ b/StarsEx/Weapon.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Weapon.h b/StarsEx/Weapon.h index d8e0082..082abb2 100644 --- a/StarsEx/Weapon.h +++ b/StarsEx/Weapon.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/WeaponDesign.cpp b/StarsEx/WeaponDesign.cpp index aa116b0..3dd826d 100644 --- a/StarsEx/WeaponDesign.cpp +++ b/StarsEx/WeaponDesign.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/WeaponDesign.h b/StarsEx/WeaponDesign.h index 712d220..4fa97d4 100644 --- a/StarsEx/WeaponDesign.h +++ b/StarsEx/WeaponDesign.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/WeaponGroup.cpp b/StarsEx/WeaponGroup.cpp index 5519c68..70fe18f 100644 --- a/StarsEx/WeaponGroup.cpp +++ b/StarsEx/WeaponGroup.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/WeaponGroup.h b/StarsEx/WeaponGroup.h index 7b2b1bd..a35ba76 100644 --- a/StarsEx/WeaponGroup.h +++ b/StarsEx/WeaponGroup.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Weather.cpp b/StarsEx/Weather.cpp index b894b3e..8d3ded6 100644 --- a/StarsEx/Weather.cpp +++ b/StarsEx/Weather.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Weather.h b/StarsEx/Weather.h index e10da74..b08cce4 100644 --- a/StarsEx/Weather.h +++ b/StarsEx/Weather.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/WepView.cpp b/StarsEx/WepView.cpp index 82ce103..5fdbfa9 100644 --- a/StarsEx/WepView.cpp +++ b/StarsEx/WepView.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/WepView.h b/StarsEx/WepView.h index 0a3b8d8..95171e1 100644 --- a/StarsEx/WepView.h +++ b/StarsEx/WepView.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Window.cpp b/StarsEx/Window.cpp index c04d45b..54015e5 100644 --- a/StarsEx/Window.cpp +++ b/StarsEx/Window.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/Window.h b/StarsEx/Window.h index f9a143f..c2ac09b 100644 --- a/StarsEx/Window.h +++ b/StarsEx/Window.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/StarsEx/WndProc.cpp b/StarsEx/WndProc.cpp index 0c48236..0078bfe 100644 --- a/StarsEx/WndProc.cpp +++ b/StarsEx/WndProc.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/StarsEx/WndProc.h b/StarsEx/WndProc.h index 715ebef..2f04d62 100644 --- a/StarsEx/WndProc.h +++ b/StarsEx/WndProc.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/Starserver/Main.cpp b/Starserver/Main.cpp index ef1a611..b3632e7 100644 --- a/Starserver/Main.cpp +++ b/Starserver/Main.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. */ diff --git a/Starserver/NetAdminChat.cpp b/Starserver/NetAdminChat.cpp index b8241b5..b627ae0 100644 --- a/Starserver/NetAdminChat.cpp +++ b/Starserver/NetAdminChat.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/Starserver/NetAdminChat.h b/Starserver/NetAdminChat.h index 6295f40..8012b39 100644 --- a/Starserver/NetAdminChat.h +++ b/Starserver/NetAdminChat.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/Starserver/NetAdminServer.cpp b/Starserver/NetAdminServer.cpp index c30880b..0880293 100644 --- a/Starserver/NetAdminServer.cpp +++ b/Starserver/NetAdminServer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/Starserver/NetAdminServer.h b/Starserver/NetAdminServer.h index 5c009e8..6eba2b1 100644 --- a/Starserver/NetAdminServer.h +++ b/Starserver/NetAdminServer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/Starserver/NetFileServlet.cpp b/Starserver/NetFileServlet.cpp index 431bdb6..11cb0a6 100644 --- a/Starserver/NetFileServlet.cpp +++ b/Starserver/NetFileServlet.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/Starserver/NetFileServlet.h b/Starserver/NetFileServlet.h index 3d21043..a4815dc 100644 --- a/Starserver/NetFileServlet.h +++ b/Starserver/NetFileServlet.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/Starserver/StarServer.cpp b/Starserver/StarServer.cpp index ea10639..787a5c0 100644 --- a/Starserver/StarServer.cpp +++ b/Starserver/StarServer.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/Starserver/StarServer.h b/Starserver/StarServer.h index 68f69f2..d5ed58b 100644 --- a/Starserver/StarServer.h +++ b/Starserver/StarServer.h @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/Starshatter/Main.cpp b/Starshatter/Main.cpp index beda5d0..58fb891 100644 --- a/Starshatter/Main.cpp +++ b/Starshatter/Main.cpp @@ -1,5 +1,5 @@ /* Starshatter: The Open Source Project - Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt deleted file mode 100644 index 2c9f2f1..0000000 --- a/contrib/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -include(ApplyPatch) -include(FetchContent) -include(MakeAvailable) -add_subdirectory(gtest) -add_subdirectory(infoware) -add_subdirectory(libpng) -add_subdirectory(ogg) -add_subdirectory(vorbis) -add_subdirectory(zlib) -make_available(gtest infoware libpng ogg vorbis zlib) -add_subdirectory(Opcode) -add_subdirectory(sha1) -install( - TARGETS png15 Opcode - RUNTIME - COMPONENT Runtime - DESTINATION ${CMAKE_INSTALL_PREFIX} - ) -if(NOT MSVC) - foreach(LIB IN ITEMS "libstdc++-6.dll" "libwinpthread-1.dll" "libgcc_s_dw2-1.dll") - find_file(LIBRARY_${LIB} ${LIB} PATHS ${CMAKE_FIND_ROOT_PATH}/bin) - if(LIBRARY_${LIB}) - install( - PROGRAMS ${LIBRARY_${LIB}} - COMPONENT Runtime - DESTINATION ${CMAKE_INSTALL_PREFIX} - ) - endif() - endforeach() -endif() diff --git a/contrib/Opcode/CMakeLists.txt b/contrib/Opcode/CMakeLists.txt deleted file mode 100644 index 6010c50..0000000 --- a/contrib/Opcode/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -project(Opcode) -add_library( - Opcode - SHARED - OPC_AABBCollider.cpp - OPC_AABBTree.cpp - OPC_BaseModel.cpp - OPC_BoxPruning.cpp - OPC_Collider.cpp - OPC_Common.cpp - OPC_HybridModel.cpp - OPC_LSSCollider.cpp - OPC_MeshInterface.cpp - OPC_Model.cpp - OPC_OBBCollider.cpp - OPC_OptimizedTree.cpp - OPC_Picking.cpp - OPC_PlanesCollider.cpp - OPC_RayCollider.cpp - OPC_SphereCollider.cpp - OPC_SweepAndPrune.cpp - OPC_TreeBuilders.cpp - OPC_TreeCollider.cpp - OPC_VolumeCollider.cpp - Opcode.cpp - StdAfx.cpp - Ice/IceAABB.cpp - Ice/IceContainer.cpp - Ice/IceHPoint.cpp - Ice/IceIndexedTriangle.cpp - Ice/IceMatrix3x3.cpp - Ice/IceMatrix4x4.cpp - Ice/IceOBB.cpp - Ice/IcePlane.cpp - Ice/IcePoint.cpp - Ice/IceRandom.cpp - Ice/IceRay.cpp - Ice/IceRevisitedRadix.cpp - Ice/IceSegment.cpp - Ice/IceTriangle.cpp - Ice/IceUtils.cpp - ) -target_include_directories( - Opcode - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - ) -target_precompile_headers( - Opcode - PUBLIC StdAfx.h - ) -target_compile_definitions( - Opcode - PRIVATE OPCODE_EXPORTS - PUBLIC _ALLOW_KEYWORD_MACROS - ) diff --git a/contrib/Opcode/Doc/OpcodeUserManual.pdf b/contrib/Opcode/Doc/OpcodeUserManual.pdf deleted file mode 100644 index 4ca3f12..0000000 Binary files a/contrib/Opcode/Doc/OpcodeUserManual.pdf and /dev/null differ diff --git a/contrib/Opcode/Ice/IceAABB.cpp b/contrib/Opcode/Ice/IceAABB.cpp deleted file mode 100644 index 03bca6c..0000000 --- a/contrib/Opcode/Ice/IceAABB.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains AABB-related code. - * \file IceAABB.cpp - * \author Pierre Terdiman - * \date January, 29, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * AABB class. - * \class AABB - * \author Pierre Terdiman - * \version 1.0 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the sum of two AABBs. - * \param aabb [in] the other AABB - * \return Self-Reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABB& AABB::Add(const AABB& aabb) -{ - // Compute new min & max values - IcePoint Min; GetMin(Min); - IcePoint Tmp; aabb.GetMin(Tmp); - Min.Min(Tmp); - - IcePoint Max; GetMax(Max); - aabb.GetMax(Tmp); - Max.Max(Tmp); - - // Update this - SetMinMax(Min, Max); - return *this; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Makes a cube from the AABB. - * \param cube [out] the cube AABB - * \return cube edge length - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float AABB::MakeCube(AABB& cube) const -{ - IcePoint Ext; GetExtents(Ext); - float Max = Ext.Max(); - - IcePoint Cnt; GetCenter(Cnt); - cube.SetCenterExtents(Cnt, IcePoint(Max, Max, Max)); - return Max; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Makes a sphere from the AABB. - * \param sphere [out] sphere containing the AABB - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABB::MakeSphere(Sphere& sphere) const -{ - GetExtents(sphere.mCenter); - sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f; // To make sure sphere::Contains(*this) succeeds - GetCenter(sphere.mCenter); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks a box is inside another box. - * \param box [in] the other AABB - * \return true if current box is inside input box - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABB::IsInside(const AABB& box) const -{ - if(box.GetMin(0)>GetMin(0)) return false; - if(box.GetMin(1)>GetMin(1)) return false; - if(box.GetMin(2)>GetMin(2)) return false; - if(box.GetMax(0) max.x) ? 2 : 0) // 2 = right - + ((local_eye.y < min.y) ? 4 : 0) // 4 = bottom - + ((local_eye.y > max.y) ? 8 : 0) // 8 = top - + ((local_eye.z < min.z) ? 16 : 0) // 16 = front - + ((local_eye.z > max.z) ? 32 : 0); // 32 = back - - // Look up number of vertices in outline - num = (sdword)gIndexList[pos][7]; - // Zero indicates invalid case - if(!num) return null; - - return &gIndexList[pos][0]; -} - -// calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box - -//const IcePoint& eye, //eye point (in bbox object coordinates) -//const AABB& box, //3d bbox -//const Matrix4x4& mat, //free transformation for bbox -//float width, float height, int& num) -float AABB::ComputeBoxArea(const IcePoint& eye, const Matrix4x4& mat, float width, float height, sdword& num) const -{ - const sbyte* Outline = ComputeOutline(eye, num); - if(!Outline) return -1.0f; - - // Compute box vertices - IcePoint vertexBox[8], dst[8]; - ComputePoints(vertexBox); - - // Transform all outline corners into 2D screen space - for(sdword i=0;i GetMax(0) || p.x < GetMin(0)) return FALSE; \ - if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \ - if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \ - return TRUE; \ - } - - enum AABBType - { - AABB_RENDER = 0, //!< AABB used for rendering. Not visible == not rendered. - AABB_UPDATE = 1, //!< AABB used for dynamic updates. Not visible == not updated. - - AABB_FORCE_DWORD = 0x7fffffff, - }; - -#ifdef USE_MINMAX - - struct ICEMATHS_API ShadowAABB - { - Point mMin; - Point mMax; - }; - - class ICEMATHS_API AABB - { - public: - //! Constructor - inline_ AABB() {} - //! Destructor - inline_ ~AABB() {} - - //! Type-independent methods - AABB_COMMON_METHODS; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups an AABB from min & max vectors. - * \param min [in] the min point - * \param max [in] the max point - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups an AABB from center & extents vectors. - * \param c [in] the center point - * \param e [in] the extents vector - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups an empty AABB. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;} - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups a point AABB. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetPoint(const Point& pt) { mMin = mMax = pt; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the size of the AABB. The size is defined as the longest extent. - * \return the size of the AABB - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - float GetSize() const { Point e; GetExtents(e); return e.Max(); } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Extends the AABB. - * \param p [in] the next point - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Extend(const Point& p) - { - if(p.x > mMax.x) mMax.x = p.x; - if(p.x < mMin.x) mMin.x = p.x; - - if(p.y > mMax.y) mMax.y = p.y; - if(p.y < mMin.y) mMin.y = p.y; - - if(p.z > mMax.z) mMax.z = p.z; - if(p.z < mMin.z) mMin.z = p.z; - } - // Data access - - //! Get min point of the box - inline_ void GetMin(Point& min) const { min = mMin; } - //! Get max point of the box - inline_ void GetMax(Point& max) const { max = mMax; } - - //! Get component of the box's min point along a given axis - inline_ float GetMin(udword axis) const { return mMin[axis]; } - //! Get component of the box's max point along a given axis - inline_ float GetMax(udword axis) const { return mMax[axis]; } - - //! Get box center - inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; } - //! Get box extents - inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; } - - //! Get component of the box's center along a given axis - inline_ float GetCenter(udword axis) const { return (mMax[axis] + mMin[axis])*0.5f; } - //! Get component of the box's extents along a given axis - inline_ float GetExtents(udword axis) const { return (mMax[axis] - mMin[axis])*0.5f; } - - //! Get box diagonal - inline_ void GetDiagonal(Point& diagonal) const { diagonal = mMax - mMin; } - inline_ float GetWidth() const { return mMax.x - mMin.x; } - inline_ float GetHeight() const { return mMax.y - mMin.y; } - inline_ float GetDepth() const { return mMax.z - mMin.z; } - - //! Volume - inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes the intersection between two AABBs. - * \param a [in] the other AABB - * \return true on intersection - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL Intersect(const AABB& a) const - { - if(mMax.x < a.mMin.x - || a.mMax.x < mMin.x - || mMax.y < a.mMin.y - || a.mMax.y < mMin.y - || mMax.z < a.mMin.z - || a.mMax.z < mMin.z) return FALSE; - - return TRUE; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes the 1D-intersection between two AABBs, on a given axis. - * \param a [in] the other AABB - * \param axis [in] the axis (0, 1, 2) - * \return true on intersection - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL Intersect(const AABB& a, udword axis) const - { - if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE; - return TRUE; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. - * Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it) - * \param mtx [in] the transform matrix - * \param aabb [out] the transformed AABB [can be *this] - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const - { - // The three edges transformed: you can efficiently transform an X-only vector - // by just getting the "X" column of the matrix - Point vx,vy,vz; - mtx.GetRow(0, vx); vx *= (mMax.x - mMin.x); - mtx.GetRow(1, vy); vy *= (mMax.y - mMin.y); - mtx.GetRow(2, vz); vz *= (mMax.z - mMin.z); - - // Transform the min point - aabb.mMin = aabb.mMax = mMin * mtx; - - // Take the transformed min & axes and find new extents - // Using CPU code in the right place is faster... - if(IS_NEGATIVE_FLOAT(vx.x)) aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x; - if(IS_NEGATIVE_FLOAT(vx.y)) aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y; - if(IS_NEGATIVE_FLOAT(vx.z)) aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z; - if(IS_NEGATIVE_FLOAT(vy.x)) aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x; - if(IS_NEGATIVE_FLOAT(vy.y)) aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y; - if(IS_NEGATIVE_FLOAT(vy.z)) aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z; - if(IS_NEGATIVE_FLOAT(vz.x)) aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x; - if(IS_NEGATIVE_FLOAT(vz.y)) aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y; - if(IS_NEGATIVE_FLOAT(vz.z)) aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks the AABB is valid. - * \return true if the box is valid - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL IsValid() const - { - // Consistency condition for (Min, Max) boxes: min < max - if(mMin.x > mMax.x) return FALSE; - if(mMin.y > mMax.y) return FALSE; - if(mMin.z > mMax.z) return FALSE; - return TRUE; - } - - //! Operator for AABB *= float. Scales the extents, keeps same center. - inline_ AABB& operator*=(float s) - { - Point Center; GetCenter(Center); - Point Extents; GetExtents(Extents); - SetCenterExtents(Center, Extents * s); - return *this; - } - - //! Operator for AABB /= float. Scales the extents, keeps same center. - inline_ AABB& operator/=(float s) - { - Point Center; GetCenter(Center); - Point Extents; GetExtents(Extents); - SetCenterExtents(Center, Extents / s); - return *this; - } - - //! Operator for AABB += Point. Translates the box. - inline_ AABB& operator+=(const Point& trans) - { - mMin+=trans; - mMax+=trans; - return *this; - } - private: - Point mMin; //!< Min point - Point mMax; //!< Max point - }; - -#else - - class ICEMATHS_API AABB - { - public: - //! Constructor - inline_ AABB() {} - //! Destructor - inline_ ~AABB() {} - - //! Type-independent methods - AABB_COMMON_METHODS; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups an AABB from min & max vectors. - * \param min [in] the min point - * \param max [in] the max point - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetMinMax(const IcePoint& min, const IcePoint& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups an AABB from center & extents vectors. - * \param c [in] the center point - * \param e [in] the extents vector - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetCenterExtents(const IcePoint& c, const IcePoint& e) { mCenter = c; mExtents = e; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups an empty AABB. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);} - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups a point AABB. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetPoint(const IcePoint& pt) { mCenter = pt; mExtents.Zero(); } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the size of the AABB. The size is defined as the longest extent. - * \return the size of the AABB - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - float GetSize() const { return mExtents.Max(); } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Extends the AABB. - * \param p [in] the next point - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Extend(const IcePoint& p) - { - IcePoint Max = mCenter + mExtents; - IcePoint Min = mCenter - mExtents; - - if(p.x > Max.x) Max.x = p.x; - if(p.x < Min.x) Min.x = p.x; - - if(p.y > Max.y) Max.y = p.y; - if(p.y < Min.y) Min.y = p.y; - - if(p.z > Max.z) Max.z = p.z; - if(p.z < Min.z) Min.z = p.z; - - SetMinMax(Min, Max); - } - // Data access - - //! Get min point of the box - inline_ void GetMin(IcePoint& min) const { min = mCenter - mExtents; } - //! Get max point of the box - inline_ void GetMax(IcePoint& max) const { max = mCenter + mExtents; } - - //! Get component of the box's min point along a given axis - inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } - //! Get component of the box's max point along a given axis - inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } - - //! Get box center - inline_ void GetCenter(IcePoint& center) const { center = mCenter; } - //! Get box extents - inline_ void GetExtents(IcePoint& extents) const { extents = mExtents; } - - //! Get component of the box's center along a given axis - inline_ float GetCenter(udword axis) const { return mCenter[axis]; } - //! Get component of the box's extents along a given axis - inline_ float GetExtents(udword axis) const { return mExtents[axis]; } - - //! Get box diagonal - inline_ void GetDiagonal(IcePoint& diagonal) const { diagonal = mExtents * 2.0f; } - inline_ float GetWidth() const { return mExtents.x * 2.0f; } - inline_ float GetHeight() const { return mExtents.y * 2.0f; } - inline_ float GetDepth() const { return mExtents.z * 2.0f; } - - //! Volume - inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes the intersection between two AABBs. - * \param a [in] the other AABB - * \return true on intersection - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL Intersect(const AABB& a) const - { - float tx = mCenter.x - a.mCenter.x; float ex = a.mExtents.x + mExtents.x; if(AIR(tx) > IR(ex)) return FALSE; - float ty = mCenter.y - a.mCenter.y; float ey = a.mExtents.y + mExtents.y; if(AIR(ty) > IR(ey)) return FALSE; - float tz = mCenter.z - a.mCenter.z; float ez = a.mExtents.z + mExtents.z; if(AIR(tz) > IR(ez)) return FALSE; - return TRUE; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * The standard intersection method from Gamasutra. Just here to check its speed against the one above. - * \param a [in] the other AABB - * \return true on intersection - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ bool GomezIntersect(const AABB& a) - { - IcePoint T = mCenter - a.mCenter; // Vector from A to B - return ((fabsf(T.x) <= (a.mExtents.x + mExtents.x)) - && (fabsf(T.y) <= (a.mExtents.y + mExtents.y)) - && (fabsf(T.z) <= (a.mExtents.z + mExtents.z))); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes the 1D-intersection between two AABBs, on a given axis. - * \param a [in] the other AABB - * \param axis [in] the axis (0, 1, 2) - * \return true on intersection - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL Intersect(const AABB& a, udword axis) const - { - float t = mCenter[axis] - a.mCenter[axis]; - float e = a.mExtents[axis] + mExtents[axis]; - if(AIR(t) > IR(e)) return FALSE; - return TRUE; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. - * \param mtx [in] the transform matrix - * \param aabb [out] the transformed AABB [can be *this] - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const - { - // Compute new center - aabb.mCenter = mCenter * mtx; - - // Compute new extents. FPU code & CPU code have been interleaved for improved performance. - IcePoint Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x); - IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff; - - IcePoint Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y); - IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff; - - IcePoint Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z); - IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff; - - aabb.mExtents.x = Ex.x + Ey.x + Ez.x; - aabb.mExtents.y = Ex.y + Ey.y + Ez.y; - aabb.mExtents.z = Ex.z + Ey.z + Ez.z; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks the AABB is valid. - * \return true if the box is valid - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL IsValid() const - { - // Consistency condition for (Center, Extents) boxes: Extents >= 0 - if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE; - if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE; - if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE; - return TRUE; - } - - //! Operator for AABB *= float. Scales the extents, keeps same center. - inline_ AABB& operator*=(float s) { mExtents*=s; return *this; } - - //! Operator for AABB /= float. Scales the extents, keeps same center. - inline_ AABB& operator/=(float s) { mExtents/=s; return *this; } - - //! Operator for AABB += Point. Translates the box. - inline_ AABB& operator+=(const IcePoint& trans) - { - mCenter+=trans; - return *this; - } - private: - IcePoint mCenter; //!< AABB Center - IcePoint mExtents; //!< x, y and z extents - }; - -#endif - - inline_ void ComputeMinMax(const IcePoint& p, IcePoint& min, IcePoint& max) - { - if(p.x > max.x) max.x = p.x; - if(p.x < min.x) min.x = p.x; - - if(p.y > max.y) max.y = p.y; - if(p.y < min.y) min.y = p.y; - - if(p.z > max.z) max.z = p.z; - if(p.z < min.z) min.z = p.z; - } - - inline_ void ComputeAABB(AABB& aabb, const IcePoint* list, udword nb_pts) - { - if(list) - { - IcePoint Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); - IcePoint Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT); - while(nb_pts--) - { -// _prefetch(list+1); // off by one ? - ComputeMinMax(*list++, Mini, Maxi); - } - aabb.SetMinMax(Mini, Maxi); - } - } - -#endif // __ICEAABB_H__ diff --git a/contrib/Opcode/Ice/IceAxes.h b/contrib/Opcode/Ice/IceAxes.h deleted file mode 100644 index 842b55e..0000000 --- a/contrib/Opcode/Ice/IceAxes.h +++ /dev/null @@ -1,54 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains axes definition. - * \file IceAxes.h - * \author Pierre Terdiman - * \date January, 29, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEAXES_H__ -#define __ICEAXES_H__ - - enum PointComponent - { - _X = 0, - _Y = 1, - _Z = 2, - _W = 3, - - _FORCE_DWORD = 0x7fffffff - }; - - enum AxisOrder - { - AXES_XYZ = (_X)|(_Y<<2)|(_Z<<4), - AXES_XZY = (_X)|(_Z<<2)|(_Y<<4), - AXES_YXZ = (_Y)|(_X<<2)|(_Z<<4), - AXES_YZX = (_Y)|(_Z<<2)|(_X<<4), - AXES_ZXY = (_Z)|(_X<<2)|(_Y<<4), - AXES_ZYX = (_Z)|(_Y<<2)|(_X<<4), - - AXES_FORCE_DWORD = 0x7fffffff - }; - - class ICEMATHS_API Axes - { - public: - - inline_ Axes(AxisOrder order) - { - mAxis0 = (order ) & 3; - mAxis1 = (order>>2) & 3; - mAxis2 = (order>>4) & 3; - } - inline_ ~Axes() {} - - udword mAxis0; - udword mAxis1; - udword mAxis2; - }; - -#endif // __ICEAXES_H__ diff --git a/contrib/Opcode/Ice/IceBoundingSphere.h b/contrib/Opcode/Ice/IceBoundingSphere.h deleted file mode 100644 index df2861d..0000000 --- a/contrib/Opcode/Ice/IceBoundingSphere.h +++ /dev/null @@ -1,142 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code to compute the minimal bounding sphere. - * \file IceBoundingSphere.h - * \author Pierre Terdiman - * \date January, 29, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEBOUNDINGSPHERE_H__ -#define __ICEBOUNDINGSPHERE_H__ - - enum BSphereMethod - { - BS_NONE, - BS_GEMS, - BS_MINIBALL, - - BS_FORCE_DWORD = 0x7fffffff - }; - - class ICEMATHS_API Sphere - { - public: - //! Constructor - inline_ Sphere() {} - //! Constructor - inline_ Sphere(const IcePoint& center, float radius) : mCenter(center), mRadius(radius) {} - //! Constructor - Sphere(udword nb_verts, const IcePoint* verts); - //! Copy constructor - inline_ Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius) {} - //! Destructor - inline_ ~Sphere() {} - - BSphereMethod Compute(udword nb_verts, const IcePoint* verts); - bool FastCompute(udword nb_verts, const IcePoint* verts); - - // Access methods - inline_ const IcePoint& GetCenter() const { return mCenter; } - inline_ float GetRadius() const { return mRadius; } - - inline_ const IcePoint& Center() const { return mCenter; } - inline_ float Radius() const { return mRadius; } - - inline_ Sphere& Set(const IcePoint& center, float radius) { mCenter = center; mRadius = radius; return *this; } - inline_ Sphere& SetCenter(const IcePoint& center) { mCenter = center; return *this; } - inline_ Sphere& SetRadius(float radius) { mRadius = radius; return *this; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Tests if a IcePoint is contained within the sphere. - * \param p [in] the IcePoint to test - * \return true if inside the sphere - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ bool Contains(const IcePoint& p) const - { - return mCenter.SquareDistance(p) <= mRadius*mRadius; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Tests if a sphere is contained within the sphere. - * \param sphere [in] the sphere to test - * \return true if inside the sphere - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ bool Contains(const Sphere& sphere) const - { - // If our radius is the smallest, we can't possibly contain the other sphere - if(mRadius < sphere.mRadius) return false; - // So r is always positive or null now - float r = mRadius - sphere.mRadius; - return mCenter.SquareDistance(sphere.mCenter) <= r*r; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Tests if a box is contained within the sphere. - * \param aabb [in] the box to test - * \return true if inside the sphere - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL Contains(const AABB& aabb) const - { - // I assume if all 8 box vertices are inside the sphere, so does the whole box. - // Sounds ok but maybe there's a better way? - float R2 = mRadius * mRadius; -#ifdef USE_MIN_MAX - const IcePoint& Max = ((ShadowAABB&)&aabb).mMax; - const IcePoint& Min = ((ShadowAABB&)&aabb).mMin; -#else - IcePoint Max; aabb.GetMax(Max); - IcePoint Min; aabb.GetMin(Min); -#endif - IcePoint p; - p.x=Max.x; p.y=Max.y; p.z=Max.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; - p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; - p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; - p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; - p.x=Max.x; p.y=Max.y; p.z=Min.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; - p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; - p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; - p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; - - return TRUE; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Tests if the sphere intersects another sphere - * \param sphere [in] the other sphere - * \return true if spheres overlap - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ bool Intersect(const Sphere& sphere) const - { - float r = mRadius + sphere.mRadius; - return mCenter.SquareDistance(sphere.mCenter) <= r*r; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks the sphere is valid. - * \return true if the box is valid - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL IsValid() const - { - // Consistency condition for spheres: Radius >= 0.0f - if(mRadius < 0.0f) return FALSE; - return TRUE; - } - public: - IcePoint mCenter; //!< Sphere center - float mRadius; //!< Sphere radius - }; - -#endif // __ICEBOUNDINGSPHERE_H__ diff --git a/contrib/Opcode/Ice/IceContainer.cpp b/contrib/Opcode/Ice/IceContainer.cpp deleted file mode 100644 index dc59602..0000000 --- a/contrib/Opcode/Ice/IceContainer.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a simple container class. - * \file IceContainer.cpp - * \author Pierre Terdiman - * \date February, 5, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a list of 32-bits values. - * Use this class when you need to store an unknown number of values. The list is automatically - * resized and can contains 32-bits entities (dwords or floats) - * - * \class Container - * \author Pierre Terdiman - * \version 1.0 - * \date 08.15.98 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceCore; - -// Static members -#ifdef CONTAINER_STATS -#ifdef OPCODE_EXPORTS -udword Container::mNbContainers = 0; -udword Container::mUsedRam = 0; -#endif -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. No entries allocated there. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) -{ -#ifdef CONTAINER_STATS - mNbContainers++; - mUsedRam+=sizeof(Container); -#endif -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. Also allocates a given number of entries. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor) -{ -#ifdef CONTAINER_STATS - mNbContainers++; - mUsedRam+=sizeof(Container); -#endif - SetSize(size); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Copy constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) -{ -#ifdef CONTAINER_STATS - mNbContainers++; - mUsedRam+=sizeof(Container); -#endif - *this = object; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. Frees everything and leaves. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Container::~Container() -{ - Empty(); -#ifdef CONTAINER_STATS - mNbContainers--; - mUsedRam-=GetUsedRam(); -#endif -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Clears the container. All stored values are deleted, and it frees used ram. - * \see Reset() - * \return Self-Reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Container& Container::Empty() -{ -#ifdef CONTAINER_STATS - mUsedRam-=mMaxNbEntries*sizeof(udword); -#endif - DELETEARRAY(mEntries); - mCurNbEntries = mMaxNbEntries = 0; - return *this; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Resizes the container. - * \param needed [in] assume the container can be added at least "needed" values - * \return true if success. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool Container::Resize(udword needed) -{ -#ifdef CONTAINER_STATS - // Subtract previous amount of bytes - mUsedRam-=mMaxNbEntries*sizeof(udword); -#endif - - // Get more entries - mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2 - if(mMaxNbEntriesmMaxNbEntries) Resize(nb); - - // Add new entry - CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword)); - mCurNbEntries+=nb; - return *this; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * A O(1) method to add a value in the container. The container is automatically resized if needed. - * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation - * costs a lot more than the call overhead... - * - * \param entry [in] a float to store in the container - * \see Add(udword entry) - * \see Empty() - * \see Contains(udword entry) - * \return Self-Reference - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ Container& Add(float entry) - { - // Resize if needed - if(mCurNbEntries==mMaxNbEntries) Resize(); - - // Add new entry - mEntries[mCurNbEntries++] = IR(entry); - return *this; - } - - inline_ Container& Add(const float* entries, udword nb) - { - // Resize if needed - if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb); - - // Add new entry - CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float)); - mCurNbEntries+=nb; - return *this; - } - - //! Add unique [slow] - inline_ Container& AddUnique(udword entry) - { - if(!Contains(entry)) Add(entry); - return *this; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Clears the container. All stored values are deleted, and it frees used ram. - * \see Reset() - * \return Self-Reference - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Container& Empty(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again. - * That's a kind of temporal coherence. - * \see Empty() - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void Reset() - { - // Avoid the write if possible - // ### CMOV - if(mCurNbEntries) mCurNbEntries = 0; - } - - // HANDLE WITH CARE - inline_ void ForceSize(udword size) - { - mCurNbEntries = size; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Sets the initial size of the container. If it already contains something, it's discarded. - * \param nb [in] Number of entries - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool SetSize(udword nb); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Refits the container and get rid of unused bytes. - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Refit(); - - // Checks whether the container already contains a given value. - bool Contains(udword entry, udword* location=null) const; - // Deletes an entry - doesn't preserve insertion order. - bool Delete(udword entry); - // Deletes an entry - does preserve insertion order. - bool DeleteKeepingOrder(udword entry); - //! Deletes the very last entry. - inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; } - //! Deletes the entry whose index is given - inline_ void DeleteIndex(udword index) { mEntries[index] = mEntries[--mCurNbEntries]; } - - // Helpers - Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP); - Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP); - // Data access. - inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries. - inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry - inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries. - - inline_ udword GetFirst() const { return mEntries[0]; } - inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; } - - // Growth control - inline_ float GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor - inline_ void SetGrowthFactor(float growth) { mGrowthFactor = growth; } //!< Sets the growth factor - inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full - inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty - - //! Read-access as an array - inline_ udword operator[](udword i) const { ASSERT(i>=0 && i=0 && i - #include - - #define SIGN_BITMASK 0x80000000 - - //! Integer representation of a floating-point value. - #define IR(x) ((udword&)(x)) - - //! Signed integer representation of a floating-point value. - #define SIR(x) ((sdword&)(x)) - - //! Absolute integer representation of a floating-point value - #define AIR(x) (IR(x)&0x7fffffff) - - //! Floating-point representation of an integer value. - #define FR(x) ((float&)(x)) - - //! Integer-based comparison of a floating point value. - //! Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context. - #define IS_NEGATIVE_FLOAT(x) (IR(x)&0x80000000) - - //! Fast fabs for floating-point values. It just clears the sign bit. - //! Don't use it blindy, it can be faster or slower than the FPU comparison, depends on the context. - inline_ float FastFabs(float x) - { - udword FloatBits = IR(x)&0x7fffffff; - return FR(FloatBits); - } - - //! Fast square root for floating-point values. - inline_ float FastSqrt(float square) - { - return std::sqrt(square); - } - - //! Saturates positive to zero. - inline_ float fsat(float f) - { - udword y = (udword&)f & ~((sdword&)f >>31); - return (float&)y; - } - - //! Computes 1.0f / sqrtf(x). - inline_ float frsqrt(float f) - { - float x = f * 0.5f; - udword y = 0x5f3759df - ((udword&)f >> 1); - // Iteration... - (float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) ); - // Result - return (float&)y; - } - - //! Computes 1.0f / sqrtf(x). Comes from NVIDIA. - inline_ float InvSqrt(const float& x) - { - udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1; - float y = *(float*)&tmp; - return y * (1.47f - 0.47f * x * y * y); - } - - //! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above. - //! See http://www.magic-software.com/3DGEDInvSqrt.html - inline_ float RSqrt(float number) - { - long i; - float x2, y; - const float threehalfs = 1.5f; - - x2 = number * 0.5f; - y = number; - i = * (long *) &y; - i = 0x5f3759df - (i >> 1); - y = * (float *) &i; - y = y * (threehalfs - (x2 * y * y)); - - return y; - } - - //! TO BE DOCUMENTED - inline_ float fsqrt(float f) - { - udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000; - // Iteration...? - // (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f; - // Result - return (float&)y; - } - - //! Returns the float ranged espilon value. - inline_ float fepsilon(float f) - { - udword b = (udword&)f & 0xff800000; - udword a = b | 0x00000001; - (float&)a -= (float&)b; - // Result - return (float&)a; - } - - //! Is the float valid ? - inline_ bool IsNAN(float value) { return (IR(value)&0x7f800000) == 0x7f800000; } - inline_ bool IsIndeterminate(float value) { return IR(value) == 0xffc00000; } - inline_ bool IsPlusInf(float value) { return IR(value) == 0x7f800000; } - inline_ bool IsMinusInf(float value) { return IR(value) == 0xff800000; } - - inline_ bool IsValidFloat(float value) - { - if(IsNAN(value)) return false; - if(IsIndeterminate(value)) return false; - if(IsPlusInf(value)) return false; - if(IsMinusInf(value)) return false; - return true; - } - - #define CHECK_VALID_FLOAT(x) ASSERT(IsValidFloat(x)); - -/* - //! FPU precision setting function. - inline_ void SetFPU() - { - // This function evaluates whether the floating-point - // control word is set to single precision/round to nearest/ - // exceptions disabled. If these conditions don't hold, the - // function changes the control word to set them and returns - // TRUE, putting the old control word value in the passback - // location pointed to by pwOldCW. - { - uword wTemp, wSave; - - __asm fstcw wSave - if (wSave & 0x300 || // Not single mode - 0x3f != (wSave & 0x3f) || // Exceptions enabled - wSave & 0xC00) // Not round to nearest mode - { - __asm - { - mov ax, wSave - and ax, not 300h ;; single mode - or ax, 3fh ;; disable all exceptions - and ax, not 0xC00 ;; round to nearest mode - mov wTemp, ax - fldcw wTemp - } - } - } - } -*/ - //! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON) - inline_ float ComputeFloatEpsilon() - { - float f = 1.0f; - ((udword&)f)^=1; - return f - 1.0f; // You can check it's the same as FLT_EPSILON - } - - inline_ bool IsFloatZero(float x, float epsilon=1e-6f) - { - return x*x < epsilon; - } - - //! A global function to find MAX(a,b) using FCOMI/FCMOV - inline_ float FCMax2(float a, float b) - { - return (std::max)(a, b); - } - - //! A global function to find MIN(a,b) using FCOMI/FCMOV - inline_ float FCMin2(float a, float b) - { - return (std::min)(a, b); - } - - //! A global function to find MAX(a,b,c) using FCOMI/FCMOV - inline_ float FCMax3(float a, float b, float c) - { - return (std::max)((std::max)(a, b), c); - } - - //! A global function to find MIN(a,b,c) using FCOMI/FCMOV - inline_ float FCMin3(float a, float b, float c) - { - return (std::min)((std::min)(a, b), c); - } - - inline_ int ConvertToSortable(float f) - { - int& Fi = (int&)f; - int Fmask = (Fi>>31); - Fi ^= Fmask; - Fmask &= ~(1<<31); - Fi -= Fmask; - return Fi; - } - - enum FPUMode - { - FPU_FLOOR = 0, - FPU_CEIL = 1, - FPU_BEST = 2, - - FPU_FORCE_DWORD = 0x7fffffff - }; - - FUNCTION ICECORE_API FPUMode GetFPUMode(); - FUNCTION ICECORE_API void SaveFPU(); - FUNCTION ICECORE_API void RestoreFPU(); - FUNCTION ICECORE_API void SetFPUFloorMode(); - FUNCTION ICECORE_API void SetFPUCeilMode(); - FUNCTION ICECORE_API void SetFPUBestMode(); - - FUNCTION ICECORE_API void SetFPUPrecision24(); - FUNCTION ICECORE_API void SetFPUPrecision53(); - FUNCTION ICECORE_API void SetFPUPrecision64(); - FUNCTION ICECORE_API void SetFPURoundingChop(); - FUNCTION ICECORE_API void SetFPURoundingUp(); - FUNCTION ICECORE_API void SetFPURoundingDown(); - FUNCTION ICECORE_API void SetFPURoundingNear(); - - FUNCTION ICECORE_API int intChop(const float& f); - FUNCTION ICECORE_API int intFloor(const float& f); - FUNCTION ICECORE_API int intCeil(const float& f); - -#endif // __ICEFPU_H__ diff --git a/contrib/Opcode/Ice/IceHPoint.cpp b/contrib/Opcode/Ice/IceHPoint.cpp deleted file mode 100644 index daa7038..0000000 --- a/contrib/Opcode/Ice/IceHPoint.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for homogeneous points. - * \file IceHPoint.cpp - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Homogeneous point. - * - * Use it: - * - for clipping in homogeneous space (standard way) - * - to differentiate between points (w=1) and vectors (w=0). - * - in some cases you can also use it instead of IcePoint for padding reasons. - * - * \class HPoint - * \author Pierre Terdiman - * \version 1.0 - * \warning No cross-product in 4D. - * \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// IcePoint Mul = HPoint * Matrix3x3; -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -IcePoint HPoint::operator*(const Matrix3x3& mat) const -{ - return IcePoint( - x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0], - x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1], - x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] ); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// HPoint Mul = HPoint * Matrix4x4; -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HPoint HPoint::operator*(const Matrix4x4& mat) const -{ - return HPoint( - x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0], - x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1], - x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2], - x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// HPoint *= Matrix4x4 -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HPoint& HPoint::operator*=(const Matrix4x4& mat) -{ - float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0]; - float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1]; - float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2]; - float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]; - - x = xp; y = yp; z = zp; w = wp; - - return *this; -} - diff --git a/contrib/Opcode/Ice/IceHPoint.h b/contrib/Opcode/Ice/IceHPoint.h deleted file mode 100644 index f7d0d16..0000000 --- a/contrib/Opcode/Ice/IceHPoint.h +++ /dev/null @@ -1,157 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for homogeneous points. - * \file IceHPoint.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEHPOINT_H__ -#define __ICEHPOINT_H__ - - class ICEMATHS_API HPoint : public IcePoint - { - public: - - //! Empty constructor - inline_ HPoint() {} - //! Constructor from floats - inline_ HPoint(float _x, float _y, float _z, float _w=0.0f) : IcePoint(_x, _y, _z), w(_w) {} - //! Constructor from array - inline_ HPoint(const float f[4]) : IcePoint(f), w(f[3]) {} - //! Constructor from a Point - inline_ HPoint(const IcePoint& p, float _w=0.0f) : IcePoint(p), w(_w) {} - //! Destructor - inline_ ~HPoint() {} - - //! Clear the point - inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; } - - //! Assignment from values - inline_ HPoint& Set(float _x, float _y, float _z, float _w ) { x = _x; y = _y; z = _z; w = _w; return *this; } - //! Assignment from array - inline_ HPoint& Set(const float f[4]) { x = f[_X]; y = f[_Y]; z = f[_Z]; w = f[_W]; return *this; } - //! Assignment from another h-point - inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; } - - //! Add a vector - inline_ HPoint& Add(float _x, float _y, float _z, float _w ) { x += _x; y += _y; z += _z; w += _w; return *this; } - //! Add a vector - inline_ HPoint& Add(const float f[4]) { x += f[_X]; y += f[_Y]; z += f[_Z]; w += f[_W]; return *this; } - - //! Subtract a vector - inline_ HPoint& Sub(float _x, float _y, float _z, float _w ) { x -= _x; y -= _y; z -= _z; w -= _w; return *this; } - //! Subtract a vector - inline_ HPoint& Sub(const float f[4]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; w -= f[_W]; return *this; } - - //! Multiplies by a scalar - inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; } - - //! Returns MIN(x, y, z, w); - float Min() const { return MIN(x, MIN(y, MIN(z, w))); } - //! Returns MAX(x, y, z, w); - float Max() const { return MAX(x, MAX(y, MAX(z, w))); } - //! Sets each element to be componentwise minimum - HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; } - //! Sets each element to be componentwise maximum - HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; } - - //! Computes square magnitude - inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; } - //! Computes magnitude - inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); } - - //! Normalize the vector - inline_ HPoint& Normalize() - { - float M = Magnitude(); - if(M) - { - M = 1.0f / M; - x *= M; - y *= M; - z *= M; - w *= M; - } - return *this; - } - - // Arithmetic operators - //! Operator for HPoint Negate = - HPoint; - inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); } - - //! Operator for HPoint Plus = HPoint + HPoint; - inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); } - //! Operator for HPoint Minus = HPoint - HPoint; - inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); } - - //! Operator for HPoint Mul = HPoint * HPoint; - inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); } - //! Operator for HPoint Scale = HPoint * float; - inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); } - //! Operator for HPoint Scale = float * HPoint; - inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); } - - //! Operator for HPoint Div = HPoint / HPoint; - inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); } - //! Operator for HPoint Scale = HPoint / float; - inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); } - //! Operator for HPoint Scale = float / HPoint; - inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); } - - //! Operator for float DotProd = HPoint | HPoint; - inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; } - // No cross-product in 4D - - //! Operator for HPoint += HPoint; - inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; } - //! Operator for HPoint += float; - inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; } - - //! Operator for HPoint -= HPoint; - inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; } - //! Operator for HPoint -= float; - inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; } - - //! Operator for HPoint *= HPoint; - inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; } - //! Operator for HPoint *= float; - inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; } - - //! Operator for HPoint /= HPoint; - inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; } - //! Operator for HPoint /= float; - inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; } - - // Arithmetic operators - - //! Operator for Point Mul = HPoint * Matrix3x3; - IcePoint operator*(const Matrix3x3& mat) const; - //! Operator for HPoint Mul = HPoint * Matrix4x4; - HPoint operator*(const Matrix4x4& mat) const; - - // HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 - //! Operator for HPoint *= Matrix4x4 - HPoint& operator*=(const Matrix4x4& mat); - - // Logical operators - - //! Operator for "if(HPoint==HPoint)" - inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); } - //! Operator for "if(HPoint!=HPoint)" - inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); } - - // Cast operators - - //! Cast a HPoint to a Point. w is discarded. - inline_ operator HPoint() const { return IcePoint(x, y, z); } - - public: - float w; - }; - -#endif // __ICEHPOINT_H__ - diff --git a/contrib/Opcode/Ice/IceIndexedTriangle.cpp b/contrib/Opcode/Ice/IceIndexedTriangle.cpp deleted file mode 100644 index 3e74cbb..0000000 --- a/contrib/Opcode/Ice/IceIndexedTriangle.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a handy indexed triangle class. - * \file IceIndexedTriangle.cpp - * \author Pierre Terdiman - * \date January, 17, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains an indexed triangle class. - * - * \class Triangle - * \author Pierre Terdiman - * \version 1.0 - * \date 08.15.98 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Flips the winding order. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void IndexedTriangle::Flip() -{ - Swap(mVRef[1], mVRef[2]); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle area. - * \param verts [in] the list of indexed vertices - * \return the area - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float IndexedTriangle::Area(const IcePoint* verts) const -{ - if(!verts) return 0.0f; - const IcePoint& p0 = verts[0]; - const IcePoint& p1 = verts[1]; - const IcePoint& p2 = verts[2]; - return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle perimeter. - * \param verts [in] the list of indexed vertices - * \return the perimeter - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float IndexedTriangle::Perimeter(const IcePoint* verts) const -{ - if(!verts) return 0.0f; - const IcePoint& p0 = verts[0]; - const IcePoint& p1 = verts[1]; - const IcePoint& p2 = verts[2]; - return p0.Distance(p1) - + p0.Distance(p2) - + p1.Distance(p2); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle compacity. - * \param verts [in] the list of indexed vertices - * \return the compacity - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float IndexedTriangle::Compacity(const IcePoint* verts) const -{ - if(!verts) return 0.0f; - float P = Perimeter(verts); - if(P==0.0f) return 0.0f; - return (4.0f*PI*Area(verts)/(P*P)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle normal. - * \param verts [in] the list of indexed vertices - * \param normal [out] the computed normal - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void IndexedTriangle::Normal(const IcePoint* verts, IcePoint& normal) const -{ - if(!verts) return; - - const IcePoint& p0 = verts[mVRef[0]]; - const IcePoint& p1 = verts[mVRef[1]]; - const IcePoint& p2 = verts[mVRef[2]]; - normal = ((p2-p1)^(p0-p1)).Normalize(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle denormalized normal. - * \param verts [in] the list of indexed vertices - * \param normal [out] the computed normal - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void IndexedTriangle::DenormalizedNormal(const IcePoint* verts, IcePoint& normal) const -{ - if(!verts) return; - - const IcePoint& p0 = verts[mVRef[0]]; - const IcePoint& p1 = verts[mVRef[1]]; - const IcePoint& p2 = verts[mVRef[2]]; - normal = ((p2-p1)^(p0-p1)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle center. - * \param verts [in] the list of indexed vertices - * \param center [out] the computed center - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void IndexedTriangle::Center(const IcePoint* verts, IcePoint& center) const -{ - if(!verts) return; - - const IcePoint& p0 = verts[mVRef[0]]; - const IcePoint& p1 = verts[mVRef[1]]; - const IcePoint& p2 = verts[mVRef[2]]; - center = (p0+p1+p2)*INV3; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the centered normal - * \param verts [in] the list of indexed vertices - * \param normal [out] the computed centered normal - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void IndexedTriangle::CenteredNormal(const IcePoint* verts, IcePoint& normal) const -{ - if(!verts) return; - - const IcePoint& p0 = verts[mVRef[0]]; - const IcePoint& p1 = verts[mVRef[1]]; - const IcePoint& p2 = verts[mVRef[2]]; - IcePoint Center = (p0+p1+p2)*INV3; - normal = Center + ((p2-p1)^(p0-p1)).Normalize(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes a random point within the triangle. - * \param verts [in] the list of indexed vertices - * \param normal [out] the computed centered normal - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void IndexedTriangle::RandomPoint(const IcePoint* verts, IcePoint& random) const -{ - if(!verts) return; - - // Random barycentric coords - float Alpha = UnitRandomFloat(); - float Beta = UnitRandomFloat(); - float Gamma = UnitRandomFloat(); - float OneOverTotal = 1.0f / (Alpha + Beta + Gamma); - Alpha *= OneOverTotal; - Beta *= OneOverTotal; - Gamma *= OneOverTotal; - - const IcePoint& p0 = verts[mVRef[0]]; - const IcePoint& p1 = verts[mVRef[1]]; - const IcePoint& p2 = verts[mVRef[2]]; - random = Alpha*p0 + Beta*p1 + Gamma*p2; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes backface culling. - * \param verts [in] the list of indexed vertices - * \param source [in] source point (in local space) from which culling must be computed - * \return true if the triangle is visible from the source point - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool IndexedTriangle::IsVisible(const IcePoint* verts, const IcePoint& source) const -{ - // Checkings - if(!verts) return false; - - const IcePoint& p0 = verts[mVRef[0]]; - const IcePoint& p1 = verts[mVRef[1]]; - const IcePoint& p2 = verts[mVRef[2]]; - - // Compute denormalized normal - IcePoint Normal = (p2 - p1)^(p0 - p1); - - // Backface culling - return (Normal | source) >= 0.0f; - -// Same as: -// IcePlane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); -// return PL.Distance(source) > PL.d; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes backface culling. - * \param verts [in] the list of indexed vertices - * \param source [in] source point (in local space) from which culling must be computed - * \return true if the triangle is visible from the source point - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool IndexedTriangle::BackfaceCulling(const IcePoint* verts, const IcePoint& source) const -{ - // Checkings - if(!verts) return false; - - const IcePoint& p0 = verts[mVRef[0]]; - const IcePoint& p1 = verts[mVRef[1]]; - const IcePoint& p2 = verts[mVRef[2]]; - - // Compute base -// IcePoint Base = (p0 + p1 + p2)*INV3; - - // Compute denormalized normal - IcePoint Normal = (p2 - p1)^(p0 - p1); - - // Backface culling -// return (Normal | (source - Base)) >= 0.0f; - return (Normal | (source - p0)) >= 0.0f; - -// Same as: (but a bit faster) -// IcePlane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); -// return PL.Distance(source)>0.0f; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the occlusion potential of the triangle. - * \param verts [in] the list of indexed vertices - * \param source [in] source point (in local space) from which occlusion potential must be computed - * \return the occlusion potential - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float IndexedTriangle::ComputeOcclusionPotential(const IcePoint* verts, const IcePoint& view) const -{ - if(!verts) return 0.0f; - // Occlusion potential: -(A * (N|V) / d^2) - // A = polygon area - // N = polygon normal - // V = view vector - // d = distance viewpoint-center of polygon - - float A = Area(verts); - IcePoint N; Normal(verts, N); - IcePoint C; Center(verts, C); - float d = view.Distance(C); - return -(A*(N|view))/(d*d); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Replaces a vertex reference with another one. - * \param oldref [in] the vertex reference to replace - * \param newref [in] the new vertex reference - * \return true if success, else false if the input vertex reference doesn't belong to the triangle - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool IndexedTriangle::ReplaceVertex(udword oldref, udword newref) -{ - if(mVRef[0]==oldref) { mVRef[0] = newref; return true; } - else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; } - else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; } - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle. - * \return true if the triangle is degenerate - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool IndexedTriangle::IsDegenerate() const -{ - if(mVRef[0]==mVRef[1]) return true; - if(mVRef[1]==mVRef[2]) return true; - if(mVRef[2]==mVRef[0]) return true; - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks whether the input vertex reference belongs to the triangle or not. - * \param ref [in] the vertex reference to look for - * \return true if the triangle contains the vertex reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool IndexedTriangle::HasVertex(udword ref) const -{ - if(mVRef[0]==ref) return true; - if(mVRef[1]==ref) return true; - if(mVRef[2]==ref) return true; - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks whether the input vertex reference belongs to the triangle or not. - * \param ref [in] the vertex reference to look for - * \param index [out] the corresponding index in the triangle - * \return true if the triangle contains the vertex reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool IndexedTriangle::HasVertex(udword ref, udword* index) const -{ - if(mVRef[0]==ref) { *index = 0; return true; } - if(mVRef[1]==ref) { *index = 1; return true; } - if(mVRef[2]==ref) { *index = 2; return true; } - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Finds an edge in a tri, given two vertex references. - * \param vref0 [in] the edge's first vertex reference - * \param vref1 [in] the edge's second vertex reference - * \return the edge number between 0 and 2, or 0xff if input refs are wrong. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ubyte IndexedTriangle::FindEdge(udword vref0, udword vref1) const -{ - if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0; - else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0; - else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1; - else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1; - else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2; - else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2; - return 0xff; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Gets the last reference given the first two. - * \param vref0 [in] the first vertex reference - * \param vref1 [in] the second vertex reference - * \return the last reference, or INVALID_ID if input refs are wrong. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -udword IndexedTriangle::OppositeVertex(udword vref0, udword vref1) const -{ - if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2]; - else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2]; - else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1]; - else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1]; - else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0]; - else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0]; - return INVALID_ID; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Gets the three sorted vertex references according to an edge number. - * edgenb = 0 => edge 0-1, returns references 0, 1, 2 - * edgenb = 1 => edge 0-2, returns references 0, 2, 1 - * edgenb = 2 => edge 1-2, returns references 1, 2, 0 - * - * \param edgenb [in] the edge number, 0, 1 or 2 - * \param vref0 [out] the returned first vertex reference - * \param vref1 [out] the returned second vertex reference - * \param vref2 [out] the returned third vertex reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void IndexedTriangle::GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const -{ - if(edgenb==0) - { - vref0 = mVRef[0]; - vref1 = mVRef[1]; - vref2 = mVRef[2]; - } - else if(edgenb==1) - { - vref0 = mVRef[0]; - vref1 = mVRef[2]; - vref2 = mVRef[1]; - } - else if(edgenb==2) - { - vref0 = mVRef[1]; - vref1 = mVRef[2]; - vref2 = mVRef[0]; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle's smallest edge length. - * \param verts [in] the list of indexed vertices - * \return the smallest edge length - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float IndexedTriangle::MinEdgeLength(const IcePoint* verts) const -{ - if(!verts) return 0.0f; - - float Min = MAX_FLOAT; - float Length01 = verts[0].Distance(verts[1]); - float Length02 = verts[0].Distance(verts[2]); - float Length12 = verts[1].Distance(verts[2]); - if(Length01 < Min) Min = Length01; - if(Length02 < Min) Min = Length02; - if(Length12 < Min) Min = Length12; - return Min; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle's largest edge length. - * \param verts [in] the list of indexed vertices - * \return the largest edge length - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float IndexedTriangle::MaxEdgeLength(const IcePoint* verts) const -{ - if(!verts) return 0.0f; - - float Max = MIN_FLOAT; - float Length01 = verts[0].Distance(verts[1]); - float Length02 = verts[0].Distance(verts[2]); - float Length12 = verts[1].Distance(verts[2]); - if(Length01 > Max) Max = Length01; - if(Length02 > Max) Max = Length02; - if(Length12 > Max) Max = Length12; - return Max; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes a point on the triangle according to the stabbing information. - * \param verts [in] the list of indexed vertices - * \param u,v [in] point's barycentric coordinates - * \param pt [out] point on triangle - * \param nearvtx [out] index of nearest vertex - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void IndexedTriangle::ComputePoint(const IcePoint* verts, float u, float v, IcePoint& pt, udword* nearvtx) const -{ - // Checkings - if(!verts) return; - - // Get face in local or global space - const IcePoint& p0 = verts[mVRef[0]]; - const IcePoint& p1 = verts[mVRef[1]]; - const IcePoint& p2 = verts[mVRef[2]]; - - // Compute point coordinates - pt = (1.0f - u - v)*p0 + u*p1 + v*p2; - - // Compute nearest vertex if needed - if(nearvtx) - { - // Compute distance vector - IcePoint d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face - p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face - p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face - - // Get smallest distance - *nearvtx = mVRef[d.SmallestAxis()]; - } -} - - //************************************** - // Angle between two vectors (in radians) - // we use this formula - // uv = |u||v| cos(u,v) - // u ^ v = w - // |w| = |u||v| |sin(u,v)| - //************************************** - float Angle(const IcePoint& u, const IcePoint& v) - { - float NormU = u.Magnitude(); // |u| - float NormV = v.Magnitude(); // |v| - float Product = NormU*NormV; // |u||v| - if(Product==0.0f) return 0.0f; - float OneOverProduct = 1.0f / Product; - - // Cosinus - float Cosinus = (u|v) * OneOverProduct; - - // Sinus - IcePoint w = u^v; - float NormW = w.Magnitude(); - - float AbsSinus = NormW * OneOverProduct; - - // Remove degeneracy - if(AbsSinus > 1.0f) AbsSinus = 1.0f; - if(AbsSinus < -1.0f) AbsSinus = -1.0f; - - if(Cosinus>=0.0f) return asinf(AbsSinus); - else return (PI-asinf(AbsSinus)); - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the angle between two triangles. - * \param tri [in] the other triangle - * \param verts [in] the list of indexed vertices - * \return the angle in radians - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float IndexedTriangle::Angle(const IndexedTriangle& tri, const IcePoint* verts) const -{ - // Checkings - if(!verts) return 0.0f; - - // Compute face normals - IcePoint n0, n1; - Normal(verts, n0); - tri.Normal(verts, n1); - - // Compute angle - float dp = n0|n1; - if(dp>1.0f) return 0.0f; - if(dp<-1.0f) return PI; - return acosf(dp); - -// return ::Angle(n0,n1); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks a triangle is the same as another one. - * \param tri [in] the other triangle - * \return true if same triangle - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool IndexedTriangle::Equal(const IndexedTriangle& tri) const -{ - // Test all vertex references - return (HasVertex(tri.mVRef[0]) && - HasVertex(tri.mVRef[1]) && - HasVertex(tri.mVRef[2])); -} diff --git a/contrib/Opcode/Ice/IceIndexedTriangle.h b/contrib/Opcode/Ice/IceIndexedTriangle.h deleted file mode 100644 index ef279c2..0000000 --- a/contrib/Opcode/Ice/IceIndexedTriangle.h +++ /dev/null @@ -1,64 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a handy indexed triangle class. - * \file IceIndexedTriangle.h - * \author Pierre Terdiman - * \date January, 17, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEINDEXEDTRIANGLE_H__ -#define __ICEINDEXEDTRIANGLE_H__ - - // An indexed triangle class. - class ICEMATHS_API IndexedTriangle - { - public: - //! Constructor - inline_ IndexedTriangle() {} - //! Constructor - inline_ IndexedTriangle(udword r0, udword r1, udword r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; } - //! Copy constructor - inline_ IndexedTriangle(const IndexedTriangle& triangle) - { - mVRef[0] = triangle.mVRef[0]; - mVRef[1] = triangle.mVRef[1]; - mVRef[2] = triangle.mVRef[2]; - } - //! Destructor - inline_ ~IndexedTriangle() {} - //! Vertex-references - udword mVRef[3]; - - // Methods - void Flip(); - float Area(const IcePoint* verts) const; - float Perimeter(const IcePoint* verts) const; - float Compacity(const IcePoint* verts) const; - void Normal(const IcePoint* verts, IcePoint& normal) const; - void DenormalizedNormal(const IcePoint* verts, IcePoint& normal) const; - void Center(const IcePoint* verts, IcePoint& center) const; - void CenteredNormal(const IcePoint* verts, IcePoint& normal) const; - void RandomPoint(const IcePoint* verts, IcePoint& random) const; - bool IsVisible(const IcePoint* verts, const IcePoint& source) const; - bool BackfaceCulling(const IcePoint* verts, const IcePoint& source) const; - float ComputeOcclusionPotential(const IcePoint* verts, const IcePoint& view) const; - bool ReplaceVertex(udword oldref, udword newref); - bool IsDegenerate() const; - bool HasVertex(udword ref) const; - bool HasVertex(udword ref, udword* index) const; - ubyte FindEdge(udword vref0, udword vref1) const; - udword OppositeVertex(udword vref0, udword vref1) const; - inline_ udword OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; } - void GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const; - float MinEdgeLength(const IcePoint* verts) const; - float MaxEdgeLength(const IcePoint* verts) const; - void ComputePoint(const IcePoint* verts, float u, float v, IcePoint& pt, udword* nearvtx=null) const; - float Angle(const IndexedTriangle& tri, const IcePoint* verts) const; - inline_ IcePlane PlaneEquation(const IcePoint* verts) const { return IcePlane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); } - bool Equal(const IndexedTriangle& tri) const; - }; - -#endif // __ICEINDEXEDTRIANGLE_H__ diff --git a/contrib/Opcode/Ice/IceLSS.h b/contrib/Opcode/Ice/IceLSS.h deleted file mode 100644 index e4c9ef8..0000000 --- a/contrib/Opcode/Ice/IceLSS.h +++ /dev/null @@ -1,75 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for line-swept spheres. - * \file IceLSS.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICELSS_H__ -#define __ICELSS_H__ - - class ICEMATHS_API LSS : public IceSegment - { - public: - //! Constructor - inline_ LSS() {} - //! Constructor - inline_ LSS(const IceSegment& seg, float radius) : IceSegment(seg), mRadius(radius) {} - //! Destructor - inline_ ~LSS() {} - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes an OBB surrounding the LSS. - * \param box [out] the OBB - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void ComputeOBB(OBB& box); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Tests if a IcePoint is contained within the LSS. - * \param pt [in] the IcePoint to test - * \return true if inside the LSS - * \warning IcePoint and LSS must be in same space - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ bool Contains(const IcePoint& pt) const { return SquareDistance(pt) <= mRadius*mRadius; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Tests if a sphere is contained within the LSS. - * \param sphere [in] the sphere to test - * \return true if inside the LSS - * \warning sphere and LSS must be in same space - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ bool Contains(const Sphere& sphere) - { - float d = mRadius - sphere.mRadius; - if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d; - else return false; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Tests if an LSS is contained within the LSS. - * \param lss [in] the LSS to test - * \return true if inside the LSS - * \warning both LSS must be in same space - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ bool Contains(const LSS& lss) - { - // We check the LSS contains the two spheres at the start and end of the sweep - return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius)); - } - - float mRadius; //!< Sphere radius - }; - -#endif // __ICELSS_H__ diff --git a/contrib/Opcode/Ice/IceMatrix3x3.cpp b/contrib/Opcode/Ice/IceMatrix3x3.cpp deleted file mode 100644 index c856366..0000000 --- a/contrib/Opcode/Ice/IceMatrix3x3.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for 3x3 matrices. - * \file IceMatrix3x3.cpp - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * 3x3 matrix. - * DirectX-compliant, ie row-column order, ie m[Row][Col]. - * Same as: - * m11 m12 m13 first row. - * m21 m22 m23 second row. - * m31 m32 m33 third row. - * Stored in memory as m11 m12 m13 m21... - * - * Multiplication rules: - * - * [x'y'z'] = [xyz][M] - * - * x' = x*m11 + y*m21 + z*m31 - * y' = x*m12 + y*m22 + z*m32 - * z' = x*m13 + y*m23 + z*m33 - * - * \class Matrix3x3 - * \author Pierre Terdiman - * \version 1.0 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -// Cast operator -Matrix3x3::operator Matrix4x4() const -{ - return Matrix4x4( - m[0][0], m[0][1], m[0][2], 0.0f, - m[1][0], m[1][1], m[1][2], 0.0f, - m[2][0], m[2][1], m[2][2], 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); -} diff --git a/contrib/Opcode/Ice/IceMatrix3x3.h b/contrib/Opcode/Ice/IceMatrix3x3.h deleted file mode 100644 index 3356103..0000000 --- a/contrib/Opcode/Ice/IceMatrix3x3.h +++ /dev/null @@ -1,496 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for 3x3 matrices. - * \file IceMatrix3x3.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEMATRIX3X3_H__ -#define __ICEMATRIX3X3_H__ - - // Forward declarations - class Quat; - - #define MATRIX3X3_EPSILON (1.0e-7f) - - class ICEMATHS_API Matrix3x3 - { - public: - //! Empty constructor - inline_ Matrix3x3() {} - //! Constructor from 9 values - inline_ Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) - { - m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; - m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; - m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; - } - //! Copy constructor - inline_ Matrix3x3(const Matrix3x3& mat) { CopyMemory(m, &mat.m, 9*sizeof(float)); } - //! Destructor - inline_ ~Matrix3x3() {} - - //! Assign values - inline_ void Set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) - { - m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; - m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; - m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; - } - - //! Sets the scale from a Point. The point is put on the diagonal. - inline_ void SetScale(const IcePoint& p) { m[0][0] = p.x; m[1][1] = p.y; m[2][2] = p.z; } - - //! Sets the scale from floats. Values are put on the diagonal. - inline_ void SetScale(float sx, float sy, float sz) { m[0][0] = sx; m[1][1] = sy; m[2][2] = sz; } - - //! Scales from a Point. Each row is multiplied by a component. - inline_ void Scale(const IcePoint& p) - { - m[0][0] *= p.x; m[0][1] *= p.x; m[0][2] *= p.x; - m[1][0] *= p.y; m[1][1] *= p.y; m[1][2] *= p.y; - m[2][0] *= p.z; m[2][1] *= p.z; m[2][2] *= p.z; - } - - //! Scales from floats. Each row is multiplied by a value. - inline_ void Scale(float sx, float sy, float sz) - { - m[0][0] *= sx; m[0][1] *= sx; m[0][2] *= sx; - m[1][0] *= sy; m[1][1] *= sy; m[1][2] *= sy; - m[2][0] *= sz; m[2][1] *= sz; m[2][2] *= sz; - } - - //! Copy from a Matrix3x3 - inline_ void Copy(const Matrix3x3& source) { CopyMemory(m, source.m, 9*sizeof(float)); } - - // Row-column access - //! Returns a row. - inline_ void GetRow(const udword r, IcePoint& p) const { p.x = m[r][0]; p.y = m[r][1]; p.z = m[r][2]; } - //! Returns a row. - inline_ const IcePoint& GetRow(const udword r) const { return *(const IcePoint*)&m[r][0]; } - //! Returns a row. - inline_ IcePoint& GetRow(const udword r) { return *(IcePoint*)&m[r][0]; } - //! Sets a row. - inline_ void SetRow(const udword r, const IcePoint& p) { m[r][0] = p.x; m[r][1] = p.y; m[r][2] = p.z; } - //! Returns a column. - inline_ void GetCol(const udword c, IcePoint& p) const { p.x = m[0][c]; p.y = m[1][c]; p.z = m[2][c]; } - //! Sets a column. - inline_ void SetCol(const udword c, const IcePoint& p) { m[0][c] = p.x; m[1][c] = p.y; m[2][c] = p.z; } - - //! Computes the trace. The trace is the sum of the 3 diagonal components. - inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2]; } - //! Clears the matrix. - inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } - //! Sets the identity matrix. - inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = 1.0f; } - //! Checks for identity - inline_ bool IsIdentity() const - { - if(IR(m[0][0])!=IEEE_1_0) return false; - if(IR(m[0][1])!=0) return false; - if(IR(m[0][2])!=0) return false; - - if(IR(m[1][0])!=0) return false; - if(IR(m[1][1])!=IEEE_1_0) return false; - if(IR(m[1][2])!=0) return false; - - if(IR(m[2][0])!=0) return false; - if(IR(m[2][1])!=0) return false; - if(IR(m[2][2])!=IEEE_1_0) return false; - - return true; - } - - //! Checks matrix validity - inline_ BOOL IsValid() const - { - for(udword j=0;j<3;j++) - { - for(udword i=0;i<3;i++) - { - if(!IsValidFloat(m[j][i])) return FALSE; - } - } - return TRUE; - } - - //! Makes a skew-symmetric matrix (a.k.a. Star(*) Matrix) - //! [ 0.0 -a.z a.y ] - //! [ a.z 0.0 -a.x ] - //! [ -a.y a.x 0.0 ] - //! This is also called a "cross matrix" since for any vectors A and B, - //! A^B = Skew(A) * B = - B * Skew(A); - inline_ void SkewSymmetric(const IcePoint& a) - { - m[0][0] = 0.0f; - m[0][1] = -a.z; - m[0][2] = a.y; - - m[1][0] = a.z; - m[1][1] = 0.0f; - m[1][2] = -a.x; - - m[2][0] = -a.y; - m[2][1] = a.x; - m[2][2] = 0.0f; - } - - //! Negates the matrix - inline_ void Neg() - { - m[0][0] = -m[0][0]; m[0][1] = -m[0][1]; m[0][2] = -m[0][2]; - m[1][0] = -m[1][0]; m[1][1] = -m[1][1]; m[1][2] = -m[1][2]; - m[2][0] = -m[2][0]; m[2][1] = -m[2][1]; m[2][2] = -m[2][2]; - } - - //! Neg from another matrix - inline_ void Neg(const Matrix3x3& mat) - { - m[0][0] = -mat.m[0][0]; m[0][1] = -mat.m[0][1]; m[0][2] = -mat.m[0][2]; - m[1][0] = -mat.m[1][0]; m[1][1] = -mat.m[1][1]; m[1][2] = -mat.m[1][2]; - m[2][0] = -mat.m[2][0]; m[2][1] = -mat.m[2][1]; m[2][2] = -mat.m[2][2]; - } - - //! Add another matrix - inline_ void Add(const Matrix3x3& mat) - { - m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; - m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; - m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; - } - - //! Sub another matrix - inline_ void Sub(const Matrix3x3& mat) - { - m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; - m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; - m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; - } - //! Mac - inline_ void Mac(const Matrix3x3& a, const Matrix3x3& b, float s) - { - m[0][0] = a.m[0][0] + b.m[0][0] * s; - m[0][1] = a.m[0][1] + b.m[0][1] * s; - m[0][2] = a.m[0][2] + b.m[0][2] * s; - - m[1][0] = a.m[1][0] + b.m[1][0] * s; - m[1][1] = a.m[1][1] + b.m[1][1] * s; - m[1][2] = a.m[1][2] + b.m[1][2] * s; - - m[2][0] = a.m[2][0] + b.m[2][0] * s; - m[2][1] = a.m[2][1] + b.m[2][1] * s; - m[2][2] = a.m[2][2] + b.m[2][2] * s; - } - //! Mac - inline_ void Mac(const Matrix3x3& a, float s) - { - m[0][0] += a.m[0][0] * s; m[0][1] += a.m[0][1] * s; m[0][2] += a.m[0][2] * s; - m[1][0] += a.m[1][0] * s; m[1][1] += a.m[1][1] * s; m[1][2] += a.m[1][2] * s; - m[2][0] += a.m[2][0] * s; m[2][1] += a.m[2][1] * s; m[2][2] += a.m[2][2] * s; - } - - //! this = A * s - inline_ void Mult(const Matrix3x3& a, float s) - { - m[0][0] = a.m[0][0] * s; m[0][1] = a.m[0][1] * s; m[0][2] = a.m[0][2] * s; - m[1][0] = a.m[1][0] * s; m[1][1] = a.m[1][1] * s; m[1][2] = a.m[1][2] * s; - m[2][0] = a.m[2][0] * s; m[2][1] = a.m[2][1] * s; m[2][2] = a.m[2][2] * s; - } - - inline_ void Add(const Matrix3x3& a, const Matrix3x3& b) - { - m[0][0] = a.m[0][0] + b.m[0][0]; m[0][1] = a.m[0][1] + b.m[0][1]; m[0][2] = a.m[0][2] + b.m[0][2]; - m[1][0] = a.m[1][0] + b.m[1][0]; m[1][1] = a.m[1][1] + b.m[1][1]; m[1][2] = a.m[1][2] + b.m[1][2]; - m[2][0] = a.m[2][0] + b.m[2][0]; m[2][1] = a.m[2][1] + b.m[2][1]; m[2][2] = a.m[2][2] + b.m[2][2]; - } - - inline_ void Sub(const Matrix3x3& a, const Matrix3x3& b) - { - m[0][0] = a.m[0][0] - b.m[0][0]; m[0][1] = a.m[0][1] - b.m[0][1]; m[0][2] = a.m[0][2] - b.m[0][2]; - m[1][0] = a.m[1][0] - b.m[1][0]; m[1][1] = a.m[1][1] - b.m[1][1]; m[1][2] = a.m[1][2] - b.m[1][2]; - m[2][0] = a.m[2][0] - b.m[2][0]; m[2][1] = a.m[2][1] - b.m[2][1]; m[2][2] = a.m[2][2] - b.m[2][2]; - } - - //! this = a * b - inline_ void Mult(const Matrix3x3& a, const Matrix3x3& b) - { - m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[1][0] + a.m[0][2] * b.m[2][0]; - m[0][1] = a.m[0][0] * b.m[0][1] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[2][1]; - m[0][2] = a.m[0][0] * b.m[0][2] + a.m[0][1] * b.m[1][2] + a.m[0][2] * b.m[2][2]; - m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[1][2] * b.m[2][0]; - m[1][1] = a.m[1][0] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[2][1]; - m[1][2] = a.m[1][0] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[1][2] * b.m[2][2]; - m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[1][0] + a.m[2][2] * b.m[2][0]; - m[2][1] = a.m[2][0] * b.m[0][1] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[2][1]; - m[2][2] = a.m[2][0] * b.m[0][2] + a.m[2][1] * b.m[1][2] + a.m[2][2] * b.m[2][2]; - } - - //! this = transpose(a) * b - inline_ void MultAtB(const Matrix3x3& a, const Matrix3x3& b) - { - m[0][0] = a.m[0][0] * b.m[0][0] + a.m[1][0] * b.m[1][0] + a.m[2][0] * b.m[2][0]; - m[0][1] = a.m[0][0] * b.m[0][1] + a.m[1][0] * b.m[1][1] + a.m[2][0] * b.m[2][1]; - m[0][2] = a.m[0][0] * b.m[0][2] + a.m[1][0] * b.m[1][2] + a.m[2][0] * b.m[2][2]; - m[1][0] = a.m[0][1] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[2][1] * b.m[2][0]; - m[1][1] = a.m[0][1] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[2][1] * b.m[2][1]; - m[1][2] = a.m[0][1] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[2][1] * b.m[2][2]; - m[2][0] = a.m[0][2] * b.m[0][0] + a.m[1][2] * b.m[1][0] + a.m[2][2] * b.m[2][0]; - m[2][1] = a.m[0][2] * b.m[0][1] + a.m[1][2] * b.m[1][1] + a.m[2][2] * b.m[2][1]; - m[2][2] = a.m[0][2] * b.m[0][2] + a.m[1][2] * b.m[1][2] + a.m[2][2] * b.m[2][2]; - } - - //! this = a * transpose(b) - inline_ void MultABt(const Matrix3x3& a, const Matrix3x3& b) - { - m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[0][1] + a.m[0][2] * b.m[0][2]; - m[0][1] = a.m[0][0] * b.m[1][0] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[1][2]; - m[0][2] = a.m[0][0] * b.m[2][0] + a.m[0][1] * b.m[2][1] + a.m[0][2] * b.m[2][2]; - m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[0][1] + a.m[1][2] * b.m[0][2]; - m[1][1] = a.m[1][0] * b.m[1][0] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[1][2]; - m[1][2] = a.m[1][0] * b.m[2][0] + a.m[1][1] * b.m[2][1] + a.m[1][2] * b.m[2][2]; - m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[0][1] + a.m[2][2] * b.m[0][2]; - m[2][1] = a.m[2][0] * b.m[1][0] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[1][2]; - m[2][2] = a.m[2][0] * b.m[2][0] + a.m[2][1] * b.m[2][1] + a.m[2][2] * b.m[2][2]; - } - - //! Makes a rotation matrix mapping vector "from" to vector "to". - Matrix3x3& FromTo(const IcePoint& from, const IcePoint& to); - - //! Set a rotation matrix around the X axis. - //! 1 0 0 - //! RX = 0 cx sx - //! 0 -sx cx - void RotX(float angle); - //! Set a rotation matrix around the Y axis. - //! cy 0 -sy - //! RY = 0 1 0 - //! sy 0 cy - void RotY(float angle); - //! Set a rotation matrix around the Z axis. - //! cz sz 0 - //! RZ = -sz cz 0 - //! 0 0 1 - void RotZ(float angle); - //! cy sx.sy -sy.cx - //! RY.RX 0 cx sx - //! sy -sx.cy cx.cy - void RotYX(float y, float x); - - //! Make a rotation matrix about an arbitrary axis - Matrix3x3& Rot(float angle, const IcePoint& axis); - - //! Transpose the matrix. - void Transpose() - { - IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]); - IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]); - IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); - } - - //! this = Transpose(a) - void Transpose(const Matrix3x3& a) - { - m[0][0] = a.m[0][0]; m[0][1] = a.m[1][0]; m[0][2] = a.m[2][0]; - m[1][0] = a.m[0][1]; m[1][1] = a.m[1][1]; m[1][2] = a.m[2][1]; - m[2][0] = a.m[0][2]; m[2][1] = a.m[1][2]; m[2][2] = a.m[2][2]; - } - - //! Compute the determinant of the matrix. We use the rule of Sarrus. - float Determinant() const - { - return (m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1]) - - (m[2][0]*m[1][1]*m[0][2] + m[2][1]*m[1][2]*m[0][0] + m[2][2]*m[1][0]*m[0][1]); - } -/* - //! Compute a cofactor. Used for matrix inversion. - float CoFactor(ubyte row, ubyte column) const - { - static sdword gIndex[3+2] = { 0, 1, 2, 0, 1 }; - return (m[gIndex[row+1]][gIndex[column+1]]*m[gIndex[row+2]][gIndex[column+2]] - m[gIndex[row+2]][gIndex[column+1]]*m[gIndex[row+1]][gIndex[column+2]]); - } -*/ - //! Invert the matrix. Determinant must be different from zero, else matrix can't be inverted. - Matrix3x3& Invert() - { - float Det = Determinant(); // Must be !=0 - float OneOverDet = 1.0f / Det; - - Matrix3x3 Temp; - Temp.m[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDet; - Temp.m[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDet; - Temp.m[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDet; - Temp.m[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDet; - Temp.m[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDet; - Temp.m[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDet; - Temp.m[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDet; - Temp.m[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDet; - Temp.m[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDet; - - *this = Temp; - - return *this; - } - - Matrix3x3& Normalize(); - - //! this = exp(a) - Matrix3x3& Exp(const Matrix3x3& a); - -void FromQuat(const Quat &q); -void FromQuatL2(const Quat &q, float l2); - - // Arithmetic operators - //! Operator for Matrix3x3 Plus = Matrix3x3 + Matrix3x3; - inline_ Matrix3x3 operator+(const Matrix3x3& mat) const - { - return Matrix3x3( - m[0][0] + mat.m[0][0], m[0][1] + mat.m[0][1], m[0][2] + mat.m[0][2], - m[1][0] + mat.m[1][0], m[1][1] + mat.m[1][1], m[1][2] + mat.m[1][2], - m[2][0] + mat.m[2][0], m[2][1] + mat.m[2][1], m[2][2] + mat.m[2][2]); - } - - //! Operator for Matrix3x3 Minus = Matrix3x3 - Matrix3x3; - inline_ Matrix3x3 operator-(const Matrix3x3& mat) const - { - return Matrix3x3( - m[0][0] - mat.m[0][0], m[0][1] - mat.m[0][1], m[0][2] - mat.m[0][2], - m[1][0] - mat.m[1][0], m[1][1] - mat.m[1][1], m[1][2] - mat.m[1][2], - m[2][0] - mat.m[2][0], m[2][1] - mat.m[2][1], m[2][2] - mat.m[2][2]); - } - - //! Operator for Matrix3x3 Mul = Matrix3x3 * Matrix3x3; - inline_ Matrix3x3 operator*(const Matrix3x3& mat) const - { - return Matrix3x3( - m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0], - m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1], - m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2], - - m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0], - m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1], - m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2], - - m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0], - m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1], - m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2]); - } - - //! Operator for Point Mul = Matrix3x3 * Point; - inline_ IcePoint operator*(const IcePoint& v) const { return IcePoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v); } - - //! Operator for Matrix3x3 Mul = Matrix3x3 * float; - inline_ Matrix3x3 operator*(float s) const - { - return Matrix3x3( - m[0][0]*s, m[0][1]*s, m[0][2]*s, - m[1][0]*s, m[1][1]*s, m[1][2]*s, - m[2][0]*s, m[2][1]*s, m[2][2]*s); - } - - //! Operator for Matrix3x3 Mul = float * Matrix3x3; - inline_ friend Matrix3x3 operator*(float s, const Matrix3x3& mat) - { - return Matrix3x3( - s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], - s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], - s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2]); - } - - //! Operator for Matrix3x3 Div = Matrix3x3 / float; - inline_ Matrix3x3 operator/(float s) const - { - if (s) s = 1.0f / s; - return Matrix3x3( - m[0][0]*s, m[0][1]*s, m[0][2]*s, - m[1][0]*s, m[1][1]*s, m[1][2]*s, - m[2][0]*s, m[2][1]*s, m[2][2]*s); - } - - //! Operator for Matrix3x3 Div = float / Matrix3x3; - inline_ friend Matrix3x3 operator/(float s, const Matrix3x3& mat) - { - return Matrix3x3( - s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], - s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], - s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2]); - } - - //! Operator for Matrix3x3 += Matrix3x3 - inline_ Matrix3x3& operator+=(const Matrix3x3& mat) - { - m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; - m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; - m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; - return *this; - } - - //! Operator for Matrix3x3 -= Matrix3x3 - inline_ Matrix3x3& operator-=(const Matrix3x3& mat) - { - m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; - m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; - m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; - return *this; - } - - //! Operator for Matrix3x3 *= Matrix3x3 - inline_ Matrix3x3& operator*=(const Matrix3x3& mat) - { - IcePoint TempRow; - - GetRow(0, TempRow); - m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; - m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; - m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; - - GetRow(1, TempRow); - m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; - m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; - m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; - - GetRow(2, TempRow); - m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; - m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; - m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; - return *this; - } - - //! Operator for Matrix3x3 *= float - inline_ Matrix3x3& operator*=(float s) - { - m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; - m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; - m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; - return *this; - } - - //! Operator for Matrix3x3 /= float - inline_ Matrix3x3& operator/=(float s) - { - if (s) s = 1.0f / s; - m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; - m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; - m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; - return *this; - } - - // Cast operators - //! Cast a Matrix3x3 to a Matrix4x4. - operator Matrix4x4() const; - //! Cast a Matrix3x3 to a Quat. - operator Quat() const; - - inline_ const IcePoint& operator[](int row) const { return *(const IcePoint*)&m[row][0]; } - inline_ IcePoint& operator[](int row) { return *(IcePoint*)&m[row][0]; } - - public: - - float m[3][3]; - }; - -#endif // __ICEMATRIX3X3_H__ - diff --git a/contrib/Opcode/Ice/IceMatrix4x4.cpp b/contrib/Opcode/Ice/IceMatrix4x4.cpp deleted file mode 100644 index f9d8997..0000000 --- a/contrib/Opcode/Ice/IceMatrix4x4.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for 4x4 matrices. - * \file IceMatrix4x4.cpp - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * 4x4 matrix. - * DirectX-compliant, ie row-column order, ie m[Row][Col]. - * Same as: - * m11 m12 m13 m14 first row. - * m21 m22 m23 m24 second row. - * m31 m32 m33 m34 third row. - * m41 m42 m43 m44 fourth row. - * Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1). - * Stored in memory as m11 m12 m13 m14 m21... - * - * Multiplication rules: - * - * [x'y'z'1] = [xyz1][M] - * - * x' = x*m11 + y*m21 + z*m31 + m41 - * y' = x*m12 + y*m22 + z*m32 + m42 - * z' = x*m13 + y*m23 + z*m33 + m43 - * 1' = 0 + 0 + 0 + m44 - * - * \class Matrix4x4 - * \author Pierre Terdiman - * \version 1.0 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Inverts a PR matrix. (which only contains a rotation and a translation) - * This is faster and less subject to FPU errors than the generic inversion code. - * - * \relates Matrix4x4 - * \fn InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src) - * \param dest [out] destination matrix - * \param src [in] source matrix - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src) -{ - dest.m[0][0] = src.m[0][0]; - dest.m[1][0] = src.m[0][1]; - dest.m[2][0] = src.m[0][2]; - dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]); - - dest.m[0][1] = src.m[1][0]; - dest.m[1][1] = src.m[1][1]; - dest.m[2][1] = src.m[1][2]; - dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]); - - dest.m[0][2] = src.m[2][0]; - dest.m[1][2] = src.m[2][1]; - dest.m[2][2] = src.m[2][2]; - dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]); - - dest.m[0][3] = 0.0f; - dest.m[1][3] = 0.0f; - dest.m[2][3] = 0.0f; - dest.m[3][3] = 1.0f; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Compute the cofactor of the Matrix at a specified location -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float Matrix4x4::CoFactor(udword row, udword col) const -{ - return (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] + - m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] + - m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3]) - - (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] + - m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] + - m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Compute the determinant of the Matrix -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float Matrix4x4::Determinant() const -{ - return m[0][0] * CoFactor(0, 0) + - m[0][1] * CoFactor(0, 1) + - m[0][2] * CoFactor(0, 2) + - m[0][3] * CoFactor(0, 3); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Compute the inverse of the matrix -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Matrix4x4& Matrix4x4::Invert() -{ - float Det = Determinant(); - Matrix4x4 Temp; - - if(fabsf(Det) < MATRIX4X4_EPSILON) - return *this; // The matrix is not invertible! Singular case! - - float IDet = 1.0f / Det; - - Temp.m[0][0] = CoFactor(0,0) * IDet; - Temp.m[1][0] = CoFactor(0,1) * IDet; - Temp.m[2][0] = CoFactor(0,2) * IDet; - Temp.m[3][0] = CoFactor(0,3) * IDet; - Temp.m[0][1] = CoFactor(1,0) * IDet; - Temp.m[1][1] = CoFactor(1,1) * IDet; - Temp.m[2][1] = CoFactor(1,2) * IDet; - Temp.m[3][1] = CoFactor(1,3) * IDet; - Temp.m[0][2] = CoFactor(2,0) * IDet; - Temp.m[1][2] = CoFactor(2,1) * IDet; - Temp.m[2][2] = CoFactor(2,2) * IDet; - Temp.m[3][2] = CoFactor(2,3) * IDet; - Temp.m[0][3] = CoFactor(3,0) * IDet; - Temp.m[1][3] = CoFactor(3,1) * IDet; - Temp.m[2][3] = CoFactor(3,2) * IDet; - Temp.m[3][3] = CoFactor(3,3) * IDet; - - *this = Temp; - - return *this; -} - diff --git a/contrib/Opcode/Ice/IceMatrix4x4.h b/contrib/Opcode/Ice/IceMatrix4x4.h deleted file mode 100644 index 82ebc05..0000000 --- a/contrib/Opcode/Ice/IceMatrix4x4.h +++ /dev/null @@ -1,455 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for 4x4 matrices. - * \file IceMatrix4x4.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEMATRIX4X4_H__ -#define __ICEMATRIX4X4_H__ - - // Forward declarations - class PRS; - class PR; - - #define MATRIX4X4_EPSILON (1.0e-7f) - - class ICEMATHS_API Matrix4x4 - { -// void LUBackwardSubstitution( sdword *indx, float* b ); -// void LUDecomposition( sdword* indx, float* d ); - - public: - //! Empty constructor. - inline_ Matrix4x4() {} - //! Constructor from 16 values - inline_ Matrix4x4( float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) - { - m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; - m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; - m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; - m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; - } - //! Copy constructor - inline_ Matrix4x4(const Matrix4x4& mat) { CopyMemory(m, &mat.m, 16*sizeof(float)); } - //! Destructor. - inline_ ~Matrix4x4() {} - - //! Assign values (rotation only) - inline_ Matrix4x4& Set( float m00, float m01, float m02, - float m10, float m11, float m12, - float m20, float m21, float m22) - { - m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; - m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; - m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; - return *this; - } - //! Assign values - inline_ Matrix4x4& Set( float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) - { - m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; - m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; - m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; - m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; - return *this; - } - - //! Copy from a Matrix4x4 - inline_ void Copy(const Matrix4x4& source) { CopyMemory(m, source.m, 16*sizeof(float)); } - - // Row-column access - //! Returns a row. - inline_ void GetRow(const udword r, HPoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; p.w=m[r][3]; } - //! Returns a row. - inline_ void GetRow(const udword r, IcePoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; } - //! Returns a row. - inline_ const HPoint& GetRow(const udword r) const { return *(const HPoint*)&m[r][0]; } - //! Returns a row. - inline_ HPoint& GetRow(const udword r) { return *(HPoint*)&m[r][0]; } - //! Sets a row. - inline_ void SetRow(const udword r, const HPoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]=p.w; } - //! Sets a row. - inline_ void SetRow(const udword r, const IcePoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]= (r!=3) ? 0.0f : 1.0f; } - //! Returns a column. - inline_ void GetCol(const udword c, HPoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; p.w=m[3][c]; } - //! Returns a column. - inline_ void GetCol(const udword c, IcePoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; } - //! Sets a column. - inline_ void SetCol(const udword c, const HPoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]=p.w; } - //! Sets a column. - inline_ void SetCol(const udword c, const IcePoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]= (c!=3) ? 0.0f : 1.0f; } - - // Translation - //! Returns the translation part of the matrix. - inline_ const HPoint& GetTrans() const { return GetRow(3); } - //! Gets the translation part of the matrix - inline_ void GetTrans(IcePoint& p) const { p.x=m[3][0]; p.y=m[3][1]; p.z=m[3][2]; } - //! Sets the translation part of the matrix, from a Point. - inline_ void SetTrans(const IcePoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; } - //! Sets the translation part of the matrix, from a HPoint. - inline_ void SetTrans(const HPoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; m[3][3]=p.w; } - //! Sets the translation part of the matrix, from floats. - inline_ void SetTrans(float tx, float ty, float tz) { m[3][0]=tx; m[3][1]=ty; m[3][2]=tz; } - - // Scale - //! Sets the scale from a Point. The point is put on the diagonal. - inline_ void SetScale(const IcePoint& p) { m[0][0]=p.x; m[1][1]=p.y; m[2][2]=p.z; } - //! Sets the scale from floats. Values are put on the diagonal. - inline_ void SetScale(float sx, float sy, float sz) { m[0][0]=sx; m[1][1]=sy; m[2][2]=sz; } - //! Scales from a Point. Each row is multiplied by a component. - void Scale(const IcePoint& p) - { - m[0][0] *= p.x; m[1][0] *= p.y; m[2][0] *= p.z; - m[0][1] *= p.x; m[1][1] *= p.y; m[2][1] *= p.z; - m[0][2] *= p.x; m[1][2] *= p.y; m[2][2] *= p.z; - } - //! Scales from floats. Each row is multiplied by a value. - void Scale(float sx, float sy, float sz) - { - m[0][0] *= sx; m[1][0] *= sy; m[2][0] *= sz; - m[0][1] *= sx; m[1][1] *= sy; m[2][1] *= sz; - m[0][2] *= sx; m[1][2] *= sy; m[2][2] *= sz; - } -/* - //! Returns a row. - inline_ HPoint GetRow(const udword row) const { return mRow[row]; } - //! Sets a row. - inline_ Matrix4x4& SetRow(const udword row, const HPoint& p) { mRow[row] = p; return *this; } - //! Sets a row. - Matrix4x4& SetRow(const udword row, const Point& p) - { - m[row][0] = p.x; - m[row][1] = p.y; - m[row][2] = p.z; - m[row][3] = (row != 3) ? 0.0f : 1.0f; - return *this; - } - //! Returns a column. - HPoint GetCol(const udword col) const - { - HPoint Res; - Res.x = m[0][col]; - Res.y = m[1][col]; - Res.z = m[2][col]; - Res.w = m[3][col]; - return Res; - } - //! Sets a column. - Matrix4x4& SetCol(const udword col, const HPoint& p) - { - m[0][col] = p.x; - m[1][col] = p.y; - m[2][col] = p.z; - m[3][col] = p.w; - return *this; - } - //! Sets a column. - Matrix4x4& SetCol(const udword col, const Point& p) - { - m[0][col] = p.x; - m[1][col] = p.y; - m[2][col] = p.z; - m[3][col] = (col != 3) ? 0.0f : 1.0f; - return *this; - } -*/ - //! Computes the trace. The trace is the sum of the 4 diagonal components. - inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2] + m[3][3]; } - //! Computes the trace of the upper 3x3 matrix. - inline_ float Trace3x3() const { return m[0][0] + m[1][1] + m[2][2]; } - //! Clears the matrix. - inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } - //! Sets the identity matrix. - inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; } - //! Checks for identity - inline_ bool IsIdentity() const - { - if(IR(m[0][0])!=IEEE_1_0) return false; - if(IR(m[0][1])!=0) return false; - if(IR(m[0][2])!=0) return false; - if(IR(m[0][3])!=0) return false; - - if(IR(m[1][0])!=0) return false; - if(IR(m[1][1])!=IEEE_1_0) return false; - if(IR(m[1][2])!=0) return false; - if(IR(m[1][3])!=0) return false; - - if(IR(m[2][0])!=0) return false; - if(IR(m[2][1])!=0) return false; - if(IR(m[2][2])!=IEEE_1_0) return false; - if(IR(m[2][3])!=0) return false; - - if(IR(m[3][0])!=0) return false; - if(IR(m[3][1])!=0) return false; - if(IR(m[3][2])!=0) return false; - if(IR(m[3][3])!=IEEE_1_0) return false; - return true; - } - - //! Checks matrix validity - inline_ BOOL IsValid() const - { - for(udword j=0;j<4;j++) - { - for(udword i=0;i<4;i++) - { - if(!IsValidFloat(m[j][i])) return FALSE; - } - } - return TRUE; - } - - //! Sets a rotation matrix around the X axis. - void RotX(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin; m[1][2] = Sin; } - //! Sets a rotation matrix around the Y axis. - void RotY(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin; m[0][2] = -Sin; } - //! Sets a rotation matrix around the Z axis. - void RotZ(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin; m[0][1] = Sin; } - - //! Makes a rotation matrix about an arbitrary axis - Matrix4x4& Rot(float angle, IcePoint& p1, IcePoint& p2); - - //! Transposes the matrix. - void Transpose() - { - IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]); - IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]); - IR(m[3][0]) ^= IR(m[0][3]); IR(m[0][3]) ^= IR(m[3][0]); IR(m[3][0]) ^= IR(m[0][3]); - IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); - IR(m[1][3]) ^= IR(m[3][1]); IR(m[3][1]) ^= IR(m[1][3]); IR(m[1][3]) ^= IR(m[3][1]); - IR(m[2][3]) ^= IR(m[3][2]); IR(m[3][2]) ^= IR(m[2][3]); IR(m[2][3]) ^= IR(m[3][2]); - } - - //! Computes a cofactor. Used for matrix inversion. - float CoFactor(udword row, udword col) const; - //! Computes the determinant of the matrix. - float Determinant() const; - //! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted. - Matrix4x4& Invert(); -// Matrix& ComputeAxisMatrix(Point& axis, float angle); - - // Cast operators - //! Casts a Matrix4x4 to a Matrix3x3. - inline_ operator Matrix3x3() const - { - return Matrix3x3( - m[0][0], m[0][1], m[0][2], - m[1][0], m[1][1], m[1][2], - m[2][0], m[2][1], m[2][2]); - } - //! Casts a Matrix4x4 to a Quat. - operator Quat() const; - //! Casts a Matrix4x4 to a PR. - operator PR() const; - - // Arithmetic operators - //! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4; - inline_ Matrix4x4 operator+(const Matrix4x4& mat) const - { - return Matrix4x4( - m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3], - m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3], - m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3], - m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]); - } - - //! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4; - inline_ Matrix4x4 operator-(const Matrix4x4& mat) const - { - return Matrix4x4( - m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3], - m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3], - m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3], - m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]); - } - - //! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4; - inline_ Matrix4x4 operator*(const Matrix4x4& mat) const - { - return Matrix4x4( - m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0], - m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1], - m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2], - m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3], - - m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0], - m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1], - m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2], - m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3], - - m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0], - m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1], - m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2], - m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3], - - m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0], - m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1], - m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2], - m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]); - } - - //! Operator for HPoint Mul = Matrix4x4 * HPoint; - inline_ HPoint operator*(const HPoint& v) const { return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); } - - //! Operator for Point Mul = Matrix4x4 * Point; - inline_ IcePoint operator*(const IcePoint& v) const - { - return IcePoint( m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3], - m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3], - m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3] ); - } - - //! Operator for Matrix4x4 Scale = Matrix4x4 * float; - inline_ Matrix4x4 operator*(float s) const - { - return Matrix4x4( - m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, - m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, - m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, - m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); - } - - //! Operator for Matrix4x4 Scale = float * Matrix4x4; - inline_ friend Matrix4x4 operator*(float s, const Matrix4x4& mat) - { - return Matrix4x4( - s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[0][3], - s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[1][3], - s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2], s*mat.m[2][3], - s*mat.m[3][0], s*mat.m[3][1], s*mat.m[3][2], s*mat.m[3][3]); - } - - //! Operator for Matrix4x4 Div = Matrix4x4 / float; - inline_ Matrix4x4 operator/(float s) const - { - if(s) s = 1.0f / s; - - return Matrix4x4( - m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, - m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, - m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, - m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); - } - - //! Operator for Matrix4x4 Div = float / Matrix4x4; - inline_ friend Matrix4x4 operator/(float s, const Matrix4x4& mat) - { - return Matrix4x4( - s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[0][3], - s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[1][3], - s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2], s/mat.m[2][3], - s/mat.m[3][0], s/mat.m[3][1], s/mat.m[3][2], s/mat.m[3][3]); - } - - //! Operator for Matrix4x4 += Matrix4x4; - inline_ Matrix4x4& operator+=(const Matrix4x4& mat) - { - m[0][0]+=mat.m[0][0]; m[0][1]+=mat.m[0][1]; m[0][2]+=mat.m[0][2]; m[0][3]+=mat.m[0][3]; - m[1][0]+=mat.m[1][0]; m[1][1]+=mat.m[1][1]; m[1][2]+=mat.m[1][2]; m[1][3]+=mat.m[1][3]; - m[2][0]+=mat.m[2][0]; m[2][1]+=mat.m[2][1]; m[2][2]+=mat.m[2][2]; m[2][3]+=mat.m[2][3]; - m[3][0]+=mat.m[3][0]; m[3][1]+=mat.m[3][1]; m[3][2]+=mat.m[3][2]; m[3][3]+=mat.m[3][3]; - return *this; - } - - //! Operator for Matrix4x4 -= Matrix4x4; - inline_ Matrix4x4& operator-=(const Matrix4x4& mat) - { - m[0][0]-=mat.m[0][0]; m[0][1]-=mat.m[0][1]; m[0][2]-=mat.m[0][2]; m[0][3]-=mat.m[0][3]; - m[1][0]-=mat.m[1][0]; m[1][1]-=mat.m[1][1]; m[1][2]-=mat.m[1][2]; m[1][3]-=mat.m[1][3]; - m[2][0]-=mat.m[2][0]; m[2][1]-=mat.m[2][1]; m[2][2]-=mat.m[2][2]; m[2][3]-=mat.m[2][3]; - m[3][0]-=mat.m[3][0]; m[3][1]-=mat.m[3][1]; m[3][2]-=mat.m[3][2]; m[3][3]-=mat.m[3][3]; - return *this; - } - - //! Operator for Matrix4x4 *= Matrix4x4; - Matrix4x4& operator*=(const Matrix4x4& mat) - { - HPoint TempRow; - - GetRow(0, TempRow); - m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; - m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; - m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; - m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; - - GetRow(1, TempRow); - m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; - m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; - m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; - m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; - - GetRow(2, TempRow); - m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; - m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; - m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; - m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; - - GetRow(3, TempRow); - m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; - m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; - m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; - m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; - - return *this; - } - - //! Operator for Matrix4x4 *= float; - inline_ Matrix4x4& operator*=(float s) - { - m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; - m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; - m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; - m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; - return *this; - } - - //! Operator for Matrix4x4 /= float; - inline_ Matrix4x4& operator/=(float s) - { - if(s) s = 1.0f / s; - m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; - m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; - m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; - m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; - return *this; - } - - inline_ const HPoint& operator[](int row) const { return *(const HPoint*)&m[row][0]; } - inline_ HPoint& operator[](int row) { return *(HPoint*)&m[row][0]; } - - public: - - float m[4][4]; - }; - - //! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix - inline_ void TransformPoint4x3(IcePoint& dest, const IcePoint& source, const Matrix4x4& rot) - { - dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; - dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; - dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; - } - - //! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix - inline_ void TransformPoint3x3(IcePoint& dest, const IcePoint& source, const Matrix4x4& rot) - { - dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; - dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; - dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; - } - - ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src); - -#endif // __ICEMATRIX4X4_H__ - diff --git a/contrib/Opcode/Ice/IceMemoryMacros.h b/contrib/Opcode/Ice/IceMemoryMacros.h deleted file mode 100644 index 0987e11..0000000 --- a/contrib/Opcode/Ice/IceMemoryMacros.h +++ /dev/null @@ -1,89 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains all memory macros. - * \file IceMemoryMacros.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEMEMORYMACROS_H__ -#define __ICEMEMORYMACROS_H__ - -#undef ZeroMemory -#undef CopyMemory -#undef MoveMemory -#undef FillMemory - - //! Clears a buffer. - //! \param addr [in] buffer address - //! \param size [in] buffer length - //! \see FillMemory - //! \see StoreDwords - //! \see CopyMemory - //! \see MoveMemory - inline_ void ZeroMemory(void* addr, udword size) { memset(addr, 0, size); } - - //! Fills a buffer with a given byte. - //! \param addr [in] buffer address - //! \param size [in] buffer length - //! \param val [in] the byte value - //! \see StoreDwords - //! \see ZeroMemory - //! \see CopyMemory - //! \see MoveMemory - inline_ void FillMemory(void* dest, udword size, ubyte val) { memset(dest, val, size); } - - //! Fills a buffer with a given dword. - //! \param addr [in] buffer address - //! \param nb [in] number of dwords to write - //! \param value [in] the dword value - //! \see FillMemory - //! \see ZeroMemory - //! \see CopyMemory - //! \see MoveMemory - //! \warning writes nb*4 bytes ! - inline_ void StoreDwords(udword* dest, udword nb, udword value) - { - while (nb--) *dest++ = value; - } - - //! Copies a buffer. - //! \param addr [in] destination buffer address - //! \param addr [in] source buffer address - //! \param size [in] buffer length - //! \see ZeroMemory - //! \see FillMemory - //! \see StoreDwords - //! \see MoveMemory - inline_ void CopyMemory(void* dest, const void* src, udword size) { memcpy(dest, src, size); } - - //! Moves a buffer. - //! \param addr [in] destination buffer address - //! \param addr [in] source buffer address - //! \param size [in] buffer length - //! \see ZeroMemory - //! \see FillMemory - //! \see StoreDwords - //! \see CopyMemory - inline_ void MoveMemory(void* dest, const void* src, udword size) { memmove(dest, src, size); } - - #define SIZEOFOBJECT sizeof(*this) //!< Gives the size of current object. Avoid some mistakes (e.g. "sizeof(this)"). - //#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); } //!< Clears current object. Laziness is my business. HANDLE WITH CARE. - #define DELETESINGLE(x) if (x) { delete x; x = null; } //!< Deletes an instance of a class. - #define DELETEARRAY(x) if (x) { delete []x; x = null; } //!< Deletes an array. - #define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; } //!< Safe D3D-style release - #define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release - -#ifdef __ICEERROR_H__ - #define CHECKALLOC(x) if(!x) return SetIceError;; // ("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE. -#else - #define CHECKALLOC(x) if(!x) return false; -#endif - - //! Standard allocation cycle - #define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr); - -#endif // __ICEMEMORYMACROS_H__ diff --git a/contrib/Opcode/Ice/IceOBB.cpp b/contrib/Opcode/Ice/IceOBB.cpp deleted file mode 100644 index ac9dbf7..0000000 --- a/contrib/Opcode/Ice/IceOBB.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains OBB-related code. - * \file IceOBB.cpp - * \author Pierre Terdiman - * \date January, 29, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * An Oriented Bounding Box (OBB). - * \class OBB - * \author Pierre Terdiman - * \version 1.0 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Tests if a point is contained within the OBB. - * \param p [in] the world point to test - * \return true if inside the OBB - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool OBB::ContainsPoint(const IcePoint& p) const -{ - // IcePoint in OBB test using lazy evaluation and early exits - - // Translate to box space - IcePoint RelPoint = p - mCenter; - - // IcePoint * mRot maps from box space to world space - // mRot * IcePoint maps from world space to box space (what we need here) - - float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z; - if(f >= mExtents.x || f <= -mExtents.x) return false; - - f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z; - if(f >= mExtents.y || f <= -mExtents.y) return false; - - f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z; - if(f >= mExtents.z || f <= -mExtents.z) return false; - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds an OBB from an AABB and a world transform. - * \param aabb [in] the aabb - * \param mat [in] the world transform - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBB::Create(const AABB& aabb, const Matrix4x4& mat) -{ - // Note: must be coherent with Rotate() - - aabb.GetCenter(mCenter); - aabb.GetExtents(mExtents); - // Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity). - - // So following what's done in Rotate: - // - x-form the center - mCenter *= mat; - // - combine rotation with identity, i.e. just use given matrix - mRot = mat; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the obb planes. - * \param planes [out] 6 box planes - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool OBB::ComputePlanes(IcePlane* planes) const -{ - // Checkings - if(!planes) return false; - - IcePoint Axis0 = mRot[0]; - IcePoint Axis1 = mRot[1]; - IcePoint Axis2 = mRot[2]; - - // Writes normals - planes[0].n = Axis0; - planes[1].n = -Axis0; - planes[2].n = Axis1; - planes[3].n = -Axis1; - planes[4].n = Axis2; - planes[5].n = -Axis2; - - // Compute a point on each plane - IcePoint p0 = mCenter + Axis0 * mExtents.x; - IcePoint p1 = mCenter - Axis0 * mExtents.x; - IcePoint p2 = mCenter + Axis1 * mExtents.y; - IcePoint p3 = mCenter - Axis1 * mExtents.y; - IcePoint p4 = mCenter + Axis2 * mExtents.z; - IcePoint p5 = mCenter - Axis2 * mExtents.z; - - // Compute d - planes[0].d = -(planes[0].n|p0); - planes[1].d = -(planes[1].n|p1); - planes[2].d = -(planes[2].n|p2); - planes[3].d = -(planes[3].n|p3); - planes[4].d = -(planes[4].n|p4); - planes[5].d = -(planes[5].n|p5); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the obb points. - * \param pts [out] 8 box points - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool OBB::ComputePoints(IcePoint* pts) const -{ - // Checkings - if(!pts) return false; - - IcePoint Axis0 = mRot[0]; - IcePoint Axis1 = mRot[1]; - IcePoint Axis2 = mRot[2]; - - Axis0 *= mExtents.x; - Axis1 *= mExtents.y; - Axis2 *= mExtents.z; - - // 7+------+6 0 = --- - // /| /| 1 = +-- - // / | / | 2 = ++- - // / 4+---/--+5 3 = -+- - // 3+------+2 / y z 4 = --+ - // | / | / | / 5 = +-+ - // |/ |/ |/ 6 = +++ - // 0+------+1 *---x 7 = -++ - - pts[0] = mCenter - Axis0 - Axis1 - Axis2; - pts[1] = mCenter + Axis0 - Axis1 - Axis2; - pts[2] = mCenter + Axis0 + Axis1 - Axis2; - pts[3] = mCenter - Axis0 + Axis1 - Axis2; - pts[4] = mCenter - Axis0 - Axis1 + Axis2; - pts[5] = mCenter + Axis0 - Axis1 + Axis2; - pts[6] = mCenter + Axis0 + Axis1 + Axis2; - pts[7] = mCenter - Axis0 + Axis1 + Axis2; - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes vertex normals. - * \param pts [out] 8 box points - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool OBB::ComputeVertexNormals(IcePoint* pts) const -{ - static float VertexNormals[] = - { - -INVSQRT3, -INVSQRT3, -INVSQRT3, - INVSQRT3, -INVSQRT3, -INVSQRT3, - INVSQRT3, INVSQRT3, -INVSQRT3, - -INVSQRT3, INVSQRT3, -INVSQRT3, - -INVSQRT3, -INVSQRT3, INVSQRT3, - INVSQRT3, -INVSQRT3, INVSQRT3, - INVSQRT3, INVSQRT3, INVSQRT3, - -INVSQRT3, INVSQRT3, INVSQRT3 - }; - - if(!pts) return false; - - const IcePoint* VN = (const IcePoint*)VertexNormals; - for(udword i=0;i<8;i++) - { - pts[i] = VN[i] * mRot; - } - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Returns edges. - * \return 24 indices (12 edges) indexing the list returned by ComputePoints() - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -const udword* OBB::GetEdges() const -{ - static udword Indices[] = { - 0, 1, 1, 2, 2, 3, 3, 0, - 7, 6, 6, 5, 5, 4, 4, 7, - 1, 5, 6, 2, - 3, 7, 4, 0 - }; - return Indices; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Returns local edge normals. - * \return edge normals in local space - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -const IcePoint* OBB::GetLocalEdgeNormals() const -{ - static float EdgeNormals[] = - { - 0, -INVSQRT2, -INVSQRT2, // 0-1 - INVSQRT2, 0, -INVSQRT2, // 1-2 - 0, INVSQRT2, -INVSQRT2, // 2-3 - -INVSQRT2, 0, -INVSQRT2, // 3-0 - - 0, INVSQRT2, INVSQRT2, // 7-6 - INVSQRT2, 0, INVSQRT2, // 6-5 - 0, -INVSQRT2, INVSQRT2, // 5-4 - -INVSQRT2, 0, INVSQRT2, // 4-7 - - INVSQRT2, -INVSQRT2, 0, // 1-5 - INVSQRT2, INVSQRT2, 0, // 6-2 - -INVSQRT2, INVSQRT2, 0, // 3-7 - -INVSQRT2, -INVSQRT2, 0 // 4-0 - }; - return (const IcePoint*)EdgeNormals; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Returns world edge normal - * \param edge_index [in] 0 <= edge index < 12 - * \param world_normal [out] edge normal in world space - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBB::ComputeWorldEdgeNormal(udword edge_index, IcePoint& world_normal) const -{ - ASSERT(edge_index<12); - world_normal = GetLocalEdgeNormals()[edge_index] * mRot; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes an LSS surrounding the OBB. - * \param lss [out] the LSS - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBB::ComputeLSS(LSS& lss) const -{ - IcePoint Axis0 = mRot[0]; - IcePoint Axis1 = mRot[1]; - IcePoint Axis2 = mRot[2]; - - switch(mExtents.LargestAxis()) - { - case 0: - lss.mRadius = (mExtents.y + mExtents.z)*0.5f; - lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius); - lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius); - break; - case 1: - lss.mRadius = (mExtents.x + mExtents.z)*0.5f; - lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius); - lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius); - break; - case 2: - lss.mRadius = (mExtents.x + mExtents.y)*0.5f; - lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius); - lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius); - break; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks the OBB is inside another OBB. - * \param box [in] the other OBB - * \return TRUE if we're inside the other box - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOL OBB::IsInside(const OBB& box) const -{ - // Make a 4x4 from the box & inverse it - Matrix4x4 M0Inv; - { - Matrix4x4 M0 = box.mRot; - M0.SetTrans(box.mCenter); - InvertPRMatrix(M0Inv, M0); - } - - // With our inversed 4x4, create box1 in space of box0 - OBB _1in0; - Rotate(M0Inv, _1in0); - - // This should cancel out box0's rotation, i.e. it's now an AABB. - // => Center(0,0,0), Rot(identity) - - // The two boxes are in the same space so now we can compare them. - - // Create the AABB of (box1 in space of box0) - const Matrix3x3& mtx = _1in0.mRot; - - float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x; - if(f > _1in0.mCenter.x) return FALSE; - if(-f < _1in0.mCenter.x) return FALSE; - - f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y; - if(f > _1in0.mCenter.y) return FALSE; - if(-f < _1in0.mCenter.y) return FALSE; - - f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z; - if(f > _1in0.mCenter.z) return FALSE; - if(-f < _1in0.mCenter.z) return FALSE; - - return TRUE; -} diff --git a/contrib/Opcode/Ice/IceOBB.h b/contrib/Opcode/Ice/IceOBB.h deleted file mode 100644 index c55c2d5..0000000 --- a/contrib/Opcode/Ice/IceOBB.h +++ /dev/null @@ -1,177 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains OBB-related code. (oriented bounding box) - * \file IceOBB.h - * \author Pierre Terdiman - * \date January, 13, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEOBB_H__ -#define __ICEOBB_H__ - - // Forward declarations - class LSS; - - class ICEMATHS_API OBB - { - public: - //! Constructor - inline_ OBB() {} - //! Constructor - inline_ OBB(const IcePoint& center, const IcePoint& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot) {} - //! Destructor - inline_ ~OBB() {} - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups an empty OBB. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void SetEmpty() - { - mCenter.Zero(); - mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); - mRot.Identity(); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Tests if a IcePoint is contained within the OBB. - * \param p [in] the world IcePoint to test - * \return true if inside the OBB - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool ContainsPoint(const IcePoint& p) const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Builds an OBB from an AABB and a world transform. - * \param aabb [in] the aabb - * \param mat [in] the world transform - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Create(const AABB& aabb, const Matrix4x4& mat); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Recomputes the OBB after an arbitrary transform by a 4x4 matrix. - * \param mtx [in] the transform matrix - * \param obb [out] the transformed OBB - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void Rotate(const Matrix4x4& mtx, OBB& obb) const - { - // The extents remain constant - obb.mExtents = mExtents; - // The center gets x-formed - obb.mCenter = mCenter * mtx; - // Combine rotations - obb.mRot = mRot * Matrix3x3(mtx); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks the OBB is valid. - * \return true if the box is valid - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL IsValid() const - { - // Consistency condition for (Center, Extents) boxes: Extents >= 0.0f - if(mExtents.x < 0.0f) return FALSE; - if(mExtents.y < 0.0f) return FALSE; - if(mExtents.z < 0.0f) return FALSE; - return TRUE; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes the obb planes. - * \param planes [out] 6 box planes - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool ComputePlanes(IcePlane* planes) const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes the obb points. - * \param pts [out] 8 box points - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool ComputePoints(IcePoint* pts) const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes vertex normals. - * \param pts [out] 8 box points - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool ComputeVertexNormals(IcePoint* pts) const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Returns edges. - * \return 24 indices (12 edges) indexing the list returned by ComputePoints() - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - const udword* GetEdges() const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Returns local edge normals. - * \return edge normals in local space - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - const IcePoint* GetLocalEdgeNormals() const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Returns world edge normal - * \param edge_index [in] 0 <= edge index < 12 - * \param world_normal [out] edge normal in world space - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void ComputeWorldEdgeNormal(udword edge_index, IcePoint& world_normal) const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes an LSS surrounding the OBB. - * \param lss [out] the LSS - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void ComputeLSS(LSS& lss) const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks the OBB is inside another OBB. - * \param box [in] the other OBB - * \return TRUE if we're inside the other box - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - BOOL IsInside(const OBB& box) const; - - inline_ const IcePoint& GetCenter() const { return mCenter; } - inline_ const IcePoint& GetExtents() const { return mExtents; } - inline_ const Matrix3x3& GetRot() const { return mRot; } - - inline_ void GetRotatedExtents(Matrix3x3& extents) const - { - extents = mRot; - extents.Scale(mExtents); - } - - IcePoint mCenter; //!< B for Box - IcePoint mExtents; //!< B for Bounding - Matrix3x3 mRot; //!< O for Oriented - - // Orientation is stored in row-major format, - // i.e. rows = eigen vectors of the covariance matrix - }; - -#endif // __ICEOBB_H__ diff --git a/contrib/Opcode/Ice/IcePairs.h b/contrib/Opcode/Ice/IcePairs.h deleted file mode 100644 index 2c09b92..0000000 --- a/contrib/Opcode/Ice/IcePairs.h +++ /dev/null @@ -1,45 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a simple pair class. - * \file IcePairs.h - * \author Pierre Terdiman - * \date January, 13, 2003 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEPAIRS_H__ -#define __ICEPAIRS_H__ - - //! A generic couple structure - struct ICECORE_API Pair - { - inline_ Pair() {} - inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {} - - udword id0; //!< First index of the pair - udword id1; //!< Second index of the pair - }; - - class ICECORE_API Pairs : private Container - { - public: - // Constructor / Destructor - Pairs() {} - ~Pairs() {} - - inline_ udword GetNbPairs() const { return GetNbEntries()>>1; } - inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); } - inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; } - - inline_ BOOL HasPairs() const { return IsNotEmpty(); } - - inline_ void ResetPairs() { Reset(); } - inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); } - - inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); } - inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); } - }; - -#endif // __ICEPAIRS_H__ diff --git a/contrib/Opcode/Ice/IcePlane.cpp b/contrib/Opcode/Ice/IcePlane.cpp deleted file mode 100644 index f198843..0000000 --- a/contrib/Opcode/Ice/IcePlane.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for planes. - * \file IcePlane.cpp - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * IcePlane class. - * \class IcePlane - * \author Pierre Terdiman - * \version 1.0 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the plane equation from 3 points. - * \param p0 [in] first IcePoint - * \param p1 [in] second IcePoint - * \param p2 [in] third IcePoint - * \return Self-reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -IcePlane& IcePlane::Set(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) -{ - IcePoint Edge0 = p1 - p0; - IcePoint Edge1 = p2 - p0; - - n = Edge0 ^ Edge1; - n.Normalize(); - - d = -(p0 | n); - - return *this; -} diff --git a/contrib/Opcode/Ice/IcePlane.h b/contrib/Opcode/Ice/IcePlane.h deleted file mode 100644 index 5c93b90..0000000 --- a/contrib/Opcode/Ice/IcePlane.h +++ /dev/null @@ -1,113 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for planes. - * \file IcePlane.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEPLANE_H__ -#define __ICEPLANE_H__ - - #define PLANE_EPSILON (1.0e-7f) - - class ICEMATHS_API IcePlane - { - public: - //! Constructor - inline_ IcePlane() { } - //! Constructor from a normal and a distance - inline_ IcePlane(float nx, float ny, float nz, float d) { Set(nx, ny, nz, d); } - //! Constructor from a point on the plane and a normal - inline_ IcePlane(const IcePoint& p, const IcePoint& n) { Set(p, n); } - //! Constructor from three points - inline_ IcePlane(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) { Set(p0, p1, p2); } - //! Constructor from a normal and a distance - inline_ IcePlane(const IcePoint& _n, float _d) { n = _n; d = _d; } - //! Copy constructor - inline_ IcePlane(const IcePlane& plane) : n(plane.n), d(plane.d) { } - //! Destructor - inline_ ~IcePlane() { } - - inline_ IcePlane& Zero() { n.Zero(); d = 0.0f; return *this; } - inline_ IcePlane& Set(float nx, float ny, float nz, float _d) { n.Set(nx, ny, nz); d = _d; return *this; } - inline_ IcePlane& Set(const IcePoint& p, const IcePoint& _n) { n = _n; d = - p | _n; return *this; } - IcePlane& Set(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2); - - inline_ float Distance(const IcePoint& p) const { return (p | n) + d; } - inline_ bool Belongs(const IcePoint& p) const { return fabsf(Distance(p)) < PLANE_EPSILON; } - - inline_ void Normalize() - { - float Denom = 1.0f / n.Magnitude(); - n.x *= Denom; - n.y *= Denom; - n.z *= Denom; - d *= Denom; - } - public: - // Members - IcePoint n; //!< The normal to the plane - float d; //!< The distance from the origin - - // Cast operators - inline_ operator IcePoint() const { return n; } - inline_ operator HPoint() const { return HPoint(n, d); } - - // Arithmetic operators - inline_ IcePlane operator*(const Matrix4x4& m) const - { - // Old code from Irion. Kept for reference. - IcePlane Ret(*this); - return Ret *= m; - } - - inline_ IcePlane& operator*=(const Matrix4x4& m) - { - // Old code from Irion. Kept for reference. - IcePoint n2 = HPoint(n, 0.0f) * m; - d = -((IcePoint) (HPoint( -d*n, 1.0f ) * m) | n2); - n = n2; - return *this; - } - }; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Transforms a plane by a 4x4 matrix. Same as IcePlane * Matrix4x4 operator, but faster. - * \param transformed [out] transformed plane - * \param plane [in] source plane - * \param transform [in] transform matrix - * \warning the plane normal must be unit-length - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void TransformPlane(IcePlane& transformed, const IcePlane& plane, const Matrix4x4& transform) - { - // Rotate the normal using the rotation part of the 4x4 matrix - transformed.n = plane.n * Matrix3x3(transform); - - // Compute new d - transformed.d = plane.d - (IcePoint(transform.GetTrans())|transformed.n); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Transforms a plane by a 4x4 matrix. Same as IcePlane * Matrix4x4 operator, but faster. - * \param plane [in/out] source plane (transformed on return) - * \param transform [in] transform matrix - * \warning the plane normal must be unit-length - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void TransformPlane(IcePlane& plane, const Matrix4x4& transform) - { - // Rotate the normal using the rotation part of the 4x4 matrix - plane.n *= Matrix3x3(transform); - - // Compute new d - plane.d -= IcePoint(transform.GetTrans())|plane.n; - } - -#endif // __ICEPLANE_H__ diff --git a/contrib/Opcode/Ice/IcePoint.cpp b/contrib/Opcode/Ice/IcePoint.cpp deleted file mode 100644 index 616b08c..0000000 --- a/contrib/Opcode/Ice/IcePoint.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for 3D vectors. - * \file IcePoint.cpp - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * 3D point. - * - * The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3". - * So the choice was between "Point" and "Vector3", the first one looked better (IMHO). - * - * Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3; - * This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out: - * - * \code - * Point P0,P1 = some 3D points; - * Point Delta = P1 - P0; - * \endcode - * - * This compiles fine, although you should have written: - * - * \code - * Point P0,P1 = some 3D points; - * Vector3 Delta = P1 - P0; - * \endcode - * - * Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake - * from the author or something you don't get. - * - * One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors. - * But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work. - * - * Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store - * your model's vertices and in most cases, you really want to use Points to save ram. - * - * \class Point - * \author Pierre Terdiman - * \version 1.0 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Creates a positive unit random vector. - * \return Self-reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -IcePoint& IcePoint::PositiveUnitRandomVector() -{ - x = UnitRandomFloat(); - y = UnitRandomFloat(); - z = UnitRandomFloat(); - Normalize(); - return *this; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Creates a unit random vector. - * \return Self-reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -IcePoint& IcePoint::UnitRandomVector() -{ - x = UnitRandomFloat() - 0.5f; - y = UnitRandomFloat() - 0.5f; - z = UnitRandomFloat() - 0.5f; - Normalize(); - return *this; -} - -// Cast operator -// WARNING: not inlined -IcePoint::operator HPoint() const { return HPoint(x, y, z, 0.0f); } - -IcePoint& IcePoint::Refract(const IcePoint& eye, const IcePoint& n, float refractindex, IcePoint& refracted) -{ - // IcePoint EyePt = eye position - // IcePoint p = current vertex - // IcePoint n = vertex normal - // IcePoint rv = refracted vector - // Eye vector - doesn't need to be normalized - IcePoint Env; - Env.x = eye.x - x; - Env.y = eye.y - y; - Env.z = eye.z - z; - - float NDotE = n|Env; - float NDotN = n|n; - NDotE /= refractindex; - - // Refracted vector - refracted = n*NDotE - Env*NDotN; - - return *this; -} - -IcePoint& IcePoint::ProjectToPlane(const IcePlane& p) -{ - *this-= (p.d + (*this|p.n))*p.n; - return *this; -} - -void IcePoint::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const -{ - projected = HPoint(x, y, z, 1.0f) * mat; - projected.w = 1.0f / projected.w; - - projected.x*=projected.w; - projected.y*=projected.w; - projected.z*=projected.w; - - projected.x *= halfrenderwidth; projected.x += halfrenderwidth; - projected.y *= -halfrenderheight; projected.y += halfrenderheight; -} - -void IcePoint::SetNotUsed() -{ - // We use a particular integer pattern : 0xffffffff everywhere. This is a NAN. - IR(x) = 0xffffffff; - IR(y) = 0xffffffff; - IR(z) = 0xffffffff; -} - -BOOL IcePoint::IsNotUsed() const -{ - if(IR(x)!=0xffffffff) return FALSE; - if(IR(y)!=0xffffffff) return FALSE; - if(IR(z)!=0xffffffff) return FALSE; - return TRUE; -} - -IcePoint& IcePoint::Mult(const Matrix3x3& mat, const IcePoint& a) -{ - x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; - y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; - z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; - return *this; -} - -IcePoint& IcePoint::Mult2(const Matrix3x3& mat1, const IcePoint& a1, const Matrix3x3& mat2, const IcePoint& a2) -{ - x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2]; - y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2]; - z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2]; - return *this; -} - -IcePoint& IcePoint::Mac(const Matrix3x3& mat, const IcePoint& a) -{ - x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; - y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; - z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; - return *this; -} - -IcePoint& IcePoint::TransMult(const Matrix3x3& mat, const IcePoint& a) -{ - x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0]; - y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1]; - z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2]; - return *this; -} - -IcePoint& IcePoint::Transform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos) -{ - x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x; - y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y; - z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z; - return *this; -} - -IcePoint& IcePoint::InvTransform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos) -{ - float sx = r.x - linpos.x; - float sy = r.y - linpos.y; - float sz = r.z - linpos.z; - x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0]; - y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1]; - z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2]; - return *this; -} diff --git a/contrib/Opcode/Ice/IcePoint.h b/contrib/Opcode/Ice/IcePoint.h deleted file mode 100644 index 2ca1801..0000000 --- a/contrib/Opcode/Ice/IcePoint.h +++ /dev/null @@ -1,528 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for 3D vectors. - * \file IcePoint.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEPOINT_H__ -#define __ICEPOINT_H__ - - // Forward declarations - class HPoint; - class IcePlane; - class Matrix3x3; - class Matrix4x4; - - #define CROSS2D(a, b) (a.x*b.y - b.x*a.y) - - const float EPSILON2 = 1.0e-20f; - - class ICEMATHS_API IcePoint - { - public: - - //! Empty constructor - inline_ IcePoint() {} - //! Constructor from a single float -// inline_ Point(float val) : x(val), y(val), z(val) {} -// Removed since it introduced the nasty "Point T = *Matrix4x4.GetTrans();" bug....... - //! Constructor from floats - inline_ IcePoint(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} - //! Constructor from array - inline_ IcePoint(const float f[3]) : x(f[_X]), y(f[_Y]), z(f[_Z]) {} - //! Copy constructor - inline_ IcePoint(const IcePoint& p) : x(p.x), y(p.y), z(p.z) {} - //! Destructor - inline_ ~IcePoint() {} - - //! Clears the vector - inline_ IcePoint& Zero() { x = y = z = 0.0f; return *this; } - - //! + infinity - inline_ IcePoint& SetPlusInfinity() { x = y = z = MAX_FLOAT; return *this; } - //! - infinity - inline_ IcePoint& SetMinusInfinity() { x = y = z = MIN_FLOAT; return *this; } - - //! Sets positive unit random vector - IcePoint& PositiveUnitRandomVector(); - //! Sets unit random vector - IcePoint& UnitRandomVector(); - - //! Assignment from values - inline_ IcePoint& Set(float _x, float _y, float _z) { x = _x; y = _y; z = _z; return *this; } - //! Assignment from array - inline_ IcePoint& Set(const float f[3]) { x = f[_X]; y = f[_Y]; z = f[_Z]; return *this; } - //! Assignment from another point - inline_ IcePoint& Set(const IcePoint& src) { x = src.x; y = src.y; z = src.z; return *this; } - - //! Adds a vector - inline_ IcePoint& Add(const IcePoint& p) { x += p.x; y += p.y; z += p.z; return *this; } - //! Adds a vector - inline_ IcePoint& Add(float _x, float _y, float _z) { x += _x; y += _y; z += _z; return *this; } - //! Adds a vector - inline_ IcePoint& Add(const float f[3]) { x += f[_X]; y += f[_Y]; z += f[_Z]; return *this; } - //! Adds vectors - inline_ IcePoint& Add(const IcePoint& p, const IcePoint& q) { x = p.x+q.x; y = p.y+q.y; z = p.z+q.z; return *this; } - - //! Subtracts a vector - inline_ IcePoint& Sub(const IcePoint& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } - //! Subtracts a vector - inline_ IcePoint& Sub(float _x, float _y, float _z) { x -= _x; y -= _y; z -= _z; return *this; } - //! Subtracts a vector - inline_ IcePoint& Sub(const float f[3]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; return *this; } - //! Subtracts vectors - inline_ IcePoint& Sub(const IcePoint& p, const IcePoint& q) { x = p.x-q.x; y = p.y-q.y; z = p.z-q.z; return *this; } - - //! this = -this - inline_ IcePoint& Neg() { x = -x; y = -y; z = -z; return *this; } - //! this = -a - inline_ IcePoint& Neg(const IcePoint& a) { x = -a.x; y = -a.y; z = -a.z; return *this; } - - //! Multiplies by a scalar - inline_ IcePoint& Mult(float s) { x *= s; y *= s; z *= s; return *this; } - - //! this = a * scalar - inline_ IcePoint& Mult(const IcePoint& a, float scalar) - { - x = a.x * scalar; - y = a.y * scalar; - z = a.z * scalar; - return *this; - } - - //! this = a + b * scalar - inline_ IcePoint& Mac(const IcePoint& a, const IcePoint& b, float scalar) - { - x = a.x + b.x * scalar; - y = a.y + b.y * scalar; - z = a.z + b.z * scalar; - return *this; - } - - //! this = this + a * scalar - inline_ IcePoint& Mac(const IcePoint& a, float scalar) - { - x += a.x * scalar; - y += a.y * scalar; - z += a.z * scalar; - return *this; - } - - //! this = a - b * scalar - inline_ IcePoint& Msc(const IcePoint& a, const IcePoint& b, float scalar) - { - x = a.x - b.x * scalar; - y = a.y - b.y * scalar; - z = a.z - b.z * scalar; - return *this; - } - - //! this = this - a * scalar - inline_ IcePoint& Msc(const IcePoint& a, float scalar) - { - x -= a.x * scalar; - y -= a.y * scalar; - z -= a.z * scalar; - return *this; - } - - //! this = a + b * scalarb + c * scalarc - inline_ IcePoint& Mac2(const IcePoint& a, const IcePoint& b, float scalarb, const IcePoint& c, float scalarc) - { - x = a.x + b.x * scalarb + c.x * scalarc; - y = a.y + b.y * scalarb + c.y * scalarc; - z = a.z + b.z * scalarb + c.z * scalarc; - return *this; - } - - //! this = a - b * scalarb - c * scalarc - inline_ IcePoint& Msc2(const IcePoint& a, const IcePoint& b, float scalarb, const IcePoint& c, float scalarc) - { - x = a.x - b.x * scalarb - c.x * scalarc; - y = a.y - b.y * scalarb - c.y * scalarc; - z = a.z - b.z * scalarb - c.z * scalarc; - return *this; - } - - //! this = mat * a - inline_ IcePoint& Mult(const Matrix3x3& mat, const IcePoint& a); - - //! this = mat1 * a1 + mat2 * a2 - inline_ IcePoint& Mult2(const Matrix3x3& mat1, const IcePoint& a1, const Matrix3x3& mat2, const IcePoint& a2); - - //! this = this + mat * a - inline_ IcePoint& Mac(const Matrix3x3& mat, const IcePoint& a); - - //! this = transpose(mat) * a - inline_ IcePoint& TransMult(const Matrix3x3& mat, const IcePoint& a); - - //! Linear interpolate between two vectors: this = a + t * (b - a) - inline_ IcePoint& Lerp(const IcePoint& a, const IcePoint& b, float t) - { - x = a.x + t * (b.x - a.x); - y = a.y + t * (b.y - a.y); - z = a.z + t * (b.z - a.z); - return *this; - } - - //! Hermite interpolate between p1 and p2. p0 and p3 are used for finding gradient at p1 and p2. - //! this = p0 * (2t^2 - t^3 - t)/2 - //! + p1 * (3t^3 - 5t^2 + 2)/2 - //! + p2 * (4t^2 - 3t^3 + t)/2 - //! + p3 * (t^3 - t^2)/2 - inline_ IcePoint& Herp(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2, const IcePoint& p3, float t) - { - float t2 = t * t; - float t3 = t2 * t; - float kp0 = (2.0f * t2 - t3 - t) * 0.5f; - float kp1 = (3.0f * t3 - 5.0f * t2 + 2.0f) * 0.5f; - float kp2 = (4.0f * t2 - 3.0f * t3 + t) * 0.5f; - float kp3 = (t3 - t2) * 0.5f; - x = p0.x * kp0 + p1.x * kp1 + p2.x * kp2 + p3.x * kp3; - y = p0.y * kp0 + p1.y * kp1 + p2.y * kp2 + p3.y * kp3; - z = p0.z * kp0 + p1.z * kp1 + p2.z * kp2 + p3.z * kp3; - return *this; - } - - //! this = rotpos * r + linpos - inline_ IcePoint& Transform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos); - - //! this = trans(rotpos) * (r - linpos) - inline_ IcePoint& InvTransform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos); - - //! Returns MIN(x, y, z); - inline_ float Min() const { return MIN(x, MIN(y, z)); } - //! Returns MAX(x, y, z); - inline_ float Max() const { return MAX(x, MAX(y, z)); } - //! Sets each element to be componentwise minimum - inline_ IcePoint& Min(const IcePoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); return *this; } - //! Sets each element to be componentwise maximum - inline_ IcePoint& Max(const IcePoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); return *this; } - - //! Clamps each element - inline_ IcePoint& Clamp(float min, float max) - { - if(xmax) x=max; - if(ymax) y=max; - if(zmax) z=max; - return *this; - } - - //! Computes square magnitude - inline_ float SquareMagnitude() const { return x*x + y*y + z*z; } - //! Computes magnitude - inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z); } - //! Computes volume - inline_ float Volume() const { return x * y * z; } - - //! Checks the IcePoint is near zero - inline_ bool ApproxZero() const { return SquareMagnitude() < EPSILON2; } - - //! Tests for exact zero vector - inline_ BOOL IsZero() const - { - if(IR(x) || IR(y) || IR(z)) return FALSE; - return TRUE; - } - - //! Checks IcePoint validity - inline_ BOOL IsValid() const - { - if(!IsValidFloat(x)) return FALSE; - if(!IsValidFloat(y)) return FALSE; - if(!IsValidFloat(z)) return FALSE; - return TRUE; - } - - //! Slighty moves the IcePoint - void Tweak(udword coord_mask, udword tweak_mask) - { - if(coord_mask&1) { udword Dummy = IR(x); Dummy^=tweak_mask; x = FR(Dummy); } - if(coord_mask&2) { udword Dummy = IR(y); Dummy^=tweak_mask; y = FR(Dummy); } - if(coord_mask&4) { udword Dummy = IR(z); Dummy^=tweak_mask; z = FR(Dummy); } - } - - #define TWEAKMASK 0x3fffff - #define TWEAKNOTMASK ~TWEAKMASK - //! Slighty moves the IcePoint out - inline_ void TweakBigger() - { - udword Dummy = (IR(x)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); - Dummy = (IR(y)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); - Dummy = (IR(z)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); - } - - //! Slighty moves the IcePoint in - inline_ void TweakSmaller() - { - udword Dummy = (IR(x)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); - Dummy = (IR(y)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); - Dummy = (IR(z)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); - } - - //! Normalizes the vector - inline_ IcePoint& Normalize() - { - float M = x*x + y*y + z*z; - if(M) - { - M = 1.0f / sqrtf(M); - x *= M; - y *= M; - z *= M; - } - return *this; - } - - //! Sets vector length - inline_ IcePoint& SetLength(float length) - { - float NewLength = length / Magnitude(); - x *= NewLength; - y *= NewLength; - z *= NewLength; - return *this; - } - - //! Clamps vector length - inline_ IcePoint& ClampLength(float limit_length) - { - if(limit_length>=0.0f) // Magnitude must be positive - { - float CurrentSquareLength = SquareMagnitude(); - - if(CurrentSquareLength > limit_length * limit_length) - { - float Coeff = limit_length / sqrtf(CurrentSquareLength); - x *= Coeff; - y *= Coeff; - z *= Coeff; - } - } - return *this; - } - - //! Computes distance to another IcePoint - inline_ float Distance(const IcePoint& b) const - { - return sqrtf((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); - } - - //! Computes square distance to another IcePoint - inline_ float SquareDistance(const IcePoint& b) const - { - return ((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); - } - - //! Dot product dp = this|a - inline_ float Dot(const IcePoint& p) const { return p.x * x + p.y * y + p.z * z; } - - //! Cross product this = a x b - inline_ IcePoint& Cross(const IcePoint& a, const IcePoint& b) - { - x = a.y * b.z - a.z * b.y; - y = a.z * b.x - a.x * b.z; - z = a.x * b.y - a.y * b.x; - return *this; - } - - //! Vector code ( bitmask = sign(z) | sign(y) | sign(x) ) - inline_ udword VectorCode() const - { - return (IR(x)>>31) | ((IR(y)&SIGN_BITMASK)>>30) | ((IR(z)&SIGN_BITMASK)>>29); - } - - //! Returns largest axis - inline_ PointComponent LargestAxis() const - { - const float* Vals = &x; - PointComponent m = _X; - if(Vals[_Y] > Vals[m]) m = _Y; - if(Vals[_Z] > Vals[m]) m = _Z; - return m; - } - - //! Returns closest axis - inline_ PointComponent ClosestAxis() const - { - const float* Vals = &x; - PointComponent m = _X; - if(AIR(Vals[_Y]) > AIR(Vals[m])) m = _Y; - if(AIR(Vals[_Z]) > AIR(Vals[m])) m = _Z; - return m; - } - - //! Returns smallest axis - inline_ PointComponent SmallestAxis() const - { - const float* Vals = &x; - PointComponent m = _X; - if(Vals[_Y] < Vals[m]) m = _Y; - if(Vals[_Z] < Vals[m]) m = _Z; - return m; - } - - //! Refracts the IcePoint - IcePoint& Refract(const IcePoint& eye, const IcePoint& n, float refractindex, IcePoint& refracted); - - //! Projects the IcePoint onto a plane - IcePoint& ProjectToPlane(const IcePlane& p); - - //! Projects the IcePoint onto the screen - void ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const; - - //! Unfolds the IcePoint onto a plane according to edge(a,b) - IcePoint& Unfold(IcePlane& p, IcePoint& a, IcePoint& b); - - //! Hash function from Ville Miettinen - inline_ udword GetHashValue() const - { - const udword* h = (const udword*)(this); - udword f = (h[0]+h[1]*11-(h[2]*17)) & 0x7fffffff; // avoid problems with +-0 - return (f>>22)^(f>>12)^(f); - } - - //! Stuff magic values in the IcePoint, marking it as explicitely not used. - void SetNotUsed(); - //! Checks the IcePoint is marked as not used - BOOL IsNotUsed() const; - - // Arithmetic operators - - //! Unary operator for IcePoint Negate = - IcePoint - inline_ IcePoint operator-() const { return IcePoint(-x, -y, -z); } - - //! Operator for IcePoint Plus = IcePoint + IcePoint. - inline_ IcePoint operator+(const IcePoint& p) const { return IcePoint(x + p.x, y + p.y, z + p.z); } - //! Operator for IcePoint Minus = IcePoint - IcePoint. - inline_ IcePoint operator-(const IcePoint& p) const { return IcePoint(x - p.x, y - p.y, z - p.z); } - - //! Operator for IcePoint Mul = IcePoint * IcePoint. - inline_ IcePoint operator*(const IcePoint& p) const { return IcePoint(x * p.x, y * p.y, z * p.z); } - //! Operator for IcePoint Scale = IcePoint * float. - inline_ IcePoint operator*(float s) const { return IcePoint(x * s, y * s, z * s ); } - //! Operator for IcePoint Scale = float * IcePoint. - inline_ friend IcePoint operator*(float s, const IcePoint& p) { return IcePoint(s * p.x, s * p.y, s * p.z); } - - //! Operator for IcePoint Div = IcePoint / IcePoint. - inline_ IcePoint operator/(const IcePoint& p) const { return IcePoint(x / p.x, y / p.y, z / p.z); } - //! Operator for IcePoint Scale = IcePoint / float. - inline_ IcePoint operator/(float s) const { s = 1.0f / s; return IcePoint(x * s, y * s, z * s); } - //! Operator for IcePoint Scale = float / IcePoint. - inline_ friend IcePoint operator/(float s, const IcePoint& p) { return IcePoint(s / p.x, s / p.y, s / p.z); } - - //! Operator for float DotProd = IcePoint | IcePoint. - inline_ float operator|(const IcePoint& p) const { return x*p.x + y*p.y + z*p.z; } - //! Operator for IcePoint VecProd = IcePoint ^ IcePoint. - inline_ IcePoint operator^(const IcePoint& p) const - { - return IcePoint( - y * p.z - z * p.y, - z * p.x - x * p.z, - x * p.y - y * p.x ); - } - - //! Operator for IcePoint += IcePoint. - inline_ IcePoint& operator+=(const IcePoint& p) { x += p.x; y += p.y; z += p.z; return *this; } - //! Operator for IcePoint += float. - inline_ IcePoint& operator+=(float s) { x += s; y += s; z += s; return *this; } - - //! Operator for IcePoint -= IcePoint. - inline_ IcePoint& operator-=(const IcePoint& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } - //! Operator for IcePoint -= float. - inline_ IcePoint& operator-=(float s) { x -= s; y -= s; z -= s; return *this; } - - //! Operator for IcePoint *= IcePoint. - inline_ IcePoint& operator*=(const IcePoint& p) { x *= p.x; y *= p.y; z *= p.z; return *this; } - //! Operator for IcePoint *= float. - inline_ IcePoint& operator*=(float s) { x *= s; y *= s; z *= s; return *this; } - - //! Operator for IcePoint /= IcePoint. - inline_ IcePoint& operator/=(const IcePoint& p) { x /= p.x; y /= p.y; z /= p.z; return *this; } - //! Operator for IcePoint /= float. - inline_ IcePoint& operator/=(float s) { s = 1.0f/s; x *= s; y *= s; z *= s; return *this; } - - // Logical operators - - //! Operator for "if(IcePoint==IcePoint)" - inline_ bool operator==(const IcePoint& p) const { return ( (IR(x)==IR(p.x))&&(IR(y)==IR(p.y))&&(IR(z)==IR(p.z))); } - //! Operator for "if(IcePoint!=IcePoint)" - inline_ bool operator!=(const IcePoint& p) const { return ( (IR(x)!=IR(p.x))||(IR(y)!=IR(p.y))||(IR(z)!=IR(p.z))); } - - // Arithmetic operators - - //! Operator for IcePoint Mul = IcePoint * Matrix3x3. - inline_ IcePoint operator*(const Matrix3x3& mat) const - { - class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining - const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; - - return IcePoint( - x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0], - x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1], - x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] ); - } - - //! Operator for IcePoint Mul = IcePoint * Matrix4x4. - inline_ IcePoint operator*(const Matrix4x4& mat) const - { - class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining - const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; - - return IcePoint( - x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0], - x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1], - x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]); - } - - //! Operator for IcePoint *= Matrix3x3. - inline_ IcePoint& operator*=(const Matrix3x3& mat) - { - class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining - const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; - - float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0]; - float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1]; - float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2]; - - x = xp; y = yp; z = zp; - - return *this; - } - - //! Operator for IcePoint *= Matrix4x4. - inline_ IcePoint& operator*=(const Matrix4x4& mat) - { - class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining - const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; - - float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0]; - float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1]; - float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]; - - x = xp; y = yp; z = zp; - - return *this; - } - - // Cast operators - - //! Cast a IcePoint to a HPoint. w is set to zero. - operator HPoint() const; - - inline_ operator const float*() const { return &x; } - inline_ operator float*() { return &x; } - - public: - float x, y, z; - }; - - FUNCTION ICEMATHS_API void Normalize1(IcePoint& a); - FUNCTION ICEMATHS_API void Normalize2(IcePoint& a); - -#endif //__ICEPOINT_H__ diff --git a/contrib/Opcode/Ice/IcePreprocessor.h b/contrib/Opcode/Ice/IcePreprocessor.h deleted file mode 100644 index d4ca850..0000000 --- a/contrib/Opcode/Ice/IcePreprocessor.h +++ /dev/null @@ -1,132 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains preprocessor stuff. This should be the first included header. - * \file IcePreprocessor.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICEPREPROCESSOR_H__ -#define __ICEPREPROCESSOR_H__ - - // Check platform - #if defined( _WIN32 ) || defined( WIN32 ) - #pragma message("Compiling on Windows...") - #define PLATFORM_WINDOWS - #else - #pragma message("Compiling on unknown platform...") - #endif - - // Check compiler - #if defined(_MSC_VER) - #pragma message("Compiling with VC++...") - #define COMPILER_VISUAL_CPP - #else - #pragma message("Compiling with unknown compiler...") - #endif - - // Check compiler options. If this file is included in user-apps, this - // shouldn't be needed, so that they can use what they like best. - #ifndef ICE_DONT_CHECK_COMPILER_OPTIONS - #ifdef COMPILER_VISUAL_CPP - #if defined(_CHAR_UNSIGNED) - #endif - - #if defined(_CPPRTTI) - #error Please disable RTTI... - #endif - - #if defined(_CPPUNWIND) - #error Please disable exceptions... - #endif - - #if defined(_MT) - // Multithreading - #endif - #endif - #endif - - // Check debug mode - #ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it. - #ifndef _DEBUG - #define _DEBUG - #endif - #endif - - #ifdef _DEBUG - // Here you may define items for debug builds - #endif - - #ifndef THIS_FILE - #define THIS_FILE __FILE__ - #endif - - #ifdef WIN32 - #ifndef ICE_NO_DLL - #ifdef ICECORE_EXPORTS - #define ICECORE_API __declspec(dllexport) - #else - #define ICECORE_API __declspec(dllimport) - #endif - #else - #define ICECORE_API - #endif - #else - #define ICECORE_API - #endif - - // Don't override new/delete -// #define DEFAULT_NEWDELETE - #define DONT_TRACK_MEMORY_LEAKS - - #define FUNCTION extern "C" - - // Cosmetic stuff [mainly useful with multiple inheritance] - #define override(base_class) virtual - - // Our own inline keyword, so that: - // - we can switch to __forceinline to check it's really better or not - // - we can remove __forceinline if the compiler doesn't support it -// #define inline_ __forceinline -// #define inline_ inline - - // Contributed by Bruce Mitchener - #if defined(COMPILER_VISUAL_CPP) - #define inline_ __forceinline -// #define inline_ inline - #elif defined(__GNUC__) && __GNUC__ < 3 - #define inline_ inline - #elif defined(__GNUC__) - #define inline_ inline __attribute__ ((always_inline)) - #else - #define inline_ inline - #endif - - // Down the hatch - #pragma inline_depth( 255 ) - - #ifdef COMPILER_VISUAL_CPP - #pragma intrinsic(memcmp) - #pragma intrinsic(memcpy) - #pragma intrinsic(memset) - #pragma intrinsic(strcat) - #pragma intrinsic(strcmp) - #pragma intrinsic(strcpy) - #pragma intrinsic(strlen) - #pragma intrinsic(abs) - #pragma intrinsic(labs) - #endif - - // ANSI compliance - #ifdef _DEBUG - // Remove painful warning in debug - inline_ bool __False__(){ return false; } - #define for if(__False__()){} else for - #else - #define for if(0){} else for - #endif - -#endif // __ICEPREPROCESSOR_H__ diff --git a/contrib/Opcode/Ice/IceRandom.cpp b/contrib/Opcode/Ice/IceRandom.cpp deleted file mode 100644 index 305721d..0000000 --- a/contrib/Opcode/Ice/IceRandom.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for random generators. - * \file IceRandom.cpp - * \author Pierre Terdiman - * \date August, 9, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceCore; - -void IceCore:: SRand(udword seed) -{ - srand(seed); -} - -udword IceCore::Rand() -{ - return rand(); -} - - -static BasicRandom gRandomGenerator(42); - -udword IceCore::GetRandomIndex(udword max_index) -{ - // We don't use rand() since it's limited to RAND_MAX - udword Index = gRandomGenerator.Randomize(); - return Index % max_index; -} - diff --git a/contrib/Opcode/Ice/IceRandom.h b/contrib/Opcode/Ice/IceRandom.h deleted file mode 100644 index 3170b33..0000000 --- a/contrib/Opcode/Ice/IceRandom.h +++ /dev/null @@ -1,42 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for random generators. - * \file IceRandom.h - * \author Pierre Terdiman - * \date August, 9, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICERANDOM_H__ -#define __ICERANDOM_H__ - - FUNCTION ICECORE_API void SRand(udword seed); - FUNCTION ICECORE_API udword Rand(); - - //! Returns a unit random floating-point value - inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; } - - //! Returns a random index so that 0<= index < max_index - ICECORE_API udword GetRandomIndex(udword max_index); - - class ICECORE_API BasicRandom - { - public: - - //! Constructor - inline_ BasicRandom(udword seed=0) : mRnd(seed) {} - //! Destructor - inline_ ~BasicRandom() {} - - inline_ void SetSeed(udword seed) { mRnd = seed; } - inline_ udword GetCurrentValue() const { return mRnd; } - inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; } - - private: - udword mRnd; - }; - -#endif // __ICERANDOM_H__ - diff --git a/contrib/Opcode/Ice/IceRay.cpp b/contrib/Opcode/Ice/IceRay.cpp deleted file mode 100644 index d7c617a..0000000 --- a/contrib/Opcode/Ice/IceRay.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for rays. - * \file IceRay.cpp - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Ray class. - * A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity - * \class Ray - * \author Pierre Terdiman - * \version 1.0 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/* - O = Origin = impact IcePoint - i = normalized vector along the x axis - j = normalized vector along the y axis = actually the normal vector in O - D = Direction vector, norm |D| = 1 - N = Projection of D on y axis, norm |N| = normal reaction - T = Projection of D on x axis, norm |T| = tangential reaction - R = Reflexion vector - - ^y - | - | - | - _ _ _| _ _ _ - * * *| - \ | / - \ |N / | - R\ | /D - \ | / | - \ | / - _________\|/______*_______>x - O T - - Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized. - - j|D = |j|*|D|*cos(theta) => |N| = j|D - - Then we simply have: - - D = N + T - - To compute tangential reaction : - - T = D - N - - To compute reflexion vector : - - R = N - T = N - (D-N) = 2*N - D -*/ - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -float Ray::SquareDistance(const IcePoint& Point, float* t) const -{ - IcePoint Diff = Point - mOrig; - float fT = Diff | mDir; - - if(fT<=0.0f) - { - fT = 0.0f; - } - else - { - fT /= mDir.SquareMagnitude(); - Diff -= fT*mDir; - } - - if(t) *t = fT; - - return Diff.SquareMagnitude(); -} diff --git a/contrib/Opcode/Ice/IceRay.h b/contrib/Opcode/Ice/IceRay.h deleted file mode 100644 index 4c0d6d9..0000000 --- a/contrib/Opcode/Ice/IceRay.h +++ /dev/null @@ -1,98 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for rays. - * \file IceRay.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICERAY_H__ -#define __ICERAY_H__ - - class ICEMATHS_API Ray - { - public: - //! Constructor - inline_ Ray() {} - //! Constructor - inline_ Ray(const IcePoint& orig, const IcePoint& dir) : mOrig(orig), mDir(dir) {} - //! Copy constructor - inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {} - //! Destructor - inline_ ~Ray() {} - - float SquareDistance(const IcePoint& point, float* t=null) const; - inline_ float Distance(const IcePoint& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } - - IcePoint mOrig; //!< Ray origin - IcePoint mDir; //!< Normalized direction - }; - - inline_ void ComputeReflexionVector(IcePoint& reflected, const IcePoint& incoming_dir, const IcePoint& outward_normal) - { - reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal); - } - - inline_ void ComputeReflexionVector(IcePoint& reflected, const IcePoint& source, const IcePoint& impact, const IcePoint& normal) - { - IcePoint V = impact - source; - reflected = V - normal * 2.0f * (V|normal); - } - - inline_ void DecomposeVector(IcePoint& normal_compo, IcePoint& tangent_compo, const IcePoint& outward_dir, const IcePoint& outward_normal) - { - normal_compo = outward_normal * (outward_dir|outward_normal); - tangent_compo = outward_dir - normal_compo; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Transforms a direction vector from world space to local space - * \param local_dir [out] direction vector in local space - * \param world_dir [in] direction vector in world space - * \param world [in] world transform - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void ComputeLocalDirection(IcePoint& local_dir, const IcePoint& world_dir, const Matrix4x4& world) - { - // Get world direction back in local space -// Matrix3x3 InvWorld = world; -// local_dir = InvWorld * world_dir; - local_dir = Matrix3x3(world) * world_dir; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Transforms a position vector from world space to local space - * \param local_pt [out] position vector in local space - * \param world_pt [in] position vector in world space - * \param world [in] world transform - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void ComputeLocalPoint(IcePoint& local_pt, const IcePoint& world_pt, const Matrix4x4& world) - { - // Get world vertex back in local space - Matrix4x4 InvWorld = world; - InvWorld.Invert(); - local_pt = world_pt * InvWorld; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Transforms a ray from world space to local space - * \param local_ray [out] ray in local space - * \param world_ray [in] ray in world space - * \param world [in] world transform - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world) - { - // Get world ray back in local space - ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world); - ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world); - } - -#endif // __ICERAY_H__ diff --git a/contrib/Opcode/Ice/IceRevisitedRadix.cpp b/contrib/Opcode/Ice/IceRevisitedRadix.cpp deleted file mode 100644 index b654995..0000000 --- a/contrib/Opcode/Ice/IceRevisitedRadix.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains source code from the article "Radix Sort Revisited". - * \file IceRevisitedRadix.cpp - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Revisited Radix Sort. - * This is my new radix routine: - * - it uses indices and doesn't recopy the values anymore, hence wasting less ram - * - it creates all the histograms in one run instead of four - * - it sorts words faster than dwords and bytes faster than words - * - it correctly sorts negative floating-point values by patching the offsets - * - it automatically takes advantage of temporal coherence - * - multiple keys support is a side effect of temporal coherence - * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway] - * - * History: - * - 08.15.98: very first version - * - 04.04.00: recoded for the radix article - * - 12.xx.00: code lifting - * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here) - * - 10.11.01: added local ram support - * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting...... - * - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all. - * - ranks are not "reset" anymore, but implicit on first calls - * - 07.05.02: - offsets rewritten with one less indirection. - * - 11.03.02: - "bool" replaced with RadixHint enum - * - * \class RadixSort - * \author Pierre Terdiman - * \version 1.4 - * \date August, 15, 1998 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/* -To do: - - add an offset parameter between two input values (avoid some data recopy sometimes) - - unroll ? asm ? - - 11 bits trick & 3 passes as Michael did - - prefetch stuff the day I have a P3 - - make a version with 16-bits indices ? -*/ - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceCore; - -#define INVALIDATE_RANKS mCurrentSize|=0x80000000 -#define VALIDATE_RANKS mCurrentSize&=0x7fffffff -#define CURRENT_SIZE (mCurrentSize&0x7fffffff) -#define INVALID_RANKS (mCurrentSize&0x80000000) - -#define CHECK_RESIZE(n) \ - if(n!=mPreviousSize) \ - { \ - if(n>mCurrentSize) Resize(n); \ - else ResetRanks(); \ - mPreviousSize = n; \ - } - -#define CREATE_HISTOGRAMS(type, buffer) \ - /* Clear counters/histograms */ \ - ZeroMemory(mHistogram, 256*4*sizeof(udword)); \ - \ - /* Prepare to count */ \ - ubyte* p = (ubyte*)input; \ - ubyte* pe = &p[nb*4]; \ - udword* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \ - udword* h1= &mHistogram[256]; /* Histogram for second pass */ \ - udword* h2= &mHistogram[512]; /* Histogram for third pass */ \ - udword* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \ - \ - bool AlreadySorted = true; /* Optimism... */ \ - \ - if(INVALID_RANKS) \ - { \ - /* Prepare for temporal coherence */ \ - type* Running = (type*)buffer; \ - type PrevVal = *Running; \ - \ - while(p!=pe) \ - { \ - /* Read input buffer in previous sorted order */ \ - type Val = *Running++; \ - /* Check whether already sorted or not */ \ - if(ValCurSize) Resize(nb); - mCurrentSize = nb; - INVALIDATE_RANKS; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Main sort routine. - * This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data. - * \param input [in] a list of integer values to sort - * \param nb [in] number of values to sort, must be < 2^31 - * \param hint [in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values - * \return Self-Reference - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint) -{ - // Checkings - if(!input || !nb || nb&0x80000000) return *this; - - // Stats - mTotalCalls++; - - // Resize lists if needed - CheckResize(nb); - -#ifdef RADIX_LOCAL_RAM - // Allocate histograms & offsets on the stack - udword mHistogram[256*4]; -// udword mOffset[256]; - udword* mLink[256]; -#endif - - // Create histograms (counters). Counters for all passes are created in one run. - // Pros: read input buffer once instead of four times - // Cons: mHistogram is 4Kb instead of 1Kb - // We must take care of signed/unsigned values for temporal coherence.... I just - // have 2 code paths even if just a single opcode changes. Self-modifying code, someone? - if(hint==RADIX_UNSIGNED) { CREATE_HISTOGRAMS(udword, input); } - else { CREATE_HISTOGRAMS(sdword, input); } - - // Compute #negative values involved if needed - udword NbNegativeValues = 0; - if(hint==RADIX_SIGNED) - { - // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128 - // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte, - // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers. - udword* h3= &mHistogram[768]; - for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part - } - - // Radix sort, j is the pass number (0=LSB, 3=MSB) - for(udword j=0;j<4;j++) - { - CHECK_PASS_VALIDITY(j); - - // Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is - // not a problem, numbers are correctly sorted anyway. - if(PerformPass) - { - // Should we care about negative values? - if(j!=3 || hint==RADIX_UNSIGNED) - { - // Here we deal with positive values only - - // Create offsets -// mOffset[0] = 0; -// for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; - mLink[0] = mRanks2; - for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; - } - else - { - // This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place. - - // Create biased offsets, in order for negative numbers to be sorted as well -// mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones - mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones -// for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers - for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers - - // Fixing the wrong place for negative values -// mOffset[128] = 0; - mLink[128] = mRanks2; -// for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; - for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; - } - - // Perform Radix Sort - ubyte* InputBytes = (ubyte*)input; - InputBytes += j; - if(INVALID_RANKS) - { -// for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). - // ### cmp to be killed. Not good. Later. -// if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above -// else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order - if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above - else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order - } - VALIDATE_RANKS; - } - else - { - for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). - // ### cmp to be killed. Not good. Later. -// if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above -// else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order - if(Radix<128) *mLink[Radix]++ = mRanks[i]; // Number is positive, same as above - else *(--mLink[Radix]) = mRanks[i]; // Number is negative, flip the sorting order - } - } - // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. - udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; - } - else - { - // The pass is useless, yet we still have to reverse the order of current list if all values are negative. - if(UniqueVal>=128) - { - if(INVALID_RANKS) - { - // ###Possible? - for(udword i=0;i=SqrLen) - { - fT = 1.0f; - Diff -= Dir; - } - else - { - fT /= SqrLen; - Diff -= fT*Dir; - } - } - - if(t) *t = fT; - - return Diff.SquareMagnitude(); -} diff --git a/contrib/Opcode/Ice/IceSegment.h b/contrib/Opcode/Ice/IceSegment.h deleted file mode 100644 index 72ddceb..0000000 --- a/contrib/Opcode/Ice/IceSegment.h +++ /dev/null @@ -1,55 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for segments. - * \file IceSegment.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICESEGMENT_H__ -#define __ICESEGMENT_H__ - - class ICEMATHS_API IceSegment - { - public: - //! Constructor - inline_ IceSegment() {} - //! Constructor - inline_ IceSegment(const IcePoint& p0, const IcePoint& p1) : mP0(p0), mP1(p1) {} - //! Copy constructor - inline_ IceSegment(const IceSegment& seg) : mP0(seg.mP0), mP1(seg.mP1) {} - //! Destructor - inline_ ~IceSegment() {} - - inline_ const IcePoint& GetOrigin() const { return mP0; } - inline_ IcePoint ComputeDirection() const { return mP1 - mP0; } - inline_ void ComputeDirection(IcePoint& dir) const { dir = mP1 - mP0; } - inline_ float ComputeLength() const { return mP1.Distance(mP0); } - inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); } - - inline_ void SetOriginDirection(const IcePoint& origin, const IcePoint& direction) - { - mP0 = mP1 = origin; - mP1 += direction; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Computes a IcePoint on the segment - * \param pt [out] IcePoint on segment - * \param t [in] IcePoint's parameter [t=0 => pt = mP0, t=1 => pt = mP1] - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void ComputePoint(IcePoint& pt, float t) const { pt = mP0 + t * (mP1 - mP0); } - - float SquareDistance(const IcePoint& IcePoint, float* t=null) const; - inline_ float Distance(const IcePoint& IcePoint, float* t=null) const { return sqrtf(SquareDistance(IcePoint, t)); } - - IcePoint mP0; //!< Start of segment - IcePoint mP1; //!< End of segment - }; - -#endif // __ICESEGMENT_H__ diff --git a/contrib/Opcode/Ice/IceTriangle.cpp b/contrib/Opcode/Ice/IceTriangle.cpp deleted file mode 100644 index e55f73e..0000000 --- a/contrib/Opcode/Ice/IceTriangle.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a handy triangle class. - * \file IceTriangle.cpp - * \author Pierre Terdiman - * \date January, 17, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace IceMaths; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a triangle class. - * - * \class Tri - * \author Pierre Terdiman - * \version 1.0 - * \date 08.15.98 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -static sdword VPlaneSideEps(const IcePoint& v, const IcePlane& plane, float epsilon) -{ - // Compute distance from current vertex to the plane - float Dist = plane.Distance(v); - // Compute side: - // 1 = the vertex is on the positive side of the plane - // -1 = the vertex is on the negative side of the plane - // 0 = the vertex is on the plane (within epsilon) - return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Flips the winding order. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Triangle::Flip() -{ - IcePoint Tmp = mVerts[1]; - mVerts[1] = mVerts[2]; - mVerts[2] = Tmp; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle area. - * \return the area - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float Triangle::Area() const -{ - const IcePoint& p0 = mVerts[0]; - const IcePoint& p1 = mVerts[1]; - const IcePoint& p2 = mVerts[2]; - return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle perimeter. - * \return the perimeter - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float Triangle::Perimeter() const -{ - const IcePoint& p0 = mVerts[0]; - const IcePoint& p1 = mVerts[1]; - const IcePoint& p2 = mVerts[2]; - return p0.Distance(p1) - + p0.Distance(p2) - + p1.Distance(p2); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle compacity. - * \return the compacity - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float Triangle::Compacity() const -{ - float P = Perimeter(); - if(P==0.0f) return 0.0f; - return (4.0f*PI*Area()/(P*P)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle normal. - * \param normal [out] the computed normal - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Triangle::Normal(IcePoint& normal) const -{ - const IcePoint& p0 = mVerts[0]; - const IcePoint& p1 = mVerts[1]; - const IcePoint& p2 = mVerts[2]; - normal = ((p0 - p1)^(p0 - p2)).Normalize(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle denormalized normal. - * \param normal [out] the computed normal - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Triangle::DenormalizedNormal(IcePoint& normal) const -{ - const IcePoint& p0 = mVerts[0]; - const IcePoint& p1 = mVerts[1]; - const IcePoint& p2 = mVerts[2]; - normal = ((p0 - p1)^(p0 - p2)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle center. - * \param center [out] the computed center - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Triangle::Center(IcePoint& center) const -{ - const IcePoint& p0 = mVerts[0]; - const IcePoint& p1 = mVerts[1]; - const IcePoint& p2 = mVerts[2]; - center = (p0 + p1 + p2)*INV3; -} - -PartVal Triangle::TestAgainstPlane(const IcePlane& plane, float epsilon) const -{ - bool Pos = false, Neg = false; - - // Loop through all vertices - for(udword i=0;i<3;i++) - { - // Compute side: - sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon); - - if (Side < 0) Neg = true; - else if (Side > 0) Pos = true; - } - - if (!Pos && !Neg) return TRI_ON_PLANE; - else if (Pos && Neg) return TRI_INTERSECT; - else if (Pos && !Neg) return TRI_PLUS_SPACE; - else if (!Pos && Neg) return TRI_MINUS_SPACE; - - // What?! - return TRI_FORCEDWORD; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle moment. - * \param m [out] the moment - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* -void Triangle::ComputeMoment(Moment& m) -{ - // Compute the area of the triangle - m.mArea = Area(); - - // Compute the centroid - Center(m.mCentroid); - - // Second-order components. Handle zero-area faces. - IcePoint& p = mVerts[0]; - IcePoint& q = mVerts[1]; - IcePoint& r = mVerts[2]; - if(m.mArea==0.0f) - { - // This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the - // sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices. - m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x); - m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y); - m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z); - m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y); - m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z); - m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z); - m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; - m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; - m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; - } - else - { - const float OneOverTwelve = 1.0f / 12.0f; - m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve; - m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve; - m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve; - m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve; - m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve; - m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve; - m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; - m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; - m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; - } -} -*/ - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle's smallest edge length. - * \return the smallest edge length - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float Triangle::MinEdgeLength() const -{ - float Min = MAX_FLOAT; - float Length01 = mVerts[0].Distance(mVerts[1]); - float Length02 = mVerts[0].Distance(mVerts[2]); - float Length12 = mVerts[1].Distance(mVerts[2]); - if(Length01 < Min) Min = Length01; - if(Length02 < Min) Min = Length02; - if(Length12 < Min) Min = Length12; - return Min; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the triangle's largest edge length. - * \return the largest edge length - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float Triangle::MaxEdgeLength() const -{ - float Max = MIN_FLOAT; - float Length01 = mVerts[0].Distance(mVerts[1]); - float Length02 = mVerts[0].Distance(mVerts[2]); - float Length12 = mVerts[1].Distance(mVerts[2]); - if(Length01 > Max) Max = Length01; - if(Length02 > Max) Max = Length02; - if(Length12 > Max) Max = Length12; - return Max; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes a IcePoint on the triangle according to the stabbing information. - * \param u,v [in] IcePoint's barycentric coordinates - * \param pt [out] IcePoint on triangle - * \param nearvtx [out] index of nearest vertex - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Triangle::ComputePoint(float u, float v, IcePoint& pt, udword* nearvtx) const -{ - // Compute IcePoint coordinates - pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2]; - - // Compute nearest vertex if needed - if(nearvtx) - { - // Compute distance vector - IcePoint d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to IcePoint on the face - mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to IcePoint on the face - mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to IcePoint on the face - - // Get smallest distance - *nearvtx = d.SmallestAxis(); - } -} - -void Triangle::Inflate(float fat_coeff, bool constant_border) -{ - // Compute triangle center - IcePoint TriangleCenter; - Center(TriangleCenter); - - // Don't normalize? - // Normalize => add a constant border, regardless of triangle size - // Don't => add more to big triangles - for(udword i=0;i<3;i++) - { - IcePoint v = mVerts[i] - TriangleCenter; - - if(constant_border) v.Normalize(); - - mVerts[i] += v * fat_coeff; - } -} diff --git a/contrib/Opcode/Ice/IceTriangle.h b/contrib/Opcode/Ice/IceTriangle.h deleted file mode 100644 index e5c8426..0000000 --- a/contrib/Opcode/Ice/IceTriangle.h +++ /dev/null @@ -1,68 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a handy triangle class. - * \file IceTriangle.h - * \author Pierre Terdiman - * \date January, 17, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICETRIANGLE_H__ -#define __ICETRIANGLE_H__ - - // Forward declarations - class Moment; - - // Partitioning values - enum PartVal - { - TRI_MINUS_SPACE = 0, //!< Triangle is in the negative space - TRI_PLUS_SPACE = 1, //!< Triangle is in the positive space - TRI_INTERSECT = 2, //!< Triangle intersects plane - TRI_ON_PLANE = 3, //!< Triangle and plane are coplanar - - TRI_FORCEDWORD = 0x7fffffff - }; - - // A triangle class. - class ICEMATHS_API Triangle - { - public: - //! Constructor - inline_ Triangle() {} - //! Constructor - inline_ Triangle(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) { mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; } - //! Copy constructor - inline_ Triangle(const Triangle& triangle) - { - mVerts[0] = triangle.mVerts[0]; - mVerts[1] = triangle.mVerts[1]; - mVerts[2] = triangle.mVerts[2]; - } - //! Destructor - inline_ ~Triangle() {} - //! Vertices - IcePoint mVerts[3]; - - // Methods - void Flip(); - float Area() const; - float Perimeter() const; - float Compacity() const; - void Normal(IcePoint& normal) const; - void DenormalizedNormal(IcePoint& normal) const; - void Center(IcePoint& center) const; - inline_ IcePlane PlaneEquation() const { return IcePlane(mVerts[0], mVerts[1], mVerts[2]); } - - PartVal TestAgainstPlane(const IcePlane& plane, float epsilon) const; -// float Distance(Point& cp, Point& cq, Tri& tri); - void ComputeMoment(Moment& m); - float MinEdgeLength() const; - float MaxEdgeLength() const; - void ComputePoint(float u, float v, IcePoint& pt, udword* nearvtx=null) const; - void Inflate(float fat_coeff, bool constant_border); - }; - -#endif // __ICETRIANGLE_H__ diff --git a/contrib/Opcode/Ice/IceTrilist.h b/contrib/Opcode/Ice/IceTrilist.h deleted file mode 100644 index 057f8df..0000000 --- a/contrib/Opcode/Ice/IceTrilist.h +++ /dev/null @@ -1,61 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for a triangle container. - * \file IceTrilist.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICETRILIST_H__ -#define __ICETRILIST_H__ - - class ICEMATHS_API TriList : public Container - { - public: - // Constructor / Destructor - TriList() {} - ~TriList() {} - - inline_ udword GetNbTriangles() const { return GetNbEntries()/9; } - inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); } - - void AddTri(const Triangle& tri) - { - Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z); - Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z); - Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z); - } - - void AddTri(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) - { - Add(p0.x).Add(p0.y).Add(p0.z); - Add(p1.x).Add(p1.y).Add(p1.z); - Add(p2.x).Add(p2.y).Add(p2.z); - } - }; - - class ICEMATHS_API TriangleList : public Container - { - public: - // Constructor / Destructor - TriangleList() {} - ~TriangleList() {} - - inline_ udword GetNbTriangles() const { return GetNbEntries()/3; } - inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();} - - void AddTriangle(const IndexedTriangle& tri) - { - Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]); - } - - void AddTriangle(udword vref0, udword vref1, udword vref2) - { - Add(vref0).Add(vref1).Add(vref2); - } - }; - -#endif //__ICETRILIST_H__ diff --git a/contrib/Opcode/Ice/IceTypes.h b/contrib/Opcode/Ice/IceTypes.h deleted file mode 100644 index 75104fa..0000000 --- a/contrib/Opcode/Ice/IceTypes.h +++ /dev/null @@ -1,164 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains custom types. - * \file IceTypes.h - * \author Pierre Terdiman - * \date April, 4, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __ICETYPES_H__ -#define __ICETYPES_H__ - -#include - - #define USE_HANDLE_MANAGER - - // Constants - #define PI 3.1415926535897932384626433832795028841971693993751f //!< PI - #define HALFPI 1.57079632679489661923f //!< 0.5 * PI - #define TWOPI 6.28318530717958647692f //!< 2.0 * PI - #define INVPI 0.31830988618379067154f //!< 1.0 / PI - - #define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees - #define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians - - #define EXP 2.71828182845904523536f //!< e - #define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2) - #define LN2 0.693147180559945f //!< ln(2) - #define INVLN2 1.44269504089f //!< 1.0f / ln(2) - - #define INV3 0.33333333333333333333f //!< 1/3 - #define INV6 0.16666666666666666666f //!< 1/6 - #define INV7 0.14285714285714285714f //!< 1/7 - #define INV9 0.11111111111111111111f //!< 1/9 - #define INV255 0.00392156862745098039f //!< 1/255 - - #define SQRT2 1.41421356237f //!< sqrt(2) - #define INVSQRT2 0.707106781188f //!< 1 / sqrt(2) - - #define SQRT3 1.73205080757f //!< sqrt(3) - #define INVSQRT3 0.577350269189f //!< 1 / sqrt(3) - - #define null 0 //!< our own NULL pointer - - // Custom types used in ICE - typedef std::int8_t sbyte; - typedef std::uint8_t ubyte; - typedef std::int16_t sword; - typedef std::uint16_t uword; - typedef std::int32_t sdword; - typedef std::uint32_t udword; - typedef std::int64_t sqword; - typedef std::uint64_t uqword; - typedef float float32; - typedef double float64; - - ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 ! - ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1); - ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1); - ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2); - ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2); - ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4); - ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4); - ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8); - ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8); - ICE_COMPILE_TIME_ASSERT(sizeof(float32)==4); - ICE_COMPILE_TIME_ASSERT(sizeof(float64)==8); - - //! TO BE DOCUMENTED - #define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name - - typedef udword DynID; //!< Dynamic identifier -#ifdef USE_HANDLE_MANAGER - typedef udword KID; //!< Kernel ID -// DECLARE_ICE_HANDLE(KID); -#else - typedef uword KID; //!< Kernel ID -#endif - typedef udword RTYPE; //!< Relationship-type (!) between owners and references - #define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers) -#ifdef USE_HANDLE_MANAGER - #define INVALID_KID 0xffffffff //!< Invalid Kernel ID -#else - #define INVALID_KID 0xffff //!< Invalid Kernel ID -#endif - #define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value - - // Define BOOL if needed - #ifndef BOOL - typedef int BOOL; //!< Another boolean type. - #endif - - //! Union of a float and a sdword - typedef union { - float f; //!< The float - sdword d; //!< The integer - }scell; - - //! Union of a float and a udword - typedef union { - float f; //!< The float - udword d; //!< The integer - }ucell; - - // Type ranges - #define MAX_SBYTE 0x7f //!< max possible sbyte value - #define MIN_SBYTE 0x80 //!< min possible sbyte value - #define MAX_UBYTE 0xff //!< max possible ubyte value - #define MIN_UBYTE 0x00 //!< min possible ubyte value - #define MAX_SWORD 0x7fff //!< max possible sword value - #define MIN_SWORD 0x8000 //!< min possible sword value - #define MAX_UWORD 0xffff //!< max possible uword value - #define MIN_UWORD 0x0000 //!< min possible uword value - #define MAX_SDWORD 0x7fffffff //!< max possible sdword value - #define MIN_SDWORD 0x80000000 //!< min possible sdword value - #define MAX_UDWORD 0xffffffff //!< max possible udword value - #define MIN_UDWORD 0x00000000 //!< min possible udword value - #define MAX_FLOAT FLT_MAX //!< max possible float value - #define MIN_FLOAT (-FLT_MAX) //!< min possible loat value - #define IEEE_1_0 0x3f800000 //!< integer representation of 1.0 - #define IEEE_255_0 0x437f0000 //!< integer representation of 255.0 - #define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT - #define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT - #define IEEE_UNDERFLOW_LIMIT 0x1a000000 - - #define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand() - #ifndef WIN32 - #define __stdcall - #endif - - typedef int (__stdcall* PROC)(); //!< A standard procedure call. - typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call - typedef void** VTABLE; //!< A V-Table. - - #undef MIN - #undef MAX - #define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b - #define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b - #define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c - - template inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; } - template inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; } - template inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; } - template inline_ void TSetMax (T& a, const T& b) { if(a> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa); - n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc); - n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0); - n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); - n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); - // Etc for larger intergers (64 bits in Java) - // NOTE: the >> operation must be unsigned! (>>> in java) - } - - //! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection) - inline_ udword CountBits(udword n) - { - // This relies of the fact that the count of n bits can NOT overflow - // an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts - // 2 bit interger, 3 bit count requires only a 2 bit interger. - // So we add all bit pairs, then each nible, then each byte etc... - n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1); - n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2); - n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4); - n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8); - n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16); - // Etc for larger intergers (64 bits in Java) - // NOTE: the >> operation must be unsigned! (>>> in java) - return n; - } - - //! Even faster? - inline_ udword CountBits2(udword bits) - { - bits = bits - ((bits >> 1) & 0x55555555); - bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333); - bits = ((bits >> 4) + bits) & 0x0F0F0F0F; - return (bits * 0x01010101) >> 24; - } - - //! Spread out bits. EG 00001111 -> 0101010101 - //! 00001010 -> 0100010000 - //! This is used to interleve to intergers to produce a `Morten Key' - //! used in Space Filling Curves (See DrDobbs Journal, July 1999) - //! Order is important. - inline_ void SpreadBits(udword& n) - { - n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16); - n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8); - n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4); - n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2); - n = ( n & 0x11111111) | (( n & 0x22222222) << 1); - } - - // Next Largest Power of 2 - // Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm - // that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with - // the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next - // largest power of 2. For a 32-bit value: - inline_ udword nlpo2(udword x) - { - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - return x+1; - } - - //! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection) - inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); } - - //! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection) - inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); } - - //! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection) - inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<> 31; return (x^y)-y; } - - //!< Alternative min function - inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); } - - // Determine if one of the bytes in a 4 byte word is zero - inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); } - - // To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0 - inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); } -// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); } - - // Most Significant 1 Bit - // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set) - // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits. - // This process yields a bit vector with the same most significant 1 as x, but all 1's below it. - // Bitwise AND of the original value with the complement of the "folded" value shifted down by one - // yields the most significant bit. For a 32-bit value: - inline_ udword msb32(udword x) - { - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - return (x & ~(x >> 1)); - } - - /* - "Just call it repeatedly with various input values and always with the same variable as "memory". - The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1 - does no filtering at all. - - I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed - to the more typical FIR (Finite Impulse Response). - - Also, I'd say that you can make more intelligent and interesting filters than this, for example filters - that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter - to be applied before this one, of course." - - (JCAB on Flipcode) - */ - inline_ float FeedbackFilter(float val, float& memory, float sharpness) - { - ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter"); - if(sharpness<0.0f) sharpness = 0.0f; - else if(sharpness>1.0f) sharpness = 1.0f; - return memory = val * sharpness + memory * (1.0f - sharpness); - } - - //! If you can guarantee that your input domain (i.e. value of x) is slightly - //! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the - //! following code to clamp the resulting value into [-32768,+32767] range: - inline_ int ClampToInt16(int x) - { -// ASSERT(abs(x) < (int)((1<<31u)-32767)); - - int delta = 32767 - x; - x += (delta>>31) & delta; - delta = x + 32768; - x -= (delta>>31) & delta; - return x; - } - - // Generic functions - template inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; } - template inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((xhi) ? hi : x); } - - template inline_ void TSort(Type& a, Type& b) - { - if(a>b) TSwap(a, b); - } - - template inline_ void TSort(Type& a, Type& b, Type& c) - { - if(a>b) TSwap(a, b); - if(b>c) TSwap(b, c); - if(a>b) TSwap(a, b); - if(b>c) TSwap(b, c); - } - - // Prevent nasty user-manipulations (strategy borrowed from Charles Bloom) -// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); } - // ... actually this is better ! - #define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object); - - //! TO BE DOCUMENTED - #define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member) - //! TO BE DOCUMENTED - #define ICEARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Returns the alignment of the input address. - * \fn Alignment() - * \param address [in] address to check - * \return the best alignment (e.g. 1 for odd addresses, etc) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - FUNCTION ICECORE_API udword Alignment(udword address); - - #define IS_ALIGNED_2(x) ((x&1)==0) - #define IS_ALIGNED_4(x) ((x&3)==0) - #define IS_ALIGNED_8(x) ((x&7)==0) - - inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; } - - // Compute implicit coords from an index: - // The idea is to get back 2D coords from a 1D index. - // For example: - // - // 0 1 2 ... nbu-1 - // nbu nbu+1 i ... - // - // We have i, we're looking for the equivalent (u=2, v=1) location. - // i = u + v*nbu - // <=> i/nbu = u/nbu + v - // Since 0 <= u < nbu, u/nbu = 0 (integer) - // Hence: v = i/nbu - // Then we simply put it back in the original equation to compute u = i - v*nbu - inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu) - { - v = i / nbu; - u = i - (v * nbu); - } - - // In 3D: i = u + v*nbu + w*nbu*nbv - // <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w - // u/(nbu*nbv) is null since u/nbu was null already. - // v/nbv is null as well for the same reason. - // Hence w = i/(nbu*nbv) - // Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu - inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv) - { - w = i / (nbu_nbv); - Compute2DCoords(u, v, i - (w * nbu_nbv), nbu); - } - -#endif // __ICEUTILS_H__ diff --git a/contrib/Opcode/OPC_AABBCollider.cpp b/contrib/Opcode/OPC_AABBCollider.cpp deleted file mode 100644 index a3cfa62..0000000 --- a/contrib/Opcode/OPC_AABBCollider.cpp +++ /dev/null @@ -1,696 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for an AABB collider. - * \file OPC_AABBCollider.cpp - * \author Pierre Terdiman - * \date January, 1st, 2002 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains an AABB-vs-tree collider. - * - * \class AABBCollider - * \author Pierre Terdiman - * \version 1.3 - * \date January, 1st, 2002 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -#include "OPC_BoxBoxOverlap.h" -#include "OPC_TriBoxOverlap.h" - -#define SET_CONTACT(prim_index, flag) \ - /* Set contact status */ \ - mFlags |= flag; \ - mTouchedPrimitives->Add(prim_index); - -//! AABB-triangle test -#define AABB_PRIM(prim_index, flag) \ - /* Request vertices from the app */ \ - VertexPointers VP; mIMesh->GetTriangle(VP, prim_index);\ - mLeafVerts[0] = *VP.Vertex[0]; \ - mLeafVerts[1] = *VP.Vertex[1]; \ - mLeafVerts[2] = *VP.Vertex[2]; \ - /* Perform triangle-box overlap test */ \ - if(TriBoxOverlap()) \ - { \ - SET_CONTACT(prim_index, flag) \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBCollider::AABBCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBCollider::~AABBCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] a box cache - * \param box [in] collision AABB in world space - * \param model [in] Opcode model to collide with - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const Model& model) -{ - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, box)) return true; - - if(!model.HasLeafNodes()) - { - if(model.IsQuantized()) - { - const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Initializes a collision query : - * - reset stats & contact status - * - check temporal coherence - * - * \param cache [in/out] a box cache - * \param box [in] AABB in world space - * \return TRUE if we can return immediately - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOL AABBCollider::InitQuery(AABBCache& cache, const CollisionAABB& box) -{ - // 1) Call the base method - VolumeCollider::InitQuery(); - - // 2) Keep track of the query box - mBox = box; - - // 3) Setup destination pointer - mTouchedPrimitives = &cache.TouchedPrimitives; - - // 4) Special case: 1-triangle meshes [Opcode 1.3] - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - if(!SkipPrimitiveTests()) - { - // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. - mTouchedPrimitives->Reset(); - - // Perform overlap test between the unique triangle and the box (and set contact status if needed) - AABB_PRIM(udword(0), OPC_CONTACT) - - // Return immediately regardless of status - return TRUE; - } - } - - // 5) Check temporal coherence : - if(TemporalCoherenceEnabled()) - { - // Here we use temporal coherence - // => check results from previous frame before performing the collision query - if(FirstContactEnabled()) - { - // We're only interested in the first contact found => test the unique previously touched face - if(mTouchedPrimitives->GetNbEntries()) - { - // Get index of previously touched face = the first entry in the array - udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); - - // Then reset the array: - // - if the overlap test below is successful, the index we'll get added back anyway - // - if it isn't, then the array should be reset anyway for the normal query - mTouchedPrimitives->Reset(); - - // Perform overlap test between the cached triangle and the box (and set contact status if needed) - AABB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) - - // Return immediately if possible - if(GetContactStatus()) return TRUE; - } - // else no face has been touched during previous query - // => we'll have to perform a normal query - } - else - { - // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): - if(IsCacheValid(cache) && mBox.IsInside(cache.FatBox)) - { - // - if N is included in P, return previous list - // => we simply leave the list (mTouchedFaces) unchanged - - // Set contact status if needed - if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; - - // In any case we don't need to do a query - return TRUE; - } - else - { - // - else do the query using a fat N - - // Reset cache since we'll about to perform a real query - mTouchedPrimitives->Reset(); - - // Make a fat box so that coherence will work for subsequent frames - mBox.mExtents *= cache.FatCoeff; - - // Update cache with query data (signature for cached faces) - cache.FatBox = mBox; - } - } - } - else - { - // Here we don't use temporal coherence => do a normal query - mTouchedPrimitives->Reset(); - } - - // 5) Precompute min & max bounds if needed - mMin = box.mCenter - box.mExtents; - mMax = box.mCenter + box.mExtents; - - return FALSE; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Collision query for vanilla AABB trees. - * \param cache [in/out] a box cache - * \param box [in] collision AABB in world space - * \param tree [in] AABB tree - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree) -{ - // This is typically called for a scene tree, full of -AABBs-, not full of triangles. - // So we don't really have "primitives" to deal with. Hence it doesn't work with - // "FirstContact" + "TemporalCoherence". - ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); - - // Checkings - if(!tree) return false; - - // Init collision query - if(InitQuery(cache, box)) return true; - - // Perform collision query - _Collide(tree); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks the AABB completely contains the box. In which case we can end the query sooner. - * \param bc [in] box center - * \param be [in] box extents - * \return true if the AABB contains the whole box - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL AABBCollider::AABBContainsBox(const IcePoint& bc, const IcePoint& be) -{ - if(mMin.x > bc.x - be.x) return FALSE; - if(mMin.y > bc.y - be.y) return FALSE; - if(mMin.z > bc.z - be.z) return FALSE; - - if(mMax.x < bc.x + be.x) return FALSE; - if(mMax.y < bc.y + be.y) return FALSE; - if(mMax.z < bc.z + be.z) return FALSE; - - return TRUE; -} - -#define TEST_BOX_IN_AABB(center, extents) \ - if(AABBContainsBox(center, extents)) \ - { \ - /* Set contact status */ \ - mFlags |= OPC_CONTACT; \ - _Dump(node); \ - return; \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_Collide(const AABBCollisionNode* node) -{ - // Perform AABB-AABB overlap test - if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; - - TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->IsLeaf()) - { - AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos()); - - if(ContactFound()) return; - - _Collide(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) -{ - // Perform AABB-AABB overlap test - if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; - - TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_Collide(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform AABB-AABB overlap test - if(!AABBAABBOverlap(Extents, Center)) return; - - TEST_BOX_IN_AABB(Center, Extents) - - if(node->IsLeaf()) - { - AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos()); - - if(ContactFound()) return; - - _Collide(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform AABB-AABB overlap test - if(!AABBAABBOverlap(Extents, Center)) return; - - TEST_BOX_IN_AABB(Center, Extents) - - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_Collide(const AABBNoLeafNode* node) -{ - // Perform AABB-AABB overlap test - if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; - - TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) -{ - // Perform AABB-AABB overlap test - if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; - - TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_Collide(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform AABB-AABB overlap test - if(!AABBAABBOverlap(Extents, Center)) return; - - TEST_BOX_IN_AABB(Center, Extents) - - if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform AABB-AABB overlap test - if(!AABBAABBOverlap(Extents, Center)) return; - - TEST_BOX_IN_AABB(Center, Extents) - - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for vanilla AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBCollider::_Collide(const AABBTreeNode* node) -{ - // Perform AABB-AABB overlap test - IcePoint Center, Extents; - node->GetAABB()->GetCenter(Center); - node->GetAABB()->GetExtents(Extents); - if(!AABBAABBOverlap(Center, Extents)) return; - - if(node->IsLeaf() || AABBContainsBox(Center, Extents)) - { - mFlags |= OPC_CONTACT; - mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); - } - else - { - _Collide(node->GetPos()); - _Collide(node->GetNeg()); - } -} - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridAABBCollider::HybridAABBCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridAABBCollider::~HybridAABBCollider() -{ -} - -bool HybridAABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model) -{ - // We don't want primitive tests here! - mFlags |= OPC_NO_PRIMITIVE_TESTS; - - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, box)) return true; - - // Special case for 1-leaf trees - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles - udword Nb = mIMesh->GetNbTriangles(); - - // Loop through all triangles - for(udword i=0;imCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - } - - // We only have a list of boxes so far - if(GetContactStatus()) - { - // Reset contact status, since it currently only reflects collisions with leaf boxes - Collider::InitQuery(); - - // Change dest container so that we can use built-in overlap tests and get collided primitives - cache.TouchedPrimitives.Reset(); - mTouchedPrimitives = &cache.TouchedPrimitives; - - // Read touched leaf boxes - udword Nb = mTouchedBoxes.GetNbEntries(); - const udword* Touched = mTouchedBoxes.GetEntries(); - - const LeafTriangles* LT = model.GetLeafTriangles(); - const udword* Indices = model.GetIndices(); - - // Loop through touched leaves - while(Nb--) - { - const LeafTriangles& CurrentLeaf = LT[*Touched++]; - - // Each leaf box has a set of triangles - udword NbTris = CurrentLeaf.GetNbTriangles(); - if(Indices) - { - const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; - - // Loop through triangles and test each of them - while(NbTris--) - { - udword TriangleIndex = *T++; - AABB_PRIM(TriangleIndex, OPC_CONTACT) - } - } - else - { - udword BaseIndex = CurrentLeaf.GetTriangleIndex(); - - // Loop through triangles and test each of them - while(NbTris--) - { - udword TriangleIndex = BaseIndex++; - AABB_PRIM(TriangleIndex, OPC_CONTACT) - } - } - } - } - - return true; -} diff --git a/contrib/Opcode/OPC_AABBCollider.h b/contrib/Opcode/OPC_AABBCollider.h deleted file mode 100644 index c792b44..0000000 --- a/contrib/Opcode/OPC_AABBCollider.h +++ /dev/null @@ -1,97 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for an AABB collider. - * \file OPC_AABBCollider.h - * \author Pierre Terdiman - * \date January, 1st, 2002 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_AABBCOLLIDER_H__ -#define __OPC_AABBCOLLIDER_H__ - - struct OPCODE_API AABBCache : VolumeCache - { - AABBCache() : FatCoeff(1.1f) - { - FatBox.mCenter.Zero(); - FatBox.mExtents.Zero(); - } - - // Cached faces signature - CollisionAABB FatBox; //!< Box used when performing the query resulting in cached faces - // User settings - float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere - }; - - class OPCODE_API AABBCollider : public VolumeCollider - { - public: - // Constructor / Destructor - AABBCollider(); - virtual ~AABBCollider(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] a box cache - * \param box [in] collision AABB in world space - * \param model [in] Opcode model to collide with - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Collide(AABBCache& cache, const CollisionAABB& box, const Model& model); - // - bool Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree); - protected: - CollisionAABB mBox; //!< Query box in (center, extents) form - IcePoint mMin; //!< Query box min IcePoint - IcePoint mMax; //!< Query box max IcePoint - // Leaf description - IcePoint mLeafVerts[3]; //!< Triangle vertices - // Internal methods - void _Collide(const AABBCollisionNode* node); - void _Collide(const AABBNoLeafNode* node); - void _Collide(const AABBQuantizedNode* node); - void _Collide(const AABBQuantizedNoLeafNode* node); - void _Collide(const AABBTreeNode* node); - void _CollideNoPrimitiveTest(const AABBCollisionNode* node); - void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); - void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); - void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); - // Overlap tests - inline_ BOOL AABBContainsBox(const IcePoint& bc, const IcePoint& be); - inline_ BOOL AABBAABBOverlap(const IcePoint& b, const IcePoint& Pb); - inline_ BOOL TriBoxOverlap(); - // Init methods - BOOL InitQuery(AABBCache& cache, const CollisionAABB& box); - }; - - class OPCODE_API HybridAABBCollider : public AABBCollider - { - public: - // Constructor / Destructor - HybridAABBCollider(); - virtual ~HybridAABBCollider(); - - bool Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model); - protected: - Container mTouchedBoxes; - }; - -#endif // __OPC_AABBCOLLIDER_H__ diff --git a/contrib/Opcode/OPC_AABBTree.cpp b/contrib/Opcode/OPC_AABBTree.cpp deleted file mode 100644 index bc1a4e0..0000000 --- a/contrib/Opcode/OPC_AABBTree.cpp +++ /dev/null @@ -1,573 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for a versatile AABB tree. - * \file OPC_AABBTree.cpp - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a generic AABB tree node. - * - * \class AABBTreeNode - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a generic AABB tree. - * This is a vanilla AABB tree, without any particular optimization. It contains anonymous references to - * user-provided primitives, which can theoretically be anything - triangles, boxes, etc. Each primitive - * is surrounded by an AABB, regardless of the primitive's nature. When the primitive is a triangle, the - * resulting tree can be converted into an optimized tree. If the primitive is a box, the resulting tree - * can be used for culling - VFC or occlusion -, assuming you cull on a mesh-by-mesh basis (modern way). - * - * \class AABBTree - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBTreeNode::AABBTreeNode() : - mPos (null), -#ifndef OPC_NO_NEG_VANILLA_TREE - mNeg (null), -#endif - mNbPrimitives (0), - mNodePrimitives (null) -{ -#ifdef OPC_USE_TREE_COHERENCE - mBitmask = 0; -#endif -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBTreeNode::~AABBTreeNode() -{ - // Opcode 1.3: - const AABBTreeNode* Pos = GetPos(); - const AABBTreeNode* Neg = GetNeg(); -#ifndef OPC_NO_NEG_VANILLA_TREE - if(!(mPos&1)) DELETESINGLE(Pos); - if(!(mNeg&1)) DELETESINGLE(Neg); -#else - if(!(mPos&1)) DELETEARRAY(Pos); -#endif - mNodePrimitives = null; // This was just a shortcut to the global list => no release - mNbPrimitives = 0; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Splits the node along a given axis. - * The list of indices is reorganized according to the split values. - * \param axis [in] splitting axis index - * \param builder [in] the tree builder - * \return the number of primitives assigned to the first child - * \warning this method reorganizes the internal list of primitives - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -udword AABBTreeNode::Split(udword axis, AABBTreeBuilder* builder) -{ - // Get node split value - float SplitValue = builder->GetSplittingValue(mNodePrimitives, mNbPrimitives, mBV, axis); - - udword NbPos = 0; - // Loop through all node-related primitives. Their indices range from mNodePrimitives[0] to mNodePrimitives[mNbPrimitives-1]. - // Those indices map the global list in the tree builder. - for(udword i=0;iGetSplittingValue(Index, axis); - - // Reorganize the list of indices in this order: positive - negative. - if(PrimitiveValue > SplitValue) - { - // Swap entries - udword Tmp = mNodePrimitives[i]; - mNodePrimitives[i] = mNodePrimitives[NbPos]; - mNodePrimitives[NbPos] = Tmp; - // Count primitives assigned to positive space - NbPos++; - } - } - return NbPos; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Subdivides the node. - * - * N - * / \ - * / \ - * N/2 N/2 - * / \ / \ - * N/4 N/4 N/4 N/4 - * (etc) - * - * A well-balanced tree should have a O(log n) depth. - * A degenerate tree would have a O(n) depth. - * Note a perfectly-balanced tree is not well-suited to collision detection anyway. - * - * \param builder [in] the tree builder - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTreeNode::Subdivide(AABBTreeBuilder* builder) -{ - // Checkings - if(!builder) return false; - - // Stop subdividing if we reach a leaf node. This is always performed here, - // else we could end in trouble if user overrides this. - if(mNbPrimitives==1) return true; - - // Let the user validate the subdivision - if(!builder->ValidateSubdivision(mNodePrimitives, mNbPrimitives, mBV)) return true; - - bool ValidSplit = true; // Optimism... - udword NbPos; - if(builder->mSettings.mRules & SPLIT_LARGEST_AXIS) - { - // Find the largest axis to split along - IcePoint Extents; mBV.GetExtents(Extents); // Box extents - udword Axis = Extents.LargestAxis(); // Index of largest axis - - // Split along the axis - NbPos = Split(Axis, builder); - - // Check split validity - if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; - } - else if(builder->mSettings.mRules & SPLIT_SPLATTER_POINTS) - { - // Compute the means - IcePoint Means(0.0f, 0.0f, 0.0f); - for(udword i=0;iGetSplittingValue(Index, 0); - Means.y+=builder->GetSplittingValue(Index, 1); - Means.z+=builder->GetSplittingValue(Index, 2); - } - Means/=float(mNbPrimitives); - - // Compute variances - IcePoint Vars(0.0f, 0.0f, 0.0f); - for(udword i=0;iGetSplittingValue(Index, 0); - float Cy = builder->GetSplittingValue(Index, 1); - float Cz = builder->GetSplittingValue(Index, 2); - Vars.x += (Cx - Means.x)*(Cx - Means.x); - Vars.y += (Cy - Means.y)*(Cy - Means.y); - Vars.z += (Cz - Means.z)*(Cz - Means.z); - } - Vars/=float(mNbPrimitives-1); - - // Choose axis with greatest variance - udword Axis = Vars.LargestAxis(); - - // Split along the axis - NbPos = Split(Axis, builder); - - // Check split validity - if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; - } - else if(builder->mSettings.mRules & SPLIT_BALANCED) - { - // Test 3 axis, take the best - float Results[3]; - NbPos = Split(0, builder); Results[0] = float(NbPos)/float(mNbPrimitives); - NbPos = Split(1, builder); Results[1] = float(NbPos)/float(mNbPrimitives); - NbPos = Split(2, builder); Results[2] = float(NbPos)/float(mNbPrimitives); - Results[0]-=0.5f; Results[0]*=Results[0]; - Results[1]-=0.5f; Results[1]*=Results[1]; - Results[2]-=0.5f; Results[2]*=Results[2]; - udword Min=0; - if(Results[1]mSettings.mRules & SPLIT_BEST_AXIS) - { - // Test largest, then middle, then smallest axis... - - // Sort axis - IcePoint Extents; mBV.GetExtents(Extents); // Box extents - udword SortedAxis[] = { 0, 1, 2 }; - float* Keys = (float*)&Extents.x; - for(udword j=0;j<3;j++) - { - for(udword i=0;i<2;i++) - { - if(Keys[SortedAxis[i]]mSettings.mRules & SPLIT_FIFTY) - { - // Don't even bother splitting (mainly a performance test) - NbPos = mNbPrimitives>>1; - } - else return false; // Unknown splitting rules - - // Check the subdivision has been successful - if(!ValidSplit) - { - // Here, all boxes lie in the same sub-space. Two strategies: - // - if the tree *must* be complete, make an arbitrary 50-50 split - // - else stop subdividing -// if(builder->mSettings.mRules&SPLIT_COMPLETE) - if(builder->mSettings.mLimit==1) - { - builder->IncreaseNbInvalidSplits(); - NbPos = mNbPrimitives>>1; - } - else return true; - } - - // Now create children and assign their pointers. - if(builder->mNodeBase) - { - // We use a pre-allocated linear pool for complete trees [Opcode 1.3] - AABBTreeNode* Pool = (AABBTreeNode*)builder->mNodeBase; - udword Count = builder->GetCount() - 1; // Count begins to 1... - // Set last bit to tell it shouldn't be freed ### pretty ugly, find a better way. Maybe one bit in mNbPrimitives - ASSERT(!(udword(&Pool[Count+0])&1)); - ASSERT(!(udword(&Pool[Count+1])&1)); - mPos = udword(&Pool[Count+0])|1; -#ifndef OPC_NO_NEG_VANILLA_TREE - mNeg = udword(&Pool[Count+1])|1; -#endif - } - else - { - // Non-complete trees and/or Opcode 1.2 allocate nodes on-the-fly -#ifndef OPC_NO_NEG_VANILLA_TREE - mPos = (udword)new AABBTreeNode; CHECKALLOC(mPos); - mNeg = (udword)new AABBTreeNode; CHECKALLOC(mNeg); -#else - AABBTreeNode* PosNeg = new AABBTreeNode[2]; - CHECKALLOC(PosNeg); - mPos = (udword)PosNeg; -#endif - } - - // Update stats - builder->IncreaseCount(2); - - // Assign children - AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); - AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); - Pos->mNodePrimitives = &mNodePrimitives[0]; - Pos->mNbPrimitives = NbPos; - Neg->mNodePrimitives = &mNodePrimitives[NbPos]; - Neg->mNbPrimitives = mNbPrimitives - NbPos; - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive hierarchy building in a top-down fashion. - * \param builder [in] the tree builder - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeNode::_BuildHierarchy(AABBTreeBuilder* builder) -{ - // 1) Compute the global box for current node. The box is stored in mBV. - builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); - - // 2) Subdivide current node - Subdivide(builder); - - // 3) Recurse - AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); - AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); - if(Pos) Pos->_BuildHierarchy(builder); - if(Neg) Neg->_BuildHierarchy(builder); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Refits the tree (top-down). - * \param builder [in] the tree builder - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeNode::_Refit(AABBTreeBuilder* builder) -{ - // 1) Recompute the new global box for current node - builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); - - // 2) Recurse - AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); - AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); - if(Pos) Pos->_Refit(builder); - if(Neg) Neg->_Refit(builder); -} - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBTree::AABBTree() : mIndices(null), mTotalNbNodes(0), mPool(null) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBTree::~AABBTree() -{ - Release(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Releases the tree. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTree::Release() -{ - DELETEARRAY(mPool); - DELETEARRAY(mIndices); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds a generic AABB tree from a tree builder. - * \param builder [in] the tree builder - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTree::Build(AABBTreeBuilder* builder) -{ - // Checkings - if(!builder || !builder->mNbPrimitives) return false; - - // Release previous tree - Release(); - - // Init stats - builder->SetCount(1); - builder->SetNbInvalidSplits(0); - - // Initialize indices. This list will be modified during build. - mIndices = new udword[builder->mNbPrimitives]; - CHECKALLOC(mIndices); - // Identity permutation - for(udword i=0;imNbPrimitives;i++) mIndices[i] = i; - - // Setup initial node. Here we have a complete permutation of the app's primitives. - mNodePrimitives = mIndices; - mNbPrimitives = builder->mNbPrimitives; - - // Use a linear array for complete trees (since we can predict the final number of nodes) [Opcode 1.3] -// if(builder->mRules&SPLIT_COMPLETE) - if(builder->mSettings.mLimit==1) - { - // Allocate a pool of nodes - mPool = new AABBTreeNode[builder->mNbPrimitives*2 - 1]; - - builder->mNodeBase = mPool; // ### ugly ! - } - - // Build the hierarchy - _BuildHierarchy(builder); - - // Get back total number of nodes - mTotalNbNodes = builder->GetCount(); - - // For complete trees, check the correct number of nodes has been created [Opcode 1.3] - if(mPool) ASSERT(mTotalNbNodes==builder->mNbPrimitives*2 - 1); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the depth of the tree. - * A well-balanced tree should have a log(n) depth. A degenerate tree O(n) depth. - * \return depth of the tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -udword AABBTree::ComputeDepth() const -{ - return Walk(null, null); // Use the walking code without callback -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Walks the tree, calling the user back for each node. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -udword AABBTree::Walk(WalkingCallback callback, void* user_data) const -{ - // Call it without callback to compute max depth - udword MaxDepth = 0; - udword CurrentDepth = 0; - - struct Local - { - static void _Walk(const AABBTreeNode* current_node, udword& max_depth, udword& current_depth, WalkingCallback callback, void* user_data) - { - // Checkings - if(!current_node) return; - // Entering a new node => increase depth - current_depth++; - // Keep track of max depth - if(current_depth>max_depth) max_depth = current_depth; - - // Callback - if(callback && !(callback)(current_node, current_depth, user_data)) return; - - // Recurse - if(current_node->GetPos()) { _Walk(current_node->GetPos(), max_depth, current_depth, callback, user_data); current_depth--; } - if(current_node->GetNeg()) { _Walk(current_node->GetNeg(), max_depth, current_depth, callback, user_data); current_depth--; } - } - }; - Local::_Walk(this, MaxDepth, CurrentDepth, callback, user_data); - return MaxDepth; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Refits the tree in a top-down way. - * \param builder [in] the tree builder - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTree::Refit(AABBTreeBuilder* builder) -{ - if(!builder) return false; - _Refit(builder); - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Refits the tree in a bottom-up way. - * \param builder [in] the tree builder - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTree::Refit2(AABBTreeBuilder* builder) -{ - // Checkings - if(!builder) return false; - - ASSERT(mPool); - - // Bottom-up update - IcePoint Min,Max; - IcePoint Min_,Max_; - udword Index = mTotalNbNodes; - while(Index--) - { - AABBTreeNode& Current = mPool[Index]; - - if(Current.IsLeaf()) - { - builder->ComputeGlobalBox(Current.GetPrimitives(), Current.GetNbPrimitives(), *(AABB*)Current.GetAABB()); - } - else - { - Current.GetPos()->GetAABB()->GetMin(Min); - Current.GetPos()->GetAABB()->GetMax(Max); - - Current.GetNeg()->GetAABB()->GetMin(Min_); - Current.GetNeg()->GetAABB()->GetMax(Max_); - - Min.Min(Min_); - Max.Max(Max_); - - ((AABB*)Current.GetAABB())->SetMinMax(Min, Max); - } - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the number of bytes used by the tree. - * \return number of bytes used - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -udword AABBTree::GetUsedBytes() const -{ - udword TotalSize = mTotalNbNodes*GetNodeSize(); - if(mIndices) TotalSize+=mNbPrimitives*sizeof(udword); - return TotalSize; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks the tree is a complete tree or not. - * A complete tree is made of 2*N-1 nodes, where N is the number of primitives in the tree. - * \return true for complete trees - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTree::IsComplete() const -{ - return (GetNbNodes()==GetNbPrimitives()*2-1); -} diff --git a/contrib/Opcode/OPC_AABBTree.h b/contrib/Opcode/OPC_AABBTree.h deleted file mode 100644 index 298f482..0000000 --- a/contrib/Opcode/OPC_AABBTree.h +++ /dev/null @@ -1,137 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for a versatile AABB tree. - * \file OPC_AABBTree.h - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_AABBTREE_H__ -#define __OPC_AABBTREE_H__ - -#ifdef OPC_NO_NEG_VANILLA_TREE - //! TO BE DOCUMENTED - #define IMPLEMENT_TREE(base_class, volume) \ - public: \ - /* Constructor / Destructor */ \ - base_class(); \ - ~base_class(); \ - /* Data access */ \ - inline_ const volume* Get##volume() const { return &mBV; } \ - /* Clear the last bit */ \ - inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \ - inline_ const base_class* GetNeg() const { const base_class* P = GetPos(); return P ? P+1 : null;} \ - \ - /* We don't need to test both nodes since we can't have one without the other */ \ - inline_ bool IsLeaf() const { return !GetPos(); } \ - \ - /* Stats */ \ - inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ - protected: \ - /* Tree-independent data */ \ - /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \ - /* Whatever happens we need the two children and the enclosing volume.*/ \ - volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \ - udword mPos; /* "Positive" & "Negative" children */ -#else - //! TO BE DOCUMENTED - #define IMPLEMENT_TREE(base_class, volume) \ - public: \ - /* Constructor / Destructor */ \ - base_class(); \ - ~base_class(); \ - /* Data access */ \ - inline_ const volume* Get##volume() const { return &mBV; } \ - /* Clear the last bit */ \ - inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \ - inline_ const base_class* GetNeg() const { return (const base_class*)(mNeg&~1); } \ - \ -/* inline_ bool IsLeaf() const { return (!GetPos() && !GetNeg()); } */ \ - /* We don't need to test both nodes since we can't have one without the other */ \ - inline_ bool IsLeaf() const { return !GetPos(); } \ - \ - /* Stats */ \ - inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ - protected: \ - /* Tree-independent data */ \ - /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \ - /* Whatever happens we need the two children and the enclosing volume.*/ \ - volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \ - udword mPos; /* "Positive" child */ \ - udword mNeg; /* "Negative" child */ -#endif - - typedef void (*CullingCallback) (udword nb_primitives, udword* node_primitives, BOOL need_clipping, void* user_data); - - class OPCODE_API AABBTreeNode - { - IMPLEMENT_TREE(AABBTreeNode, AABB) - public: - // Data access - inline_ const udword* GetPrimitives() const { return mNodePrimitives; } - inline_ udword GetNbPrimitives() const { return mNbPrimitives; } - - protected: - // Tree-dependent data - udword* mNodePrimitives; //!< Node-related primitives (shortcut to a position in mIndices below) - udword mNbPrimitives; //!< Number of primitives for this node - // Internal methods - udword Split(udword axis, AABBTreeBuilder* builder); - bool Subdivide(AABBTreeBuilder* builder); - void _BuildHierarchy(AABBTreeBuilder* builder); - void _Refit(AABBTreeBuilder* builder); - }; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * User-callback, called for each node by the walking code. - * \param current [in] current node - * \param depth [in] current node's depth - * \param user_data [in] user-defined data - * \return true to recurse through children, else false to bypass them - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - typedef bool (*WalkingCallback) (const AABBTreeNode* current, udword depth, void* user_data); - - class OPCODE_API AABBTree : public AABBTreeNode - { - public: - // Constructor / Destructor - AABBTree(); - ~AABBTree(); - // Build - bool Build(AABBTreeBuilder* builder); - void Release(); - - // Data access - inline_ const udword* GetIndices() const { return mIndices; } //!< Catch the indices - inline_ udword GetNbNodes() const { return mTotalNbNodes; } //!< Catch the number of nodes - - // Infos - bool IsComplete() const; - // Stats - udword ComputeDepth() const; - udword GetUsedBytes() const; - udword Walk(WalkingCallback callback, void* user_data) const; - - bool Refit(AABBTreeBuilder* builder); - bool Refit2(AABBTreeBuilder* builder); - private: - udword* mIndices; //!< Indices in the app list. Indices are reorganized during build (permutation). - AABBTreeNode* mPool; //!< Linear pool of nodes for complete trees. Null otherwise. [Opcode 1.3] - // Stats - udword mTotalNbNodes; //!< Number of nodes in the tree. - }; - -#endif // __OPC_AABBTREE_H__ diff --git a/contrib/Opcode/OPC_BaseModel.cpp b/contrib/Opcode/OPC_BaseModel.cpp deleted file mode 100644 index 88b6a69..0000000 --- a/contrib/Opcode/OPC_BaseModel.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains base model interface. - * \file OPC_BaseModel.cpp - * \author Pierre Terdiman - * \date May, 18, 2003 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * The base class for collision models. - * - * \class BaseModel - * \author Pierre Terdiman - * \version 1.3 - * \date May, 18, 2003 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -OPCODECREATE::OPCODECREATE() -{ - mIMesh = null; - mSettings.mRules = SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER; - mSettings.mLimit = 1; // Mandatory for complete trees - mNoLeaf = true; - mQuantized = true; -#ifdef __MESHMERIZER_H__ - mCollisionHull = false; -#endif // __MESHMERIZER_H__ - mKeepOriginal = false; - mCanRemap = false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BaseModel::BaseModel() : mIMesh(null), mModelCode(0), mSource(null), mTree(null) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BaseModel::~BaseModel() -{ - ReleaseBase(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Releases everything. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void BaseModel::ReleaseBase() -{ - DELETESINGLE(mSource); - DELETESINGLE(mTree); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Creates an optimized tree according to user-settings, and setups mModelCode. - * \param no_leaf [in] true for "no leaf" tree - * \param quantized [in] true for quantized tree - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool BaseModel::CreateTree(bool no_leaf, bool quantized) -{ - DELETESINGLE(mTree); - - // Setup model code - if(no_leaf) mModelCode |= OPC_NO_LEAF; - else mModelCode &= ~OPC_NO_LEAF; - - if(quantized) mModelCode |= OPC_QUANTIZED; - else mModelCode &= ~OPC_QUANTIZED; - - // Create the correct class - if(mModelCode & OPC_NO_LEAF) - { - if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedNoLeafTree; - else mTree = new AABBNoLeafTree; - } - else - { - if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedTree; - else mTree = new AABBCollisionTree; - } - CHECKALLOC(mTree); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Refits the collision model. This can be used to handle dynamic meshes. Usage is: - * 1. modify your mesh vertices (keep the topology constant!) - * 2. refit the tree (call this method) - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool BaseModel::Refit() -{ - // Refit the optimized tree - return mTree->Refit(mIMesh); - -// Old code kept for reference : refit the source tree then rebuild ! -// if(!mSource) return false; -// // Ouch... -// mSource->Refit(&mTB); -// // Ouch... -// return mTree->Build(mSource); -} diff --git a/contrib/Opcode/OPC_BaseModel.h b/contrib/Opcode/OPC_BaseModel.h deleted file mode 100644 index 3c2e58c..0000000 --- a/contrib/Opcode/OPC_BaseModel.h +++ /dev/null @@ -1,175 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains base model interface. - * \file OPC_BaseModel.h - * \author Pierre Terdiman - * \date May, 18, 2003 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_BASEMODEL_H__ -#define __OPC_BASEMODEL_H__ - - //! Model creation structure - struct OPCODE_API OPCODECREATE - { - //! Constructor - OPCODECREATE(); - - MeshInterface* mIMesh; //!< Mesh interface (access to triangles & vertices) (*) - BuildSettings mSettings; //!< Builder's settings - bool mNoLeaf; //!< true => discard leaf nodes (else use a normal tree) - bool mQuantized; //!< true => quantize the tree (else use a normal tree) -#ifdef __MESHMERIZER_H__ - bool mCollisionHull; //!< true => use convex hull + GJK -#endif // __MESHMERIZER_H__ - bool mKeepOriginal; //!< true => keep a copy of the original tree (debug purpose) - bool mCanRemap; //!< true => allows OPCODE to reorganize client arrays - - // (*) This pointer is saved internally and used by OPCODE until collision structures are released, - // so beware of the object's lifetime. - }; - - enum ModelFlag - { - OPC_QUANTIZED = (1<<0), //!< Compressed/uncompressed tree - OPC_NO_LEAF = (1<<1), //!< Leaf/NoLeaf tree - OPC_SINGLE_NODE = (1<<2) //!< Special case for 1-node models - }; - - class OPCODE_API BaseModel - { - public: - // Constructor/Destructor - BaseModel(); - virtual ~BaseModel(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Builds a collision model. - * \param create [in] model creation structure - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual bool Build(const OPCODECREATE& create) = 0; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the number of bytes used by the tree. - * \return amount of bytes used - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual udword GetUsedBytes() const = 0; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Refits the collision model. This can be used to handle dynamic meshes. Usage is: - * 1. modify your mesh vertices (keep the topology constant!) - * 2. refit the tree (call this method) - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual bool Refit(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the source tree. - * \return generic tree - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ const AABBTree* GetSourceTree() const { return mSource; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the tree. - * \return the collision tree - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ const AABBOptimizedTree* GetTree() const { return mTree; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the tree. - * \return the collision tree - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ AABBOptimizedTree* GetTree() { return mTree; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the number of nodes in the tree. - * Should be 2*N-1 for normal trees and N-1 for optimized ones. - * \return number of nodes - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbNodes() const { return mTree->GetNbNodes(); } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks whether the tree has leaf nodes or not. - * \return true if the tree has leaf nodes (normal tree), else false (optimized tree) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL HasLeafNodes() const { return !(mModelCode & OPC_NO_LEAF); } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks whether the tree is quantized or not. - * \return true if the tree is quantized - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL IsQuantized() const { return mModelCode & OPC_QUANTIZED; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks whether the model has a single node or not. This special case must be handled separately. - * \return true if the model has only 1 node - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL HasSingleNode() const { return mModelCode & OPC_SINGLE_NODE; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the model's code. - * \return model's code - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetModelCode() const { return mModelCode; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the mesh interface. - * \return mesh interface - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ const MeshInterface* GetMeshInterface() const { return mIMesh; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Sets the mesh interface. - * \param imesh [in] mesh interface - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetMeshInterface(const MeshInterface* imesh) { mIMesh = imesh; } - - protected: - const MeshInterface* mIMesh; //!< User-defined mesh interface - udword mModelCode; //!< Model code = combination of ModelFlag(s) - AABBTree* mSource; //!< Original source tree - AABBOptimizedTree* mTree; //!< Optimized tree owned by the model - // Internal methods - void ReleaseBase(); - bool CreateTree(bool no_leaf, bool quantized); - }; - -#endif //__OPC_BASEMODEL_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_BoxBoxOverlap.h b/contrib/Opcode/OPC_BoxBoxOverlap.h deleted file mode 100644 index 78a7675..0000000 --- a/contrib/Opcode/OPC_BoxBoxOverlap.h +++ /dev/null @@ -1,122 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * OBB-OBB overlap test using the separating axis theorem. - * - original code by Gomez / Gamasutra (similar to Gottschalk's one in RAPID) - * - optimized for AABB trees by computing the rotation matrix once (SOLID-fashion) - * - the fabs matrix is precomputed as well and epsilon-tweaked (RAPID-style, we found this almost mandatory) - * - Class III axes can be disabled... (SOLID & Intel fashion) - * - ...or enabled to perform some profiling - * - CPU comparisons used when appropriate - * - lazy evaluation sometimes saves some work in case of early exits (unlike SOLID) - * - * \param ea [in] extents from box A - * \param ca [in] center from box A - * \param eb [in] extents from box B - * \param cb [in] center from box B - * \return true if boxes overlap - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL AABBTreeCollider::BoxBoxOverlap(const IcePoint& ea, const IcePoint& ca, const IcePoint& eb, const IcePoint& cb) -{ - // Stats - mNbBVBVTests++; - - float t,t2; - - // Class I : A's basis vectors - float Tx = (mR1to0.m[0][0]*cb.x + mR1to0.m[1][0]*cb.y + mR1to0.m[2][0]*cb.z) + mT1to0.x - ca.x; - t = ea.x + eb.x*mAR.m[0][0] + eb.y*mAR.m[1][0] + eb.z*mAR.m[2][0]; - if(GREATER(Tx, t)) return FALSE; - - float Ty = (mR1to0.m[0][1]*cb.x + mR1to0.m[1][1]*cb.y + mR1to0.m[2][1]*cb.z) + mT1to0.y - ca.y; - t = ea.y + eb.x*mAR.m[0][1] + eb.y*mAR.m[1][1] + eb.z*mAR.m[2][1]; - if(GREATER(Ty, t)) return FALSE; - - float Tz = (mR1to0.m[0][2]*cb.x + mR1to0.m[1][2]*cb.y + mR1to0.m[2][2]*cb.z) + mT1to0.z - ca.z; - t = ea.z + eb.x*mAR.m[0][2] + eb.y*mAR.m[1][2] + eb.z*mAR.m[2][2]; - if(GREATER(Tz, t)) return FALSE; - - // Class II : B's basis vectors - t = Tx*mR1to0.m[0][0] + Ty*mR1to0.m[0][1] + Tz*mR1to0.m[0][2]; t2 = ea.x*mAR.m[0][0] + ea.y*mAR.m[0][1] + ea.z*mAR.m[0][2] + eb.x; - if(GREATER(t, t2)) return FALSE; - - t = Tx*mR1to0.m[1][0] + Ty*mR1to0.m[1][1] + Tz*mR1to0.m[1][2]; t2 = ea.x*mAR.m[1][0] + ea.y*mAR.m[1][1] + ea.z*mAR.m[1][2] + eb.y; - if(GREATER(t, t2)) return FALSE; - - t = Tx*mR1to0.m[2][0] + Ty*mR1to0.m[2][1] + Tz*mR1to0.m[2][2]; t2 = ea.x*mAR.m[2][0] + ea.y*mAR.m[2][1] + ea.z*mAR.m[2][2] + eb.z; - if(GREATER(t, t2)) return FALSE; - - // Class III : 9 cross products - // Cool trick: always perform the full test for first level, regardless of settings. - // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! - if(mFullBoxBoxTest || mNbBVBVTests==1) - { - t = Tz*mR1to0.m[0][1] - Ty*mR1to0.m[0][2]; t2 = ea.y*mAR.m[0][2] + ea.z*mAR.m[0][1] + eb.y*mAR.m[2][0] + eb.z*mAR.m[1][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 - t = Tz*mR1to0.m[1][1] - Ty*mR1to0.m[1][2]; t2 = ea.y*mAR.m[1][2] + ea.z*mAR.m[1][1] + eb.x*mAR.m[2][0] + eb.z*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 - t = Tz*mR1to0.m[2][1] - Ty*mR1to0.m[2][2]; t2 = ea.y*mAR.m[2][2] + ea.z*mAR.m[2][1] + eb.x*mAR.m[1][0] + eb.y*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 - t = Tx*mR1to0.m[0][2] - Tz*mR1to0.m[0][0]; t2 = ea.x*mAR.m[0][2] + ea.z*mAR.m[0][0] + eb.y*mAR.m[2][1] + eb.z*mAR.m[1][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 - t = Tx*mR1to0.m[1][2] - Tz*mR1to0.m[1][0]; t2 = ea.x*mAR.m[1][2] + ea.z*mAR.m[1][0] + eb.x*mAR.m[2][1] + eb.z*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 - t = Tx*mR1to0.m[2][2] - Tz*mR1to0.m[2][0]; t2 = ea.x*mAR.m[2][2] + ea.z*mAR.m[2][0] + eb.x*mAR.m[1][1] + eb.y*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 - t = Ty*mR1to0.m[0][0] - Tx*mR1to0.m[0][1]; t2 = ea.x*mAR.m[0][1] + ea.y*mAR.m[0][0] + eb.y*mAR.m[2][2] + eb.z*mAR.m[1][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 - t = Ty*mR1to0.m[1][0] - Tx*mR1to0.m[1][1]; t2 = ea.x*mAR.m[1][1] + ea.y*mAR.m[1][0] + eb.x*mAR.m[2][2] + eb.z*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 - t = Ty*mR1to0.m[2][0] - Tx*mR1to0.m[2][1]; t2 = ea.x*mAR.m[2][1] + ea.y*mAR.m[2][0] + eb.x*mAR.m[1][2] + eb.y*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 - } - return TRUE; -} - -//! A dedicated version when one box is constant -inline_ BOOL OBBCollider::BoxBoxOverlap(const IcePoint& extents, const IcePoint& center) -{ - // Stats - mNbVolumeBVTests++; - - float t,t2; - - // Class I : A's basis vectors - float Tx = mTBoxToModel.x - center.x; t = extents.x + mBBx1; if(GREATER(Tx, t)) return FALSE; - float Ty = mTBoxToModel.y - center.y; t = extents.y + mBBy1; if(GREATER(Ty, t)) return FALSE; - float Tz = mTBoxToModel.z - center.z; t = extents.z + mBBz1; if(GREATER(Tz, t)) return FALSE; - - // Class II : B's basis vectors - t = Tx*mRBoxToModel.m[0][0] + Ty*mRBoxToModel.m[0][1] + Tz*mRBoxToModel.m[0][2]; - t2 = extents.x*mAR.m[0][0] + extents.y*mAR.m[0][1] + extents.z*mAR.m[0][2] + mBoxExtents.x; - if(GREATER(t, t2)) return FALSE; - - t = Tx*mRBoxToModel.m[1][0] + Ty*mRBoxToModel.m[1][1] + Tz*mRBoxToModel.m[1][2]; - t2 = extents.x*mAR.m[1][0] + extents.y*mAR.m[1][1] + extents.z*mAR.m[1][2] + mBoxExtents.y; - if(GREATER(t, t2)) return FALSE; - - t = Tx*mRBoxToModel.m[2][0] + Ty*mRBoxToModel.m[2][1] + Tz*mRBoxToModel.m[2][2]; - t2 = extents.x*mAR.m[2][0] + extents.y*mAR.m[2][1] + extents.z*mAR.m[2][2] + mBoxExtents.z; - if(GREATER(t, t2)) return FALSE; - - // Class III : 9 cross products - // Cool trick: always perform the full test for first level, regardless of settings. - // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! - if(mFullBoxBoxTest || mNbVolumeBVTests==1) - { - t = Tz*mRBoxToModel.m[0][1] - Ty*mRBoxToModel.m[0][2]; t2 = extents.y*mAR.m[0][2] + extents.z*mAR.m[0][1] + mBB_1; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 - t = Tz*mRBoxToModel.m[1][1] - Ty*mRBoxToModel.m[1][2]; t2 = extents.y*mAR.m[1][2] + extents.z*mAR.m[1][1] + mBB_2; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 - t = Tz*mRBoxToModel.m[2][1] - Ty*mRBoxToModel.m[2][2]; t2 = extents.y*mAR.m[2][2] + extents.z*mAR.m[2][1] + mBB_3; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 - t = Tx*mRBoxToModel.m[0][2] - Tz*mRBoxToModel.m[0][0]; t2 = extents.x*mAR.m[0][2] + extents.z*mAR.m[0][0] + mBB_4; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 - t = Tx*mRBoxToModel.m[1][2] - Tz*mRBoxToModel.m[1][0]; t2 = extents.x*mAR.m[1][2] + extents.z*mAR.m[1][0] + mBB_5; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 - t = Tx*mRBoxToModel.m[2][2] - Tz*mRBoxToModel.m[2][0]; t2 = extents.x*mAR.m[2][2] + extents.z*mAR.m[2][0] + mBB_6; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 - t = Ty*mRBoxToModel.m[0][0] - Tx*mRBoxToModel.m[0][1]; t2 = extents.x*mAR.m[0][1] + extents.y*mAR.m[0][0] + mBB_7; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 - t = Ty*mRBoxToModel.m[1][0] - Tx*mRBoxToModel.m[1][1]; t2 = extents.x*mAR.m[1][1] + extents.y*mAR.m[1][0] + mBB_8; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 - t = Ty*mRBoxToModel.m[2][0] - Tx*mRBoxToModel.m[2][1]; t2 = extents.x*mAR.m[2][1] + extents.y*mAR.m[2][0] + mBB_9; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 - } - return TRUE; -} - -//! A special version for 2 axis-aligned boxes -inline_ BOOL AABBCollider::AABBAABBOverlap(const IcePoint& extents, const IcePoint& center) -{ - // Stats - mNbVolumeBVTests++; - - float tx = mBox.mCenter.x - center.x; float ex = extents.x + mBox.mExtents.x; if(GREATER(tx, ex)) return FALSE; - float ty = mBox.mCenter.y - center.y; float ey = extents.y + mBox.mExtents.y; if(GREATER(ty, ey)) return FALSE; - float tz = mBox.mCenter.z - center.z; float ez = extents.z + mBox.mExtents.z; if(GREATER(tz, ez)) return FALSE; - - return TRUE; -} diff --git a/contrib/Opcode/OPC_BoxPruning.cpp b/contrib/Opcode/OPC_BoxPruning.cpp deleted file mode 100644 index 3735a39..0000000 --- a/contrib/Opcode/OPC_BoxPruning.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for box pruning. - * \file IceBoxPruning.cpp - * \author Pierre Terdiman - * \date January, 29, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/* -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - You could use a complex sweep-and-prune as implemented in I-Collide. - You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems. - You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2. - - Or you could use this. - Faster ? I don't know. Probably not. It would be a shame. But who knows ? - Easier ? Definitely. Enjoy the sheer simplicity. -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -*/ - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - - inline_ void FindRunningIndex(udword& index, float* array, udword* sorted, int last, float max) - { - int First=index; - while(First<=last) - { - index = (First+last)>>1; - - if(max>array[sorted[index]]) First = index+1; - else last = index-1; - } - } -// ### could be log(n) ! -// and maybe use cmp integers - -// InsertionSort has better coherence, RadixSort is better for one-shot queries. -#define PRUNING_SORTER RadixSort -//#define PRUNING_SORTER InsertionSort - -// Static for coherence -static PRUNING_SORTER* gCompletePruningSorter = null; -static PRUNING_SORTER* gBipartitePruningSorter0 = null; -static PRUNING_SORTER* gBipartitePruningSorter1 = null; -inline_ PRUNING_SORTER* GetCompletePruningSorter() -{ - if(!gCompletePruningSorter) gCompletePruningSorter = new PRUNING_SORTER; - return gCompletePruningSorter; -} -inline_ PRUNING_SORTER* GetBipartitePruningSorter0() -{ - if(!gBipartitePruningSorter0) gBipartitePruningSorter0 = new PRUNING_SORTER; - return gBipartitePruningSorter0; -} -inline_ PRUNING_SORTER* GetBipartitePruningSorter1() -{ - if(!gBipartitePruningSorter1) gBipartitePruningSorter1 = new PRUNING_SORTER; - return gBipartitePruningSorter1; -} -void ReleasePruningSorters() -{ - DELETESINGLE(gBipartitePruningSorter1); - DELETESINGLE(gBipartitePruningSorter0); - DELETESINGLE(gCompletePruningSorter); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. - * \param nb0 [in] number of boxes in the first set - * \param array0 [in] array of boxes for the first set - * \param nb1 [in] number of boxes in the second set - * \param array1 [in] array of boxes for the second set - * \param pairs [out] array of overlapping pairs - * \param axes [in] projection order (0,2,1 is often best) - * \return true if success. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool Opcode::BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes) -{ - // Checkings - if(!nb0 || !array0 || !nb1 || !array1) return false; - - // Catch axes - udword Axis0 = axes.mAxis0; - udword Axis1 = axes.mAxis1; - udword Axis2 = axes.mAxis2; - - // Allocate some temporary data - float* MinPosList0 = new float[nb0]; - float* MinPosList1 = new float[nb1]; - - // 1) Build main lists using the primary axis - for(udword i=0;iGetMin(Axis0); - for(udword i=0;iGetMin(Axis0); - - // 2) Sort the lists - PRUNING_SORTER* RS0 = GetBipartitePruningSorter0(); - PRUNING_SORTER* RS1 = GetBipartitePruningSorter1(); - const udword* Sorted0 = RS0->Sort(MinPosList0, nb0).GetRanks(); - const udword* Sorted1 = RS1->Sort(MinPosList1, nb1).GetRanks(); - - // 3) Prune the lists - udword Index0, Index1; - - const udword* const LastSorted0 = &Sorted0[nb0]; - const udword* const LastSorted1 = &Sorted1[nb1]; - const udword* RunningAddress0 = Sorted0; - const udword* RunningAddress1 = Sorted1; - - while(RunningAddress1GetMax(Axis0)) - { - if(array0[Index0]->Intersect(*array1[Index1], Axis1)) - { - if(array0[Index0]->Intersect(*array1[Index1], Axis2)) - { - pairs.AddPair(Index0, Index1); - } - } - } - } - - //// - - while(RunningAddress0GetMax(Axis0)) - { - if(array0[Index1]->Intersect(*array1[Index0], Axis1)) - { - if(array0[Index1]->Intersect(*array1[Index0], Axis2)) - { - pairs.AddPair(Index1, Index0); - } - } - - } - } - - DELETEARRAY(MinPosList1); - DELETEARRAY(MinPosList0); - - return true; -} - -#define ORIGINAL_VERSION -//#define JOAKIM - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. - * \param nb [in] number of boxes - * \param array [in] array of boxes - * \param pairs [out] array of overlapping pairs - * \param axes [in] projection order (0,2,1 is often best) - * \return true if success. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool Opcode::CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes) -{ - // Checkings - if(!nb || !array) return false; - - // Catch axes - udword Axis0 = axes.mAxis0; - udword Axis1 = axes.mAxis1; - udword Axis2 = axes.mAxis2; - -#ifdef ORIGINAL_VERSION - // Allocate some temporary data -// float* PosList = new float[nb]; - float* PosList = new float[nb+1]; - - // 1) Build main list using the primary axis - for(udword i=0;iGetMin(Axis0); -PosList[nb++] = MAX_FLOAT; - - // 2) Sort the list - PRUNING_SORTER* RS = GetCompletePruningSorter(); - const udword* Sorted = RS->Sort(PosList, nb).GetRanks(); - - // 3) Prune the list - const udword* const LastSorted = &Sorted[nb]; - const udword* RunningAddress = Sorted; - udword Index0, Index1; - while(RunningAddressGetMax(Axis0)) - while(PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0)) - { -// if(Index0!=Index1) -// { - if(array[Index0]->Intersect(*array[Index1], Axis1)) - { - if(array[Index0]->Intersect(*array[Index1], Axis2)) - { - pairs.AddPair(Index0, Index1); - } - } -// } - } - } - } - - DELETEARRAY(PosList); -#endif - -#ifdef JOAKIM - // Allocate some temporary data -// float* PosList = new float[nb]; - float* MinList = new float[nb+1]; - - // 1) Build main list using the primary axis - for(udword i=0;iGetMin(Axis0); - MinList[nb] = MAX_FLOAT; - - // 2) Sort the list - PRUNING_SORTER* RS = GetCompletePruningSorter(); - udword* Sorted = RS->Sort(MinList, nb+1).GetRanks(); - - // 3) Prune the list -// const udword* const LastSorted = &Sorted[nb]; -// const udword* const LastSorted = &Sorted[nb-1]; - const udword* RunningAddress = Sorted; - udword Index0, Index1; - -// while(RunningAddressGetMax(Axis0)) - -// float CurrentMin = array[Index0]->GetMin(Axis0); - float CurrentMax = array[Index0]->GetMax(Axis0); - - while(MinList[Index1 = *RunningAddress2] <= CurrentMax) -// while(PosList[Index1 = *RunningAddress] <= CurrentMax) - { -// if(Index0!=Index1) -// { - if(array[Index0]->Intersect(*array[Index1], Axis1)) - { - if(array[Index0]->Intersect(*array[Index1], Axis2)) - { - pairs.AddPair(Index0, Index1); - } - } -// } - - RunningAddress2++; -// RunningAddress++; - } - } - } - - DELETEARRAY(MinList); -#endif - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Brute-force versions are kept: -// - to check the optimized versions return the correct list of intersections -// - to check the speed of the optimized code against the brute-force one -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Brute-force bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. - * \param nb0 [in] number of boxes in the first set - * \param array0 [in] array of boxes for the first set - * \param nb1 [in] number of boxes in the second set - * \param array1 [in] array of boxes for the second set - * \param pairs [out] array of overlapping pairs - * \return true if success. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool Opcode::BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs) -{ - // Checkings - if(!nb0 || !array0 || !nb1 || !array1) return false; - - // Brute-force nb0*nb1 overlap tests - for(udword i=0;iIntersect(*array1[j])) pairs.AddPair(i, j); - } - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. - * \param nb [in] number of boxes - * \param array [in] array of boxes - * \param pairs [out] array of overlapping pairs - * \return true if success. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool Opcode::BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs) -{ - // Checkings - if(!nb || !array) return false; - - // Brute-force n(n-1)/2 overlap tests - for(udword i=0;iIntersect(*array[j])) pairs.AddPair(i, j); - } - } - return true; -} diff --git a/contrib/Opcode/OPC_BoxPruning.h b/contrib/Opcode/OPC_BoxPruning.h deleted file mode 100644 index b431946..0000000 --- a/contrib/Opcode/OPC_BoxPruning.h +++ /dev/null @@ -1,31 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for box pruning. - * \file IceBoxPruning.h - * \author Pierre Terdiman - * \date January, 29, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_BOXPRUNING_H__ -#define __OPC_BOXPRUNING_H__ - - // Optimized versions - FUNCTION OPCODE_API bool CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes); - FUNCTION OPCODE_API bool BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes); - - // Brute-force versions - FUNCTION OPCODE_API bool BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs); - FUNCTION OPCODE_API bool BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs); - -#endif //__OPC_BOXPRUNING_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_Collider.cpp b/contrib/Opcode/OPC_Collider.cpp deleted file mode 100644 index c352618..0000000 --- a/contrib/Opcode/OPC_Collider.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains base collider class. - * \file OPC_Collider.cpp - * \author Pierre Terdiman - * \date June, 2, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains the abstract class for colliders. - * - * \class Collider - * \author Pierre Terdiman - * \version 1.3 - * \date June, 2, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Collider::Collider() : - mFlags (0), - mCurrentModel (null), - mIMesh (null) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Collider::~Collider() -{ -} diff --git a/contrib/Opcode/OPC_Collider.h b/contrib/Opcode/OPC_Collider.h deleted file mode 100644 index d718e02..0000000 --- a/contrib/Opcode/OPC_Collider.h +++ /dev/null @@ -1,176 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains base collider class. - * \file OPC_Collider.h - * \author Pierre Terdiman - * \date June, 2, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_COLLIDER_H__ -#define __OPC_COLLIDER_H__ - - enum CollisionFlag - { - OPC_FIRST_CONTACT = (1<<0), //!< Report all contacts (false) or only first one (true) - OPC_TEMPORAL_COHERENCE = (1<<1), //!< Use temporal coherence or not - OPC_CONTACT = (1<<2), //!< Final contact status after a collision query - OPC_TEMPORAL_HIT = (1<<3), //!< There has been an early exit due to temporal coherence - OPC_NO_PRIMITIVE_TESTS = (1<<4), //!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries) - - OPC_CONTACT_FOUND = OPC_FIRST_CONTACT | OPC_CONTACT, - OPC_TEMPORAL_CONTACT = OPC_TEMPORAL_HIT | OPC_CONTACT, - - OPC_FORCE_DWORD = 0x7fffffff - }; - - class OPCODE_API Collider - { - public: - // Constructor / Destructor - Collider(); - virtual ~Collider(); - - // Collision report - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the last collision status after a collision query. - * \return true if a collision occured - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL GetContactStatus() const { return mFlags & OPC_CONTACT; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the "first contact" mode. - * \return true if "first contact" mode is on - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL FirstContactEnabled() const { return mFlags & OPC_FIRST_CONTACT; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the temporal coherence mode. - * \return true if temporal coherence is on - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL TemporalCoherenceEnabled() const { return mFlags & OPC_TEMPORAL_COHERENCE; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks a first contact has already been found. - * \return true if a first contact has been found and we can stop a query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL ContactFound() const { return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks there's been an early exit due to temporal coherence; - * \return true if a temporal hit has occured - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL TemporalHit() const { return mFlags & OPC_TEMPORAL_HIT; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks primitive tests are enabled; - * \return true if primitive tests must be skipped - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL SkipPrimitiveTests() const { return mFlags & OPC_NO_PRIMITIVE_TESTS; } - - // Settings - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Reports all contacts (false) or first contact only (true) - * \param flag [in] true for first contact, false for all contacts - * \see SetTemporalCoherence(bool flag) - * \see ValidateSettings() - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetFirstContact(bool flag) - { - if(flag) mFlags |= OPC_FIRST_CONTACT; - else mFlags &= ~OPC_FIRST_CONTACT; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Enable/disable temporal coherence. - * \param flag [in] true to enable temporal coherence, false to discard it - * \see SetFirstContact(bool flag) - * \see ValidateSettings() - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetTemporalCoherence(bool flag) - { - if(flag) mFlags |= OPC_TEMPORAL_COHERENCE; - else mFlags &= ~OPC_TEMPORAL_COHERENCE; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Enable/disable primitive tests. - * \param flag [in] true to enable primitive tests, false to discard them - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetPrimitiveTests(bool flag) - { - if(!flag) mFlags |= OPC_NO_PRIMITIVE_TESTS; - else mFlags &= ~OPC_NO_PRIMITIVE_TESTS; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. - * \return null if everything is ok, else a string describing the problem - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual const char* ValidateSettings() = 0; - - protected: - udword mFlags; //!< Bit flags - const BaseModel* mCurrentModel; //!< Current model for collision query (owner of touched faces) - // User mesh interface - const MeshInterface* mIMesh; //!< User-defined mesh interface - - // Internal methods - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups current collision model - * \param model [in] current collision model - * \return TRUE if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL Setup(const BaseModel* model) - { - // Keep track of current model - mCurrentModel = model; - if(!mCurrentModel) return FALSE; - - mIMesh = model->GetMeshInterface(); - return mIMesh!=null; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Initializes a query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual inline_ void InitQuery() { mFlags &= ~OPC_TEMPORAL_CONTACT; } - }; - -#endif // __OPC_COLLIDER_H__ diff --git a/contrib/Opcode/OPC_Common.cpp b/contrib/Opcode/OPC_Common.cpp deleted file mode 100644 index 6bd9722..0000000 --- a/contrib/Opcode/OPC_Common.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains common classes & defs used in OPCODE. - * \file OPC_Common.cpp - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * An AABB dedicated to collision detection. - * We don't use the generic AABB class included in ICE, since it can be a Min/Max or a Center/Extents one (depends - * on compilation flags). Since the Center/Extents model is more efficient in collision detection, it was worth - * using an extra special class. - * - * \class CollisionAABB - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A quantized AABB. - * Center/Extent model, using 16-bits integers. - * - * \class QuantizedAABB - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; diff --git a/contrib/Opcode/OPC_Common.h b/contrib/Opcode/OPC_Common.h deleted file mode 100644 index 84ccf8d..0000000 --- a/contrib/Opcode/OPC_Common.h +++ /dev/null @@ -1,101 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains common classes & defs used in OPCODE. - * \file OPC_Common.h - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_COMMON_H__ -#define __OPC_COMMON_H__ - -// [GOTTFRIED]: Just a small change for readability. -#ifdef OPC_CPU_COMPARE - #define GREATER(x, y) AIR(x) > IR(y) -#else - #define GREATER(x, y) fabsf(x) > (y) -#endif - - class OPCODE_API CollisionAABB - { - public: - //! Constructor - inline_ CollisionAABB() {} - //! Constructor - inline_ CollisionAABB(const AABB& b) { b.GetCenter(mCenter); b.GetExtents(mExtents); } - //! Destructor - inline_ ~CollisionAABB() {} - - //! Get min IcePoint of the box - inline_ void GetMin(IcePoint& min) const { min = mCenter - mExtents; } - //! Get max IcePoint of the box - inline_ void GetMax(IcePoint& max) const { max = mCenter + mExtents; } - - //! Get component of the box's min IcePoint along a given axis - inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } - //! Get component of the box's max IcePoint along a given axis - inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Setups an AABB from min & max vectors. - * \param min [in] the min IcePoint - * \param max [in] the max IcePoint - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetMinMax(const IcePoint& min, const IcePoint& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks a box is inside another box. - * \param box [in] the other box - * \return true if current box is inside input box - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ BOOL IsInside(const CollisionAABB& box) const - { - if(box.GetMin(0)>GetMin(0)) return FALSE; - if(box.GetMin(1)>GetMin(1)) return FALSE; - if(box.GetMin(2)>GetMin(2)) return FALSE; - if(box.GetMax(0)IsValid()) return false; - - // Look for degenerate faces. - udword NbDegenerate = create.mIMesh->CheckTopology(); - if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); - // We continue nonetheless.... - - Release(); // Make sure previous tree has been discarded - - // 1-1) Setup mesh interface automatically - SetMeshInterface(create.mIMesh); - - bool Status = false; - AABBTree* LeafTree = null; - Internal Data; - - // 2) Build a generic AABB Tree. - mSource = new AABBTree; - CHECKALLOC(mSource); - - // 2-1) Setup a builder. Our primitives here are triangles from input mesh, - // so we use an AABBTreeOfTrianglesBuilder..... - { - AABBTreeOfTrianglesBuilder TB; - TB.mIMesh = create.mIMesh; - TB.mNbPrimitives = create.mIMesh->GetNbTriangles(); - TB.mSettings = create.mSettings; - TB.mSettings.mLimit = 16; // ### Hardcoded, but maybe we could let the user choose 8 / 16 / 32 ... - if(!mSource->Build(&TB)) goto FreeAndExit; - } - - // 2-2) Here's the trick : create *another* AABB tree using the leaves of the first one (which are boxes, this time) - struct Local - { - // A callback to count leaf nodes - static bool CountLeaves(const AABBTreeNode* current, udword depth, void* user_data) - { - if(current->IsLeaf()) - { - Internal* Data = (Internal*)user_data; - Data->mNbLeaves++; - } - return true; - } - - // A callback to setup leaf nodes in our internal structures - static bool SetupLeafData(const AABBTreeNode* current, udword depth, void* user_data) - { - if(current->IsLeaf()) - { - Internal* Data = (Internal*)user_data; - - // Get current leaf's box - Data->mLeaves[Data->mNbLeaves] = *current->GetAABB(); - - // Setup leaf data - udword Index = (udword(current->GetPrimitives()) - udword(Data->mBase))/sizeof(udword); - Data->mTriangles[Data->mNbLeaves].SetData(current->GetNbPrimitives(), Index); - - Data->mNbLeaves++; - } - return true; - } - }; - - // Walk the tree & count number of leaves - Data.mNbLeaves = 0; - mSource->Walk(Local::CountLeaves, &Data); - mNbLeaves = Data.mNbLeaves; // Keep track of it - - // Special case for 1-leaf meshes - if(mNbLeaves==1) - { - mModelCode |= OPC_SINGLE_NODE; - Status = true; - goto FreeAndExit; - } - - // Allocate our structures - Data.mLeaves = new AABB[Data.mNbLeaves]; CHECKALLOC(Data.mLeaves); - mTriangles = new LeafTriangles[Data.mNbLeaves]; CHECKALLOC(mTriangles); - - // Walk the tree again & setup leaf data - Data.mTriangles = mTriangles; - Data.mBase = mSource->GetIndices(); - Data.mNbLeaves = 0; // Reset for incoming walk - mSource->Walk(Local::SetupLeafData, &Data); - - // Handle source indices - { - bool MustKeepIndices = true; - if(create.mCanRemap) - { - // We try to get rid of source indices (saving more ram!) by reorganizing triangle arrays... - // Remap can fail when we use callbacks => keep track of indices in that case (it still - // works, only using more memory) - if(create.mIMesh->RemapClient(mSource->GetNbPrimitives(), mSource->GetIndices())) - { - MustKeepIndices = false; - } - } - - if(MustKeepIndices) - { - // Keep track of source indices (from vanilla tree) - mNbPrimitives = mSource->GetNbPrimitives(); - mIndices = new udword[mNbPrimitives]; - CopyMemory(mIndices, mSource->GetIndices(), mNbPrimitives*sizeof(udword)); - } - } - - // Now, create our optimized tree using previous leaf nodes - LeafTree = new AABBTree; - CHECKALLOC(LeafTree); - { - AABBTreeOfAABBsBuilder TB; // Now using boxes ! - TB.mSettings = create.mSettings; - TB.mSettings.mLimit = 1; // We now want a complete tree so that we can "optimize" it - TB.mNbPrimitives = Data.mNbLeaves; - TB.mAABBArray = Data.mLeaves; - if(!LeafTree->Build(&TB)) goto FreeAndExit; - } - - // 3) Create an optimized tree according to user-settings - if(!CreateTree(create.mNoLeaf, create.mQuantized)) goto FreeAndExit; - - // 3-2) Create optimized tree - if(!mTree->Build(LeafTree)) goto FreeAndExit; - - // Finally ok... - Status = true; - -FreeAndExit: // Allow me this one... - DELETESINGLE(LeafTree); - - // 3-3) Delete generic tree if needed - if(!create.mKeepOriginal) DELETESINGLE(mSource); - - return Status; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Gets the number of bytes used by the tree. - * \return amount of bytes used - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -udword HybridModel::GetUsedBytes() const -{ - udword UsedBytes = 0; - if(mTree) UsedBytes += mTree->GetUsedBytes(); - if(mIndices) UsedBytes += mNbPrimitives * sizeof(udword); // mIndices - if(mTriangles) UsedBytes += mNbLeaves * sizeof(LeafTriangles); // mTriangles - return UsedBytes; -} - -inline_ void ComputeMinMax(IcePoint& min, IcePoint& max, const VertexPointers& vp) -{ - // Compute triangle's AABB = a leaf box -#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much - min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); - max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); - - min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); - max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); - - min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); - max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); -#else - min = *vp.Vertex[0]; - max = *vp.Vertex[0]; - min.Min(*vp.Vertex[1]); - max.Max(*vp.Vertex[1]); - min.Min(*vp.Vertex[2]); - max.Max(*vp.Vertex[2]); -#endif -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Refits the collision model. This can be used to handle dynamic meshes. Usage is: - * 1. modify your mesh vertices (keep the topology constant!) - * 2. refit the tree (call this method) - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool HybridModel::Refit() -{ - if(!mIMesh) return false; - if(!mTree) return false; - - if(IsQuantized()) return false; - if(HasLeafNodes()) return false; - - const LeafTriangles* LT = GetLeafTriangles(); - const udword* Indices = GetIndices(); - - // Bottom-up update - VertexPointers VP; - IcePoint Min,Max; - IcePoint Min_,Max_; - udword Index = mTree->GetNbNodes(); - AABBNoLeafNode* Nodes = (AABBNoLeafNode*)((AABBNoLeafTree*)mTree)->GetNodes(); - while(Index--) - { - AABBNoLeafNode& Current = Nodes[Index]; - - if(Current.HasPosLeaf()) - { - const LeafTriangles& CurrentLeaf = LT[Current.GetPosPrimitive()]; - - Min.SetPlusInfinity(); - Max.SetMinusInfinity(); - - IcePoint TmpMin, TmpMax; - - // Each leaf box has a set of triangles - udword NbTris = CurrentLeaf.GetNbTriangles(); - if(Indices) - { - const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; - - // Loop through triangles and test each of them - while(NbTris--) - { - mIMesh->GetTriangle(VP, *T++); - ComputeMinMax(TmpMin, TmpMax, VP); - Min.Min(TmpMin); - Max.Max(TmpMax); - } - } - else - { - udword BaseIndex = CurrentLeaf.GetTriangleIndex(); - - // Loop through triangles and test each of them - while(NbTris--) - { - mIMesh->GetTriangle(VP, BaseIndex++); - ComputeMinMax(TmpMin, TmpMax, VP); - Min.Min(TmpMin); - Max.Max(TmpMax); - } - } - } - else - { - const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; - CurrentBox.GetMin(Min); - CurrentBox.GetMax(Max); - } - - if(Current.HasNegLeaf()) - { - const LeafTriangles& CurrentLeaf = LT[Current.GetNegPrimitive()]; - - Min_.SetPlusInfinity(); - Max_.SetMinusInfinity(); - - IcePoint TmpMin, TmpMax; - - // Each leaf box has a set of triangles - udword NbTris = CurrentLeaf.GetNbTriangles(); - if(Indices) - { - const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; - - // Loop through triangles and test each of them - while(NbTris--) - { - mIMesh->GetTriangle(VP, *T++); - ComputeMinMax(TmpMin, TmpMax, VP); - Min_.Min(TmpMin); - Max_.Max(TmpMax); - } - } - else - { - udword BaseIndex = CurrentLeaf.GetTriangleIndex(); - - // Loop through triangles and test each of them - while(NbTris--) - { - mIMesh->GetTriangle(VP, BaseIndex++); - ComputeMinMax(TmpMin, TmpMax, VP); - Min_.Min(TmpMin); - Max_.Max(TmpMax); - } - } - } - else - { - const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; - CurrentBox.GetMin(Min_); - CurrentBox.GetMax(Max_); - } -#ifdef OPC_USE_FCOMI - Min.x = FCMin2(Min.x, Min_.x); - Max.x = FCMax2(Max.x, Max_.x); - Min.y = FCMin2(Min.y, Min_.y); - Max.y = FCMax2(Max.y, Max_.y); - Min.z = FCMin2(Min.z, Min_.z); - Max.z = FCMax2(Max.z, Max_.z); -#else - Min.Min(Min_); - Max.Max(Max_); -#endif - Current.mAABB.SetMinMax(Min, Max); - } - return true; -} diff --git a/contrib/Opcode/OPC_HybridModel.h b/contrib/Opcode/OPC_HybridModel.h deleted file mode 100644 index c7eb59d..0000000 --- a/contrib/Opcode/OPC_HybridModel.h +++ /dev/null @@ -1,106 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for hybrid models. - * \file OPC_HybridModel.h - * \author Pierre Terdiman - * \date May, 18, 2003 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_HYBRIDMODEL_H__ -#define __OPC_HYBRIDMODEL_H__ - - //! Leaf descriptor - struct LeafTriangles - { - udword Data; //!< Packed data - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets number of triangles in the leaf. - * \return number of triangles N, with 0 < N <= 16 - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbTriangles() const { return (Data & 15)+1; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets triangle index for this leaf. Indexed model's array of indices retrieved with HybridModel::GetIndices() - * \return triangle index - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetTriangleIndex() const { return Data>>4; } - inline_ void SetData(udword nb, udword index) { ASSERT(nb>0 && nb<=16); nb--; Data = (index<<4)|(nb&15); } - }; - - class OPCODE_API HybridModel : public BaseModel - { - public: - // Constructor/Destructor - HybridModel(); - virtual ~HybridModel(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Builds a collision model. - * \param create [in] model creation structure - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(BaseModel) bool Build(const OPCODECREATE& create); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the number of bytes used by the tree. - * \return amount of bytes used - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(BaseModel) udword GetUsedBytes() const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Refits the collision model. This can be used to handle dynamic meshes. Usage is: - * 1. modify your mesh vertices (keep the topology constant!) - * 2. refit the tree (call this method) - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(BaseModel) bool Refit(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets array of triangles. - * \return array of triangles - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ const LeafTriangles* GetLeafTriangles() const { return mTriangles; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets array of indices. - * \return array of indices - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ const udword* GetIndices() const { return mIndices; } - - private: - udword mNbLeaves; //!< Number of leaf nodes in the model - LeafTriangles* mTriangles; //!< Array of mNbLeaves leaf descriptors - udword mNbPrimitives; //!< Number of primitives in the model - udword* mIndices; //!< Array of primitive indices - - // Internal methods - void Release(); - }; - -#endif // __OPC_HYBRIDMODEL_H__ diff --git a/contrib/Opcode/OPC_IceHook.h b/contrib/Opcode/OPC_IceHook.h deleted file mode 100644 index d33120b..0000000 --- a/contrib/Opcode/OPC_IceHook.h +++ /dev/null @@ -1,70 +0,0 @@ - -// Should be included by Opcode.h if needed - - #define ICE_DONT_CHECK_COMPILER_OPTIONS - - // From Windows... - typedef int BOOL; - #ifndef FALSE - #define FALSE 0 - #endif - - #ifndef TRUE - #define TRUE 1 - #endif - - #include - #include - #include - #include - #include - #include - - #ifndef ASSERT - #define ASSERT(exp) {} - #endif - #define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ] - - #define Log {} - #define SetIceError false - #define EC_OUTOFMEMORY "Out of memory" - - #include "Ice/IcePreprocessor.h" - - #undef ICECORE_API - #define ICECORE_API OPCODE_API - - #include "Ice/IceTypes.h" - #include "Ice/IceFPU.h" - #include "Ice/IceMemoryMacros.h" - - namespace IceCore - { - #include "Ice/IceUtils.h" - #include "Ice/IceContainer.h" - #include "Ice/IcePairs.h" - #include "Ice/IceRevisitedRadix.h" - #include "Ice/IceRandom.h" - } - using namespace IceCore; - - #define ICEMATHS_API OPCODE_API - namespace IceMaths - { - #include "Ice/IceAxes.h" - #include "Ice/IcePoint.h" - #include "Ice/IceHPoint.h" - #include "Ice/IceMatrix3x3.h" - #include "Ice/IceMatrix4x4.h" - #include "Ice/IcePlane.h" - #include "Ice/IceRay.h" - #include "Ice/IceIndexedTriangle.h" - #include "Ice/IceTriangle.h" - #include "Ice/IceTrilist.h" - #include "Ice/IceAABB.h" - #include "Ice/IceOBB.h" - #include "Ice/IceBoundingSphere.h" - #include "Ice/IceSegment.h" - #include "Ice/IceLSS.h" - } - using namespace IceMaths; diff --git a/contrib/Opcode/OPC_LSSAABBOverlap.h b/contrib/Opcode/OPC_LSSAABBOverlap.h deleted file mode 100644 index 5afb190..0000000 --- a/contrib/Opcode/OPC_LSSAABBOverlap.h +++ /dev/null @@ -1,523 +0,0 @@ - -// Following code from Magic-Software (http://www.magic-software.com/) -// A bit modified for Opcode - -inline_ float OPC_PointAABBSqrDist(const IcePoint& Point, const IcePoint& center, const IcePoint& extents) -{ - // Compute coordinates of IcePoint in box coordinate system - IcePoint Closest = Point - center; - - float SqrDistance = 0.0f; - - if(Closest.x < -extents.x) - { - float Delta = Closest.x + extents.x; - SqrDistance += Delta*Delta; - } - else if(Closest.x > extents.x) - { - float Delta = Closest.x - extents.x; - SqrDistance += Delta*Delta; - } - - if(Closest.y < -extents.y) - { - float Delta = Closest.y + extents.y; - SqrDistance += Delta*Delta; - } - else if(Closest.y > extents.y) - { - float Delta = Closest.y - extents.y; - SqrDistance += Delta*Delta; - } - - if(Closest.z < -extents.z) - { - float Delta = Closest.z + extents.z; - SqrDistance += Delta*Delta; - } - else if(Closest.z > extents.z) - { - float Delta = Closest.z - extents.z; - SqrDistance += Delta*Delta; - } - return SqrDistance; -} - -static void Face(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, const IcePoint& rkPmE, float* pfLParam, float& rfSqrDistance) -{ - IcePoint kPpE; - float fLSqr, fInv, fTmp, fParam, fT, fDelta; - - kPpE[i1] = rkPnt[i1] + extents[i1]; - kPpE[i2] = rkPnt[i2] + extents[i2]; - if(rkDir[i0]*kPpE[i1] >= rkDir[i1]*rkPmE[i0]) - { - if(rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0]) - { - // v[i1] >= -e[i1], v[i2] >= -e[i2] (distance = 0) - if(pfLParam) - { - rkPnt[i0] = extents[i0]; - fInv = 1.0f/rkDir[i0]; - rkPnt[i1] -= rkDir[i1]*rkPmE[i0]*fInv; - rkPnt[i2] -= rkDir[i2]*rkPmE[i0]*fInv; - *pfLParam = -rkPmE[i0]*fInv; - } - } - else - { - // v[i1] >= -e[i1], v[i2] < -e[i2] - fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i2]*rkDir[i2]; - fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); - if(fTmp <= 2.0f*fLSqr*extents[i1]) - { - fT = fTmp/fLSqr; - fLSqr += rkDir[i1]*rkDir[i1]; - fTmp = kPpE[i1] - fT; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = fT - extents[i1]; - rkPnt[i2] = -extents[i2]; - } - } - else - { - fLSqr += rkDir[i1]*rkDir[i1]; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = extents[i1]; - rkPnt[i2] = -extents[i2]; - } - } - } - } - else - { - if ( rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0] ) - { - // v[i1] < -e[i1], v[i2] >= -e[i2] - fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; - fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); - if(fTmp <= 2.0f*fLSqr*extents[i2]) - { - fT = fTmp/fLSqr; - fLSqr += rkDir[i2]*rkDir[i2]; - fTmp = kPpE[i2] - fT; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = -extents[i1]; - rkPnt[i2] = fT - extents[i2]; - } - } - else - { - fLSqr += rkDir[i2]*rkDir[i2]; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = -extents[i1]; - rkPnt[i2] = extents[i2]; - } - } - } - else - { - // v[i1] < -e[i1], v[i2] < -e[i2] - fLSqr = rkDir[i0]*rkDir[i0]+rkDir[i2]*rkDir[i2]; - fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); - if(fTmp >= 0.0f) - { - // v[i1]-edge is closest - if ( fTmp <= 2.0f*fLSqr*extents[i1] ) - { - fT = fTmp/fLSqr; - fLSqr += rkDir[i1]*rkDir[i1]; - fTmp = kPpE[i1] - fT; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = fT - extents[i1]; - rkPnt[i2] = -extents[i2]; - } - } - else - { - fLSqr += rkDir[i1]*rkDir[i1]; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = extents[i1]; - rkPnt[i2] = -extents[i2]; - } - } - return; - } - - fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; - fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); - if(fTmp >= 0.0f) - { - // v[i2]-edge is closest - if(fTmp <= 2.0f*fLSqr*extents[i2]) - { - fT = fTmp/fLSqr; - fLSqr += rkDir[i2]*rkDir[i2]; - fTmp = kPpE[i2] - fT; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = -extents[i1]; - rkPnt[i2] = fT - extents[i2]; - } - } - else - { - fLSqr += rkDir[i2]*rkDir[i2]; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = -extents[i1]; - rkPnt[i2] = extents[i2]; - } - } - return; - } - - // (v[i1],v[i2])-corner is closest - fLSqr += rkDir[i2]*rkDir[i2]; - fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*kPpE[i2]; - fParam = -fDelta/fLSqr; - rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; - - if(pfLParam) - { - *pfLParam = fParam; - rkPnt[i0] = extents[i0]; - rkPnt[i1] = -extents[i1]; - rkPnt[i2] = -extents[i2]; - } - } - } -} - -static void CaseNoZeros(IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) -{ - IcePoint kPmE(rkPnt.x - extents.x, rkPnt.y - extents.y, rkPnt.z - extents.z); - - float fProdDxPy, fProdDyPx, fProdDzPx, fProdDxPz, fProdDzPy, fProdDyPz; - - fProdDxPy = rkDir.x*kPmE.y; - fProdDyPx = rkDir.y*kPmE.x; - if(fProdDyPx >= fProdDxPy) - { - fProdDzPx = rkDir.z*kPmE.x; - fProdDxPz = rkDir.x*kPmE.z; - if(fProdDzPx >= fProdDxPz) - { - // line intersects x = e0 - Face(0, 1, 2, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); - } - else - { - // line intersects z = e2 - Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); - } - } - else - { - fProdDzPy = rkDir.z*kPmE.y; - fProdDyPz = rkDir.y*kPmE.z; - if(fProdDzPy >= fProdDyPz) - { - // line intersects y = e1 - Face(1, 2, 0, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); - } - else - { - // line intersects z = e2 - Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); - } - } -} - -static void Case0(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) -{ - float fPmE0 = rkPnt[i0] - extents[i0]; - float fPmE1 = rkPnt[i1] - extents[i1]; - float fProd0 = rkDir[i1]*fPmE0; - float fProd1 = rkDir[i0]*fPmE1; - float fDelta, fInvLSqr, fInv; - - if(fProd0 >= fProd1) - { - // line intersects P[i0] = e[i0] - rkPnt[i0] = extents[i0]; - - float fPpE1 = rkPnt[i1] + extents[i1]; - fDelta = fProd0 - rkDir[i0]*fPpE1; - if(fDelta >= 0.0f) - { - fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); - rfSqrDistance += fDelta*fDelta*fInvLSqr; - if(pfLParam) - { - rkPnt[i1] = -extents[i1]; - *pfLParam = -(rkDir[i0]*fPmE0+rkDir[i1]*fPpE1)*fInvLSqr; - } - } - else - { - if(pfLParam) - { - fInv = 1.0f/rkDir[i0]; - rkPnt[i1] -= fProd0*fInv; - *pfLParam = -fPmE0*fInv; - } - } - } - else - { - // line intersects P[i1] = e[i1] - rkPnt[i1] = extents[i1]; - - float fPpE0 = rkPnt[i0] + extents[i0]; - fDelta = fProd1 - rkDir[i1]*fPpE0; - if(fDelta >= 0.0f) - { - fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); - rfSqrDistance += fDelta*fDelta*fInvLSqr; - if(pfLParam) - { - rkPnt[i0] = -extents[i0]; - *pfLParam = -(rkDir[i0]*fPpE0+rkDir[i1]*fPmE1)*fInvLSqr; - } - } - else - { - if(pfLParam) - { - fInv = 1.0f/rkDir[i1]; - rkPnt[i0] -= fProd1*fInv; - *pfLParam = -fPmE1*fInv; - } - } - } - - if(rkPnt[i2] < -extents[i2]) - { - fDelta = rkPnt[i2] + extents[i2]; - rfSqrDistance += fDelta*fDelta; - rkPnt[i2] = -extents[i2]; - } - else if ( rkPnt[i2] > extents[i2] ) - { - fDelta = rkPnt[i2] - extents[i2]; - rfSqrDistance += fDelta*fDelta; - rkPnt[i2] = extents[i2]; - } -} - -static void Case00(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) -{ - float fDelta; - - if(pfLParam) - *pfLParam = (extents[i0] - rkPnt[i0])/rkDir[i0]; - - rkPnt[i0] = extents[i0]; - - if(rkPnt[i1] < -extents[i1]) - { - fDelta = rkPnt[i1] + extents[i1]; - rfSqrDistance += fDelta*fDelta; - rkPnt[i1] = -extents[i1]; - } - else if(rkPnt[i1] > extents[i1]) - { - fDelta = rkPnt[i1] - extents[i1]; - rfSqrDistance += fDelta*fDelta; - rkPnt[i1] = extents[i1]; - } - - if(rkPnt[i2] < -extents[i2]) - { - fDelta = rkPnt[i2] + extents[i2]; - rfSqrDistance += fDelta*fDelta; - rkPnt[i1] = -extents[i2]; - } - else if(rkPnt[i2] > extents[i2]) - { - fDelta = rkPnt[i2] - extents[i2]; - rfSqrDistance += fDelta*fDelta; - rkPnt[i2] = extents[i2]; - } -} - -static void Case000(IcePoint& rkPnt, const IcePoint& extents, float& rfSqrDistance) -{ - float fDelta; - - if(rkPnt.x < -extents.x) - { - fDelta = rkPnt.x + extents.x; - rfSqrDistance += fDelta*fDelta; - rkPnt.x = -extents.x; - } - else if(rkPnt.x > extents.x) - { - fDelta = rkPnt.x - extents.x; - rfSqrDistance += fDelta*fDelta; - rkPnt.x = extents.x; - } - - if(rkPnt.y < -extents.y) - { - fDelta = rkPnt.y + extents.y; - rfSqrDistance += fDelta*fDelta; - rkPnt.y = -extents.y; - } - else if(rkPnt.y > extents.y) - { - fDelta = rkPnt.y - extents.y; - rfSqrDistance += fDelta*fDelta; - rkPnt.y = extents.y; - } - - if(rkPnt.z < -extents.z) - { - fDelta = rkPnt.z + extents.z; - rfSqrDistance += fDelta*fDelta; - rkPnt.z = -extents.z; - } - else if(rkPnt.z > extents.z) - { - fDelta = rkPnt.z - extents.z; - rfSqrDistance += fDelta*fDelta; - rkPnt.z = extents.z; - } -} - -static float SqrDistance(const Ray& rkLine, const IcePoint& center, const IcePoint& extents, float* pfLParam) -{ - // compute coordinates of line in box coordinate system - IcePoint kDiff = rkLine.mOrig - center; - IcePoint kPnt = kDiff; - IcePoint kDir = rkLine.mDir; - - // Apply reflections so that direction vector has nonnegative components. - bool bReflect[3]; - for(int i=0;i<3;i++) - { - if(kDir[i]<0.0f) - { - kPnt[i] = -kPnt[i]; - kDir[i] = -kDir[i]; - bReflect[i] = true; - } - else - { - bReflect[i] = false; - } - } - - float fSqrDistance = 0.0f; - - if(kDir.x>0.0f) - { - if(kDir.y>0.0f) - { - if(kDir.z>0.0f) CaseNoZeros(kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,+) - else Case0(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,0) - } - else - { - if(kDir.z>0.0f) Case0(0, 2, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,+) - else Case00(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,0) - } - } - else - { - if(kDir.y>0.0f) - { - if(kDir.z>0.0f) Case0(1, 2, 0, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,+) - else Case00(1, 0, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,0) - } - else - { - if(kDir.z>0.0f) Case00(2, 0, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,0,+) - else - { - Case000(kPnt, extents, fSqrDistance); // (0,0,0) - if(pfLParam) *pfLParam = 0.0f; - } - } - } - return fSqrDistance; -} - -inline_ float OPC_SegmentOBBSqrDist(const IceSegment& segment, const IcePoint& c0, const IcePoint& e0) -{ - float fLP; - float fSqrDistance = SqrDistance(Ray(segment.GetOrigin(), segment.ComputeDirection()), c0, e0, &fLP); - if(fLP>=0.0f) - { - if(fLP<=1.0f) return fSqrDistance; - else return OPC_PointAABBSqrDist(segment.mP1, c0, e0); - } - else return OPC_PointAABBSqrDist(segment.mP0, c0, e0); -} - -inline_ BOOL LSSCollider::LSSAABBOverlap(const IcePoint& center, const IcePoint& extents) -{ - // Stats - mNbVolumeBVTests++; - - float s2 = OPC_SegmentOBBSqrDist(mSeg, center, extents); - if(s2Add(prim_index); - -//! LSS-triangle overlap test -#define LSS_PRIM(prim_index, flag) \ - /* Request vertices from the app */ \ - VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ - \ - /* Perform LSS-tri overlap test */ \ - if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ - { \ - SET_CONTACT(prim_index, flag) \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -LSSCollider::LSSCollider() -{ -// mCenter.Zero(); -// mRadius2 = 0.0f; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -LSSCollider::~LSSCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] an lss cache - * \param lss [in] collision lss in local space - * \param model [in] Opcode model to collide with - * \param worldl [in] lss world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl, const Matrix4x4* worldm) -{ - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, lss, worldl, worldm)) return true; - - if(!model.HasLeafNodes()) - { - if(model.IsQuantized()) - { - const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - } - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Initializes a collision query : - * - reset stats & contact status - * - setup matrices - * - check temporal coherence - * - * \param cache [in/out] an lss cache - * \param lss [in] lss in local space - * \param worldl [in] lss world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return TRUE if we can return immediately - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOL LSSCollider::InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl, const Matrix4x4* worldm) -{ - // 1) Call the base method - VolumeCollider::InitQuery(); - - // 2) Compute LSS in model space: - // - Precompute R^2 - mRadius2 = lss.mRadius * lss.mRadius; - // - Compute segment - mSeg.mP0 = lss.mP0; - mSeg.mP1 = lss.mP1; - // -> to world space - if(worldl) - { - mSeg.mP0 *= *worldl; - mSeg.mP1 *= *worldl; - } - // -> to model space - if(worldm) - { - // Invert model matrix - Matrix4x4 InvWorldM; - InvertPRMatrix(InvWorldM, *worldm); - - mSeg.mP0 *= InvWorldM; - mSeg.mP1 *= InvWorldM; - } - - // 3) Setup destination pointer - mTouchedPrimitives = &cache.TouchedPrimitives; - - // 4) Special case: 1-triangle meshes [Opcode 1.3] - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - if(!SkipPrimitiveTests()) - { - // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. - mTouchedPrimitives->Reset(); - - // Perform overlap test between the unique triangle and the LSS (and set contact status if needed) - LSS_PRIM(udword(0), OPC_CONTACT) - - // Return immediately regardless of status - return TRUE; - } - } - - // 5) Check temporal coherence : - if(TemporalCoherenceEnabled()) - { - // Here we use temporal coherence - // => check results from previous frame before performing the collision query - if(FirstContactEnabled()) - { - // We're only interested in the first contact found => test the unique previously touched face - if(mTouchedPrimitives->GetNbEntries()) - { - // Get index of previously touched face = the first entry in the array - udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); - - // Then reset the array: - // - if the overlap test below is successful, the index we'll get added back anyway - // - if it isn't, then the array should be reset anyway for the normal query - mTouchedPrimitives->Reset(); - - // Perform overlap test between the cached triangle and the LSS (and set contact status if needed) - LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) - - // Return immediately if possible - if(GetContactStatus()) return TRUE; - } - // else no face has been touched during previous query - // => we'll have to perform a normal query - } - else - { - // We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious): - - // ### rewrite this - - LSS Test(mSeg, lss.mRadius); // in model space - LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius)); - -// if(cache.Previous.Contains(Test)) - if(IsCacheValid(cache) && Previous.Contains(Test)) - { - // - if N is included in P, return previous list - // => we simply leave the list (mTouchedFaces) unchanged - - // Set contact status if needed - if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; - - // In any case we don't need to do a query - return TRUE; - } - else - { - // - else do the query using a fat N - - // Reset cache since we'll about to perform a real query - mTouchedPrimitives->Reset(); - - // Make a fat sphere so that coherence will work for subsequent frames - mRadius2 *= cache.FatCoeff; -// mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff); - - - // Update cache with query data (signature for cached faces) - cache.Previous.mP0 = mSeg.mP0; - cache.Previous.mP1 = mSeg.mP1; - cache.Previous.mRadius = mRadius2; - } - } - } - else - { - // Here we don't use temporal coherence => do a normal query - mTouchedPrimitives->Reset(); - } - - return FALSE; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Collision query for vanilla AABB trees. - * \param cache [in/out] an lss cache - * \param lss [in] collision lss in world space - * \param tree [in] AABB tree - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree) -{ - // This is typically called for a scene tree, full of -AABBs-, not full of triangles. - // So we don't really have "primitives" to deal with. Hence it doesn't work with - // "FirstContact" + "TemporalCoherence". - ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); - - // Checkings - if(!tree) return false; - - // Init collision query - if(InitQuery(cache, lss)) return true; - - // Perform collision query - _Collide(tree); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks the LSS completely contains the box. In which case we can end the query sooner. - * \param bc [in] box center - * \param be [in] box extents - * \return true if the LSS contains the whole box - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL LSSCollider::LSSContainsBox(const IcePoint& bc, const IcePoint& be) -{ - // Not implemented - return FALSE; -} - -#define TEST_BOX_IN_LSS(center, extents) \ - if(LSSContainsBox(center, extents)) \ - { \ - /* Set contact status */ \ - mFlags |= OPC_CONTACT; \ - _Dump(node); \ - return; \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_Collide(const AABBCollisionNode* node) -{ - // Perform LSS-AABB overlap test - if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->IsLeaf()) - { - LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos()); - - if(ContactFound()) return; - - _Collide(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) -{ - // Perform LSS-AABB overlap test - if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_Collide(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform LSS-AABB overlap test - if(!LSSAABBOverlap(Center, Extents)) return; - - TEST_BOX_IN_LSS(Center, Extents) - - if(node->IsLeaf()) - { - LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos()); - - if(ContactFound()) return; - - _Collide(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform LSS-AABB overlap test - if(!LSSAABBOverlap(Center, Extents)) return; - - TEST_BOX_IN_LSS(Center, Extents) - - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_Collide(const AABBNoLeafNode* node) -{ - // Perform LSS-AABB overlap test - if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) -{ - // Perform LSS-AABB overlap test - if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform LSS-AABB overlap test - if(!LSSAABBOverlap(Center, Extents)) return; - - TEST_BOX_IN_LSS(Center, Extents) - - if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform LSS-AABB overlap test - if(!LSSAABBOverlap(Center, Extents)) return; - - TEST_BOX_IN_LSS(Center, Extents) - - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for vanilla AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void LSSCollider::_Collide(const AABBTreeNode* node) -{ - // Perform LSS-AABB overlap test - IcePoint Center, Extents; - node->GetAABB()->GetCenter(Center); - node->GetAABB()->GetExtents(Extents); - if(!LSSAABBOverlap(Center, Extents)) return; - - if(node->IsLeaf() || LSSContainsBox(Center, Extents)) - { - mFlags |= OPC_CONTACT; - mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); - } - else - { - _Collide(node->GetPos()); - _Collide(node->GetNeg()); - } -} - - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridLSSCollider::HybridLSSCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridLSSCollider::~HybridLSSCollider() -{ -} - -bool HybridLSSCollider::Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl, const Matrix4x4* worldm) -{ - // We don't want primitive tests here! - mFlags |= OPC_NO_PRIMITIVE_TESTS; - - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, lss, worldl, worldm)) return true; - - // Special case for 1-leaf trees - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles - udword Nb = mIMesh->GetNbTriangles(); - - // Loop through all triangles - for(udword i=0;imCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - } - - // We only have a list of boxes so far - if(GetContactStatus()) - { - // Reset contact status, since it currently only reflects collisions with leaf boxes - Collider::InitQuery(); - - // Change dest container so that we can use built-in overlap tests and get collided primitives - cache.TouchedPrimitives.Reset(); - mTouchedPrimitives = &cache.TouchedPrimitives; - - // Read touched leaf boxes - udword Nb = mTouchedBoxes.GetNbEntries(); - const udword* Touched = mTouchedBoxes.GetEntries(); - - const LeafTriangles* LT = model.GetLeafTriangles(); - const udword* Indices = model.GetIndices(); - - // Loop through touched leaves - while(Nb--) - { - const LeafTriangles& CurrentLeaf = LT[*Touched++]; - - // Each leaf box has a set of triangles - udword NbTris = CurrentLeaf.GetNbTriangles(); - if(Indices) - { - const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; - - // Loop through triangles and test each of them - while(NbTris--) - { - udword TriangleIndex = *T++; - LSS_PRIM(TriangleIndex, OPC_CONTACT) - } - } - else - { - udword BaseIndex = CurrentLeaf.GetTriangleIndex(); - - // Loop through triangles and test each of them - while(NbTris--) - { - udword TriangleIndex = BaseIndex++; - LSS_PRIM(TriangleIndex, OPC_CONTACT) - } - } - } - } - - return true; -} diff --git a/contrib/Opcode/OPC_LSSCollider.h b/contrib/Opcode/OPC_LSSCollider.h deleted file mode 100644 index 426564c..0000000 --- a/contrib/Opcode/OPC_LSSCollider.h +++ /dev/null @@ -1,99 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for an LSS collider. - * \file OPC_LSSCollider.h - * \author Pierre Terdiman - * \date December, 28, 2002 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_LSSCOLLIDER_H__ -#define __OPC_LSSCOLLIDER_H__ - - struct OPCODE_API LSSCache : VolumeCache - { - LSSCache() - { - Previous.mP0 = IcePoint(0.0f, 0.0f, 0.0f); - Previous.mP1 = IcePoint(0.0f, 0.0f, 0.0f); - Previous.mRadius = 0.0f; - FatCoeff = 1.1f; - } - - // Cached faces signature - LSS Previous; //!< LSS used when performing the query resulting in cached faces - // User settings - float FatCoeff; //!< mRadius2 multiplier used to create a fat LSS - }; - - class OPCODE_API LSSCollider : public VolumeCollider - { - public: - // Constructor / Destructor - LSSCollider(); - virtual ~LSSCollider(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] an lss cache - * \param lss [in] collision lss in local space - * \param model [in] Opcode model to collide with - * \param worldl [in] lss world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); - // - bool Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree); - protected: - // LSS in model space - IceSegment mSeg; //!< IceSegment - float mRadius2; //!< LSS radius squared - // Internal methods - void _Collide(const AABBCollisionNode* node); - void _Collide(const AABBNoLeafNode* node); - void _Collide(const AABBQuantizedNode* node); - void _Collide(const AABBQuantizedNoLeafNode* node); - void _Collide(const AABBTreeNode* node); - void _CollideNoPrimitiveTest(const AABBCollisionNode* node); - void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); - void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); - void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); - // Overlap tests - inline_ BOOL LSSContainsBox(const IcePoint& bc, const IcePoint& be); - inline_ BOOL LSSAABBOverlap(const IcePoint& center, const IcePoint& extents); - inline_ BOOL LSSTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); - // Init methods - BOOL InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); - }; - - class OPCODE_API HybridLSSCollider : public LSSCollider - { - public: - // Constructor / Destructor - HybridLSSCollider(); - virtual ~HybridLSSCollider(); - - bool Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); - protected: - Container mTouchedBoxes; - }; - -#endif // __OPC_LSSCOLLIDER_H__ diff --git a/contrib/Opcode/OPC_LSSTriOverlap.h b/contrib/Opcode/OPC_LSSTriOverlap.h deleted file mode 100644 index 9957534..0000000 --- a/contrib/Opcode/OPC_LSSTriOverlap.h +++ /dev/null @@ -1,679 +0,0 @@ -// Following code from Magic-Software (http://www.magic-software.com/) -// A bit modified for Opcode - -static const float gs_fTolerance = 1e-05f; - -static float OPC_PointTriangleSqrDist(const IcePoint& Point, const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) -{ - // Hook - IcePoint TriEdge0 = p1 - p0; - IcePoint TriEdge1 = p2 - p0; - - IcePoint kDiff = p0 - Point; - float fA00 = TriEdge0.SquareMagnitude(); - float fA01 = TriEdge0 | TriEdge1; - float fA11 = TriEdge1.SquareMagnitude(); - float fB0 = kDiff | TriEdge0; - float fB1 = kDiff | TriEdge1; - float fC = kDiff.SquareMagnitude(); - float fDet = fabsf(fA00*fA11 - fA01*fA01); - float fS = fA01*fB1-fA11*fB0; - float fT = fA01*fB0-fA00*fB1; - float fSqrDist; - - if(fS + fT <= fDet) - { - if(fS < 0.0f) - { - if(fT < 0.0f) // region 4 - { - if(fB0 < 0.0f) - { - if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; - else fSqrDist = fB0*(-fB0/fA00)+fC; - } - else - { - if(fB1 >= 0.0f) fSqrDist = fC; - else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; - else fSqrDist = fB1*(-fB1/fA11)+fC; - } - } - else // region 3 - { - if(fB1 >= 0.0f) fSqrDist = fC; - else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; - else fSqrDist = fB1*(-fB1/fA11)+fC; - } - } - else if(fT < 0.0f) // region 5 - { - if(fB0 >= 0.0f) fSqrDist = fC; - else if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; - else fSqrDist = fB0*(-fB0/fA00)+fC; - } - else // region 0 - { - // minimum at interior IcePoint - if(fDet==0.0f) - { - fSqrDist = MAX_FLOAT; - } - else - { - float fInvDet = 1.0f/fDet; - fS *= fInvDet; - fT *= fInvDet; - fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; - } - } - } - else - { - float fTmp0, fTmp1, fNumer, fDenom; - - if(fS < 0.0f) // region 2 - { - fTmp0 = fA01 + fB0; - fTmp1 = fA11 + fB1; - if(fTmp1 > fTmp0) - { - fNumer = fTmp1 - fTmp0; - fDenom = fA00-2.0f*fA01+fA11; - if(fNumer >= fDenom) - { - fSqrDist = fA00+2.0f*fB0+fC; - } - else - { - fS = fNumer/fDenom; - fT = 1.0f - fS; - fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; - } - } - else - { - if(fTmp1 <= 0.0f) fSqrDist = fA11+2.0f*fB1+fC; - else if(fB1 >= 0.0f) fSqrDist = fC; - else fSqrDist = fB1*(-fB1/fA11)+fC; - } - } - else if(fT < 0.0f) // region 6 - { - fTmp0 = fA01 + fB1; - fTmp1 = fA00 + fB0; - if(fTmp1 > fTmp0) - { - fNumer = fTmp1 - fTmp0; - fDenom = fA00-2.0f*fA01+fA11; - if(fNumer >= fDenom) - { - fSqrDist = fA11+2.0f*fB1+fC; - } - else - { - fT = fNumer/fDenom; - fS = 1.0f - fT; - fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; - } - } - else - { - if(fTmp1 <= 0.0f) fSqrDist = fA00+2.0f*fB0+fC; - else if(fB0 >= 0.0f) fSqrDist = fC; - else fSqrDist = fB0*(-fB0/fA00)+fC; - } - } - else // region 1 - { - fNumer = fA11 + fB1 - fA01 - fB0; - if(fNumer <= 0.0f) - { - fSqrDist = fA11+2.0f*fB1+fC; - } - else - { - fDenom = fA00-2.0f*fA01+fA11; - if(fNumer >= fDenom) - { - fSqrDist = fA00+2.0f*fB0+fC; - } - else - { - fS = fNumer/fDenom; - fT = 1.0f - fS; - fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; - } - } - } - } - return fabsf(fSqrDist); -} - -static float OPC_SegmentSegmentSqrDist(const IceSegment& rkSeg0, const IceSegment& rkSeg1) -{ - // Hook - IcePoint rkSeg0Direction = rkSeg0.ComputeDirection(); - IcePoint rkSeg1Direction = rkSeg1.ComputeDirection(); - - IcePoint kDiff = rkSeg0.mP0 - rkSeg1.mP0; - float fA00 = rkSeg0Direction.SquareMagnitude(); - float fA01 = -rkSeg0Direction.Dot(rkSeg1Direction); - float fA11 = rkSeg1Direction.SquareMagnitude(); - float fB0 = kDiff.Dot(rkSeg0Direction); - float fC = kDiff.SquareMagnitude(); - float fDet = fabsf(fA00*fA11-fA01*fA01); - - float fB1, fS, fT, fSqrDist, fTmp; - - if(fDet>=gs_fTolerance) - { - // line segments are not parallel - fB1 = -kDiff.Dot(rkSeg1Direction); - fS = fA01*fB1-fA11*fB0; - fT = fA01*fB0-fA00*fB1; - - if(fS >= 0.0f) - { - if(fS <= fDet) - { - if(fT >= 0.0f) - { - if(fT <= fDet) // region 0 (interior) - { - // minimum at two interior points of 3D lines - float fInvDet = 1.0f/fDet; - fS *= fInvDet; - fT *= fInvDet; - fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; - } - else // region 3 (side) - { - fTmp = fA01+fB0; - if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; - else if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); - else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; - } - } - else // region 7 (side) - { - if(fB0>=0.0f) fSqrDist = fC; - else if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; - else fSqrDist = fB0*(-fB0/fA00)+fC; - } - } - else - { - if ( fT >= 0.0 ) - { - if ( fT <= fDet ) // region 1 (side) - { - fTmp = fA01+fB1; - if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; - else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); - else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; - } - else // region 2 (corner) - { - fTmp = fA01+fB0; - if ( -fTmp <= fA00 ) - { - if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; - else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; - } - else - { - fTmp = fA01+fB1; - if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; - else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); - else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; - } - } - } - else // region 8 (corner) - { - if ( -fB0 < fA00 ) - { - if(fB0>=0.0f) fSqrDist = fC; - else fSqrDist = fB0*(-fB0/fA00)+fC; - } - else - { - fTmp = fA01+fB1; - if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; - else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); - else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; - } - } - } - } - else - { - if ( fT >= 0.0f ) - { - if ( fT <= fDet ) // region 5 (side) - { - if(fB1>=0.0f) fSqrDist = fC; - else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; - else fSqrDist = fB1*(-fB1/fA11)+fC; - } - else // region 4 (corner) - { - fTmp = fA01+fB0; - if ( fTmp < 0.0f ) - { - if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); - else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; - } - else - { - if(fB1>=0.0f) fSqrDist = fC; - else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; - else fSqrDist = fB1*(-fB1/fA11)+fC; - } - } - } - else // region 6 (corner) - { - if ( fB0 < 0.0f ) - { - if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; - else fSqrDist = fB0*(-fB0/fA00)+fC; - } - else - { - if(fB1>=0.0f) fSqrDist = fC; - else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; - else fSqrDist = fB1*(-fB1/fA11)+fC; - } - } - } - } - else - { - // line segments are parallel - if ( fA01 > 0.0f ) - { - // direction vectors form an obtuse angle - if ( fB0 >= 0.0f ) - { - fSqrDist = fC; - } - else if ( -fB0 <= fA00 ) - { - fSqrDist = fB0*(-fB0/fA00)+fC; - } - else - { - fB1 = -kDiff.Dot(rkSeg1Direction); - fTmp = fA00+fB0; - if ( -fTmp >= fA01 ) - { - fSqrDist = fA00+fA11+fC+2.0f*(fA01+fB0+fB1); - } - else - { - fT = -fTmp/fA01; - fSqrDist = fA00+2.0f*fB0+fC+fT*(fA11*fT+2.0f*(fA01+fB1)); - } - } - } - else - { - // direction vectors form an acute angle - if ( -fB0 >= fA00 ) - { - fSqrDist = fA00+2.0f*fB0+fC; - } - else if ( fB0 <= 0.0f ) - { - fSqrDist = fB0*(-fB0/fA00)+fC; - } - else - { - fB1 = -kDiff.Dot(rkSeg1Direction); - if ( fB0 >= -fA01 ) - { - fSqrDist = fA11+2.0f*fB1+fC; - } - else - { - fT = -fB0/fA01; - fSqrDist = fC+fT*(2.0f*fB1+fA11*fT); - } - } - } - } - return fabsf(fSqrDist); -} - -inline_ float OPC_SegmentRaySqrDist(const IceSegment& rkSeg0, const Ray& rkSeg1) -{ - return OPC_SegmentSegmentSqrDist(rkSeg0, IceSegment(rkSeg1.mOrig, rkSeg1.mOrig + rkSeg1.mDir)); -} - -static float OPC_SegmentTriangleSqrDist(const IceSegment& segment, const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) -{ - // Hook - const IcePoint TriEdge0 = p1 - p0; - const IcePoint TriEdge1 = p2 - p0; - - const IcePoint& rkSegOrigin = segment.GetOrigin(); - IcePoint rkSegDirection = segment.ComputeDirection(); - - IcePoint kDiff = p0 - rkSegOrigin; - float fA00 = rkSegDirection.SquareMagnitude(); - float fA01 = -rkSegDirection.Dot(TriEdge0); - float fA02 = -rkSegDirection.Dot(TriEdge1); - float fA11 = TriEdge0.SquareMagnitude(); - float fA12 = TriEdge0.Dot(TriEdge1); - float fA22 = TriEdge1.Dot(TriEdge1); - float fB0 = -kDiff.Dot(rkSegDirection); - float fB1 = kDiff.Dot(TriEdge0); - float fB2 = kDiff.Dot(TriEdge1); - float fCof00 = fA11*fA22-fA12*fA12; - float fCof01 = fA02*fA12-fA01*fA22; - float fCof02 = fA01*fA12-fA02*fA11; - float fDet = fA00*fCof00+fA01*fCof01+fA02*fCof02; - - Ray kTriSeg; - IcePoint kPt; - float fSqrDist, fSqrDist0; - - if(fabsf(fDet)>=gs_fTolerance) - { - float fCof11 = fA00*fA22-fA02*fA02; - float fCof12 = fA02*fA01-fA00*fA12; - float fCof22 = fA00*fA11-fA01*fA01; - float fInvDet = 1.0f/fDet; - float fRhs0 = -fB0*fInvDet; - float fRhs1 = -fB1*fInvDet; - float fRhs2 = -fB2*fInvDet; - - float fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2; - float fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2; - float fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2; - - if ( fR < 0.0f ) - { - if ( fS+fT <= 1.0f ) - { - if ( fS < 0.0f ) - { - if ( fT < 0.0f ) // region 4m - { - // min on face s=0 or t=0 or r=0 - kTriSeg.mOrig = p0; - kTriSeg.mDir = TriEdge1; - fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); - kTriSeg.mOrig = p0; - kTriSeg.mDir = TriEdge0; - fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); - if(fSqrDist0 1 - { - if ( fS+fT <= 1.0f ) - { - if ( fS < 0.0f ) - { - if ( fT < 0.0f ) // region 4p - { - // min on face s=0 or t=0 or r=1 - kTriSeg.mOrig = p0; - kTriSeg.mDir = TriEdge1; - fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); - kTriSeg.mOrig = p0; - kTriSeg.mDir = TriEdge0; - fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); - if(fSqrDist0GetTriangle(triangle_index); - * // Setup pointers to vertices for the collision system - * triangle.Vertex[0] = MyMesh->GetVertex(Tri->mVRef[0]); - * triangle.Vertex[1] = MyMesh->GetVertex(Tri->mVRef[1]); - * triangle.Vertex[2] = MyMesh->GetVertex(Tri->mVRef[2]); - * } - * - * // Setup callbacks - * MeshInterface0->SetCallback(ColCallback, udword(Mesh0)); - * MeshInterface1->SetCallback(ColCallback, udword(Mesh1)); - * \endcode - * - * Of course, you should make this callback as fast as possible. And you're also not supposed - * to modify the geometry *after* the collision trees have been built. The alternative was to - * store the geometry & topology in the collision system as well (as in RAPID) but we have found - * this approach to waste a lot of ram in many cases. - * - * - * POINTERS: - * - * If you're internally using the following canonical structures: - * - a vertex made of three 32-bits floating IcePoint values - * - a triangle made of three 32-bits integer vertex references - * ...then you may want to use pointers instead of callbacks. This is the same, except OPCODE will directly - * use provided pointers to access the topology and geometry, without using a callback. It might be faster, - * but probably not as safe. Pointers have been introduced in OPCODE 1.2. - * - * Ex: - * - * \code - * // Setup pointers - * MeshInterface0->SetPointers(Mesh0->GetFaces(), Mesh0->GetVerts()); - * MeshInterface1->SetPointers(Mesh1->GetFaces(), Mesh1->GetVerts()); - * \endcode - * - * - * STRIDES: - * - * If your vertices are D3D-like entities interleaving a position, a normal and/or texture coordinates - * (i.e. if your vertices are FVFs), you might want to use a vertex stride to skip extra data OPCODE - * doesn't need. Using a stride shouldn't be notably slower than not using it, but it might increase - * cache misses. Please also note that you *shouldn't* read from AGP or video-memory buffers ! - * - * - * In any case, compilation flags are here to select callbacks/pointers/strides at compile time, so - * choose what's best for your application. All of this has been wrapped into this MeshInterface. - * - * \class MeshInterface - * \author Pierre Terdiman - * \version 1.3 - * \date November, 27, 2002 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -MeshInterface::MeshInterface() : -#ifdef OPC_USE_CALLBACKS - mUserData (null), - mObjCallback (null), -#else - mTris (null), - mVerts (null), - #ifdef OPC_USE_STRIDE - mTriStride (sizeof(IndexedTriangle)), - mVertexStride (sizeof(IcePoint)), - #endif -#endif - mNbTris (0), - mNbVerts (0) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -MeshInterface::~MeshInterface() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks the mesh interface is valid, i.e. things have been setup correctly. - * \return true if valid - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool MeshInterface::IsValid() const -{ - if(!mNbTris || !mNbVerts) return false; -#ifdef OPC_USE_CALLBACKS - if(!mObjCallback) return false; -#else - if(!mTris || !mVerts) return false; -#endif - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks the mesh itself is valid. - * Currently we only look for degenerate faces. - * \return number of degenerate faces - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -udword MeshInterface::CheckTopology() const -{ - // Check topology. If the model contains degenerate faces, collision report can be wrong in some cases. - // e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner - // you can try this: www.codercorner.com/Consolidation.zip - - udword NbDegenerate = 0; - - VertexPointers VP; - - // Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for - // redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides). - for(udword i=0;i= 0.0f; - } - }; - -#ifdef OPC_USE_CALLBACKS - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * User-callback, called by OPCODE to request vertices from the app. - * \param triangle_index [in] face index for which the system is requesting the vertices - * \param triangle [out] triangle's vertices (must be provided by the user) - * \param user_data [in] user-defined data from SetCallback() - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - typedef void (*RequestCallback) (udword triangle_index, VertexPointers& triangle, void* user_data); -#endif - - class OPCODE_API MeshInterface - { - public: - // Constructor / Destructor - MeshInterface(); - ~MeshInterface(); - // Common settings - inline_ udword GetNbTriangles() const { return mNbTris; } - inline_ udword GetNbVertices() const { return mNbVerts; } - inline_ void SetNbTriangles(udword nb) { mNbTris = nb; } - inline_ void SetNbVertices(udword nb) { mNbVerts = nb; } - -#ifdef OPC_USE_CALLBACKS - // Callback settings - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index. - * \param callback [in] user-defined callback - * \param user_data [in] user-defined data - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool SetCallback(RequestCallback callback, void* user_data); - inline_ void* GetUserData() const { return mUserData; } - inline_ RequestCallback GetCallback() const { return mObjCallback; } -#else - // Pointers settings - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object. - * \param tris [in] pointer to triangles - * \param verts [in] pointer to vertices - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool SetPointers(const IndexedTriangle* tris, const IcePoint* verts); - inline_ const IndexedTriangle* GetTris() const { return mTris; } - inline_ const IcePoint* GetVerts() const { return mVerts; } - - #ifdef OPC_USE_STRIDE - // Strides settings - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Strides control - * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices. - * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(IcePoint) bytes are used to get vertex position. - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool SetStrides(udword tri_stride=sizeof(IndexedTriangle), udword vertex_stride=sizeof(IcePoint)); - inline_ udword GetTriStride() const { return mTriStride; } - inline_ udword GetVertexStride() const { return mVertexStride; } - #endif -#endif - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Fetches a triangle given a triangle index. - * \param vp [out] required triangle's vertex pointers - * \param index [in] triangle index - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void GetTriangle(VertexPointers& vp, udword index) const - { -#ifdef OPC_USE_CALLBACKS - (mObjCallback)(index, vp, mUserData); -#else - #ifdef OPC_USE_STRIDE - const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride); - vp.Vertex[0] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[0] * mVertexStride); - vp.Vertex[1] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[1] * mVertexStride); - vp.Vertex[2] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[2] * mVertexStride); - #else - const IndexedTriangle* T = &mTris[index]; - vp.Vertex[0] = &mVerts[T->mVRef[0]]; - vp.Vertex[1] = &mVerts[T->mVRef[1]]; - vp.Vertex[2] = &mVerts[T->mVRef[2]]; - #endif -#endif - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Remaps client's mesh according to a permutation. - * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles) - * \param permutation [in] list of triangle indices - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool RemapClient(udword nb_indices, const udword* permutation) const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks the mesh interface is valid, i.e. things have been setup correctly. - * \return true if valid - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool IsValid() const; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Checks the mesh itself is valid. - * Currently we only look for degenerate faces. - * \return number of degenerate faces - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - udword CheckTopology() const; - private: - - udword mNbTris; //!< Number of triangles in the input model - udword mNbVerts; //!< Number of vertices in the input model -#ifdef OPC_USE_CALLBACKS - // User callback - void* mUserData; //!< User-defined data sent to callback - RequestCallback mObjCallback; //!< Object callback -#else - // User pointers - const IndexedTriangle* mTris; //!< Array of indexed triangles - const IcePoint* mVerts; //!< Array of vertices - #ifdef OPC_USE_STRIDE - udword mTriStride; //!< Possible triangle stride in bytes [Opcode 1.3] - udword mVertexStride; //!< Possible vertex stride in bytes [Opcode 1.3] - #endif -#endif - }; - -#endif //__OPC_MESHINTERFACE_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_Model.cpp b/contrib/Opcode/OPC_Model.cpp deleted file mode 100644 index a9e660c..0000000 --- a/contrib/Opcode/OPC_Model.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for OPCODE models. - * \file OPC_Model.cpp - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * The main collision wrapper, for all trees. Supported trees are: - * - Normal trees (2*N-1 nodes, full size) - * - No-leaf trees (N-1 nodes, full size) - * - Quantized trees (2*N-1 nodes, half size) - * - Quantized no-leaf trees (N-1 nodes, half size) - * - * Usage: - * - * 1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp). - * Keep it around in your app, since a pointer to this interface is saved internally and - * used until you release the collision structures. - * - * 2) Build a Model using a creation structure: - * - * \code - * Model Sample; - * - * OPCODECREATE OPCC; - * OPCC.IMesh = ...; - * OPCC.Rules = ...; - * OPCC.NoLeaf = ...; - * OPCC.Quantized = ...; - * OPCC.KeepOriginal = ...; - * bool Status = Sample.Build(OPCC); - * \endcode - * - * 3) Create a tree collider and set it up: - * - * \code - * AABBTreeCollider TC; - * TC.SetFirstContact(...); - * TC.SetFullBoxBoxTest(...); - * TC.SetFullPrimBoxTest(...); - * TC.SetTemporalCoherence(...); - * \endcode - * - * 4) Perform a collision query - * - * \code - * // Setup cache - * static BVTCache ColCache; - * ColCache.Model0 = &Model0; - * ColCache.Model1 = &Model1; - * - * // Collision query - * bool IsOk = TC.Collide(ColCache, World0, World1); - * - * // Get collision status => if true, objects overlap - * BOOL Status = TC.GetContactStatus(); - * - * // Number of colliding pairs and list of pairs - * udword NbPairs = TC.GetNbPairs(); - * const Pair* p = TC.GetPairs() - * \endcode - * - * 5) Stats - * - * \code - * Model0.GetUsedBytes() = number of bytes used for this collision tree - * TC.GetNbBVBVTests() = number of BV-BV overlap tests performed during last query - * TC.GetNbPrimPrimTests() = number of Triangle-Triangle overlap tests performed during last query - * TC.GetNbBVPrimTests() = number of Triangle-BV overlap tests performed during last query - * \endcode - * - * \class Model - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Model::Model() -{ -#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! - mHull = null; -#endif // __MESHMERIZER_H__ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Model::~Model() -{ - Release(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Releases the model. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Model::Release() -{ - ReleaseBase(); -#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! - DELETESINGLE(mHull); -#endif // __MESHMERIZER_H__ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds a collision model. - * \param create [in] model creation structure - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool Model::Build(const OPCODECREATE& create) -{ - // 1) Checkings - if(!create.mIMesh || !create.mIMesh->IsValid()) return false; - - // For this model, we only support complete trees - if (create.mSettings.mLimit != 1) return SetIceError; // ("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null); - - // Look for degenerate faces. - udword NbDegenerate = create.mIMesh->CheckTopology(); - if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); - // We continue nonetheless.... - - Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam] - - // 1-1) Setup mesh interface automatically [Opcode 1.3] - SetMeshInterface(create.mIMesh); - - // Special case for 1-triangle meshes [Opcode 1.3] - udword NbTris = create.mIMesh->GetNbTriangles(); - if(NbTris==1) - { - // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway. - // It's a waste to use a "model" for this but at least it will work. - mModelCode |= OPC_SINGLE_NODE; - return true; - } - - // 2) Build a generic AABB Tree. - mSource = new AABBTree; - CHECKALLOC(mSource); - - // 2-1) Setup a builder. Our primitives here are triangles from input mesh, - // so we use an AABBTreeOfTrianglesBuilder..... - { - AABBTreeOfTrianglesBuilder TB; - TB.mIMesh = create.mIMesh; - TB.mSettings = create.mSettings; - TB.mNbPrimitives = NbTris; - if(!mSource->Build(&TB)) return false; - } - - // 3) Create an optimized tree according to user-settings - if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false; - - // 3-2) Create optimized tree - if(!mTree->Build(mSource)) return false; - - // 3-3) Delete generic tree if needed - if(!create.mKeepOriginal) DELETESINGLE(mSource); - -#ifdef __MESHMERIZER_H__ - // 4) Convex hull - if(create.mCollisionHull) - { - // Create hull - mHull = new CollisionHull; - CHECKALLOC(mHull); - - CONVEXHULLCREATE CHC; - // ### doesn't work with strides - CHC.NbVerts = create.mIMesh->GetNbVertices(); - CHC.Vertices = create.mIMesh->GetVerts(); - CHC.UnifyNormals = true; - CHC.ReduceVertices = true; - CHC.WordFaces = false; - mHull->Compute(CHC); - } -#endif // __MESHMERIZER_H__ - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Gets the number of bytes used by the tree. - * \return amount of bytes used - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -udword Model::GetUsedBytes() const -{ - if(!mTree) return 0; - return mTree->GetUsedBytes(); -} diff --git a/contrib/Opcode/OPC_Model.h b/contrib/Opcode/OPC_Model.h deleted file mode 100644 index 1b39e60..0000000 --- a/contrib/Opcode/OPC_Model.h +++ /dev/null @@ -1,65 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for OPCODE models. - * \file OPC_Model.h - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_MODEL_H__ -#define __OPC_MODEL_H__ - - class OPCODE_API Model : public BaseModel - { - public: - // Constructor/Destructor - Model(); - virtual ~Model(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Builds a collision model. - * \param create [in] model creation structure - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(BaseModel) bool Build(const OPCODECREATE& create); - -#ifdef __MESHMERIZER_H__ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the collision hull. - * \return the collision hull if it exists - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ const CollisionHull* GetHull() const { return mHull; } -#endif // __MESHMERIZER_H__ - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the number of bytes used by the tree. - * \return amount of bytes used - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(BaseModel) udword GetUsedBytes() const; - - private: -#ifdef __MESHMERIZER_H__ - CollisionHull* mHull; //!< Possible convex hull -#endif // __MESHMERIZER_H__ - // Internal methods - void Release(); - }; - -#endif //__OPC_MODEL_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_OBBCollider.cpp b/contrib/Opcode/OPC_OBBCollider.cpp deleted file mode 100644 index 8761fce..0000000 --- a/contrib/Opcode/OPC_OBBCollider.cpp +++ /dev/null @@ -1,767 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for an OBB collider. - * \file OPC_OBBCollider.cpp - * \author Pierre Terdiman - * \date January, 1st, 2002 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains an OBB-vs-tree collider. - * - * \class OBBCollider - * \author Pierre Terdiman - * \version 1.3 - * \date January, 1st, 2002 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -#include "OPC_BoxBoxOverlap.h" -#include "OPC_TriBoxOverlap.h" - -#define SET_CONTACT(prim_index, flag) \ - /* Set contact status */ \ - mFlags |= flag; \ - mTouchedPrimitives->Add(prim_index); - -//! OBB-triangle test -#define OBB_PRIM(prim_index, flag) \ - /* Request vertices from the app */ \ - VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ - /* Transform them in a common space */ \ - TransformPoint(mLeafVerts[0], *VP.Vertex[0], mRModelToBox, mTModelToBox); \ - TransformPoint(mLeafVerts[1], *VP.Vertex[1], mRModelToBox, mTModelToBox); \ - TransformPoint(mLeafVerts[2], *VP.Vertex[2], mRModelToBox, mTModelToBox); \ - /* Perform triangle-box overlap test */ \ - if(TriBoxOverlap()) \ - { \ - SET_CONTACT(prim_index, flag) \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -OBBCollider::OBBCollider() : mFullBoxBoxTest(true) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -OBBCollider::~OBBCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Validates current settings. You should call this method after all the settings and callbacks have been defined. - * \return null if everything is ok, else a string describing the problem - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -const char* OBBCollider::ValidateSettings() -{ - if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; - - return VolumeCollider::ValidateSettings(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] a box cache - * \param box [in] collision OBB in local space - * \param model [in] Opcode model to collide with - * \param worldb [in] OBB's world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool OBBCollider::Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb, const Matrix4x4* worldm) -{ - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, box, worldb, worldm)) return true; - - if(!model.HasLeafNodes()) - { - if(model.IsQuantized()) - { - const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - } - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Initializes a collision query : - * - reset stats & contact status - * - setup matrices - * - check temporal coherence - * - * \param cache [in/out] a box cache - * \param box [in] obb in local space - * \param worldb [in] obb's world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return TRUE if we can return immediately - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOL OBBCollider::InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb, const Matrix4x4* worldm) -{ - // 1) Call the base method - VolumeCollider::InitQuery(); - - // 2) Compute obb in world space - mBoxExtents = box.mExtents; - - Matrix4x4 WorldB; - - if(worldb) - { - WorldB = Matrix4x4( box.mRot * Matrix3x3(*worldb) ); - WorldB.SetTrans(box.mCenter * *worldb); - } - else - { - WorldB = box.mRot; - WorldB.SetTrans(box.mCenter); - } - - // Setup matrices - Matrix4x4 InvWorldB; - InvertPRMatrix(InvWorldB, WorldB); - - if(worldm) - { - Matrix4x4 InvWorldM; - InvertPRMatrix(InvWorldM, *worldm); - - Matrix4x4 WorldBtoM = WorldB * InvWorldM; - Matrix4x4 WorldMtoB = *worldm * InvWorldB; - - mRModelToBox = WorldMtoB; WorldMtoB.GetTrans(mTModelToBox); - mRBoxToModel = WorldBtoM; WorldBtoM.GetTrans(mTBoxToModel); - } - else - { - mRModelToBox = InvWorldB; InvWorldB.GetTrans(mTModelToBox); - mRBoxToModel = WorldB; WorldB.GetTrans(mTBoxToModel); - } - - // 3) Setup destination pointer - mTouchedPrimitives = &cache.TouchedPrimitives; - - // 4) Special case: 1-triangle meshes [Opcode 1.3] - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - if(!SkipPrimitiveTests()) - { - // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. - mTouchedPrimitives->Reset(); - - // Perform overlap test between the unique triangle and the box (and set contact status if needed) - OBB_PRIM(udword(0), OPC_CONTACT) - - // Return immediately regardless of status - return TRUE; - } - } - - // 5) Check temporal coherence: - if(TemporalCoherenceEnabled()) - { - // Here we use temporal coherence - // => check results from previous frame before performing the collision query - if(FirstContactEnabled()) - { - // We're only interested in the first contact found => test the unique previously touched face - if(mTouchedPrimitives->GetNbEntries()) - { - // Get index of previously touched face = the first entry in the array - udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); - - // Then reset the array: - // - if the overlap test below is successful, the index we'll get added back anyway - // - if it isn't, then the array should be reset anyway for the normal query - mTouchedPrimitives->Reset(); - - // Perform overlap test between the cached triangle and the box (and set contact status if needed) - OBB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) - - // Return immediately if possible - if(GetContactStatus()) return TRUE; - } - // else no face has been touched during previous query - // => we'll have to perform a normal query - } - else - { - // ### rewrite this - OBB TestBox(mTBoxToModel, mBoxExtents, mRBoxToModel); - - // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): - if(IsCacheValid(cache) && TestBox.IsInside(cache.FatBox)) - { - // - if N is included in P, return previous list - // => we simply leave the list (mTouchedFaces) unchanged - - // Set contact status if needed - if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; - - // In any case we don't need to do a query - return TRUE; - } - else - { - // - else do the query using a fat N - - // Reset cache since we'll about to perform a real query - mTouchedPrimitives->Reset(); - - // Make a fat box so that coherence will work for subsequent frames - TestBox.mExtents *= cache.FatCoeff; - mBoxExtents *= cache.FatCoeff; - - // Update cache with query data (signature for cached faces) - cache.FatBox = TestBox; - } - } - } - else - { - // Here we don't use temporal coherence => do a normal query - mTouchedPrimitives->Reset(); - } - - // Now we can precompute box-box data - - // Precompute absolute box-to-model rotation matrix - for(udword i=0;i<3;i++) - { - for(udword j=0;j<3;j++) - { - // Epsilon value prevents floating-IcePoint inaccuracies (strategy borrowed from RAPID) - mAR.m[i][j] = 1e-6f + fabsf(mRBoxToModel.m[i][j]); - } - } - - // Precompute bounds for box-in-box test - mB0 = mBoxExtents - mTModelToBox; - mB1 = - mBoxExtents - mTModelToBox; - - // Precompute box-box data - Courtesy of Erwin de Vries - mBBx1 = mBoxExtents.x*mAR.m[0][0] + mBoxExtents.y*mAR.m[1][0] + mBoxExtents.z*mAR.m[2][0]; - mBBy1 = mBoxExtents.x*mAR.m[0][1] + mBoxExtents.y*mAR.m[1][1] + mBoxExtents.z*mAR.m[2][1]; - mBBz1 = mBoxExtents.x*mAR.m[0][2] + mBoxExtents.y*mAR.m[1][2] + mBoxExtents.z*mAR.m[2][2]; - - mBB_1 = mBoxExtents.y*mAR.m[2][0] + mBoxExtents.z*mAR.m[1][0]; - mBB_2 = mBoxExtents.x*mAR.m[2][0] + mBoxExtents.z*mAR.m[0][0]; - mBB_3 = mBoxExtents.x*mAR.m[1][0] + mBoxExtents.y*mAR.m[0][0]; - mBB_4 = mBoxExtents.y*mAR.m[2][1] + mBoxExtents.z*mAR.m[1][1]; - mBB_5 = mBoxExtents.x*mAR.m[2][1] + mBoxExtents.z*mAR.m[0][1]; - mBB_6 = mBoxExtents.x*mAR.m[1][1] + mBoxExtents.y*mAR.m[0][1]; - mBB_7 = mBoxExtents.y*mAR.m[2][2] + mBoxExtents.z*mAR.m[1][2]; - mBB_8 = mBoxExtents.x*mAR.m[2][2] + mBoxExtents.z*mAR.m[0][2]; - mBB_9 = mBoxExtents.x*mAR.m[1][2] + mBoxExtents.y*mAR.m[0][2]; - - return FALSE; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks the OBB completely contains the box. In which case we can end the query sooner. - * \param bc [in] box center - * \param be [in] box extents - * \return true if the OBB contains the whole box - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL OBBCollider::OBBContainsBox(const IcePoint& bc, const IcePoint& be) -{ - // I assume if all 8 box vertices are inside the OBB, so does the whole box. - // Sounds ok but maybe there's a better way? -/* -#define TEST_PT(a,b,c) \ - p.x=a; p.y=b; p.z=c; p+=bc; \ - f = p.x * mRModelToBox.m[0][0] + p.y * mRModelToBox.m[1][0] + p.z * mRModelToBox.m[2][0]; if(f>mB0.x || fmB0.y || fmB0.z || f NCx-NEx) return FALSE; - - float NCy = bc.x * mRModelToBox.m[0][1] + bc.y * mRModelToBox.m[1][1] + bc.z * mRModelToBox.m[2][1]; - float NEy = fabsf(mRModelToBox.m[0][1] * be.x) + fabsf(mRModelToBox.m[1][1] * be.y) + fabsf(mRModelToBox.m[2][1] * be.z); - - if(mB0.y < NCy+NEy) return FALSE; - if(mB1.y > NCy-NEy) return FALSE; - - float NCz = bc.x * mRModelToBox.m[0][2] + bc.y * mRModelToBox.m[1][2] + bc.z * mRModelToBox.m[2][2]; - float NEz = fabsf(mRModelToBox.m[0][2] * be.x) + fabsf(mRModelToBox.m[1][2] * be.y) + fabsf(mRModelToBox.m[2][2] * be.z); - - if(mB0.z < NCz+NEz) return FALSE; - if(mB1.z > NCz-NEz) return FALSE; - - return TRUE; -} - -#define TEST_BOX_IN_OBB(center, extents) \ - if(OBBContainsBox(center, extents)) \ - { \ - /* Set contact status */ \ - mFlags |= OPC_CONTACT; \ - _Dump(node); \ - return; \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBBCollider::_Collide(const AABBCollisionNode* node) -{ - // Perform OBB-AABB overlap test - if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; - - TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->IsLeaf()) - { - OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos()); - - if(ContactFound()) return; - - _Collide(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) -{ - // Perform OBB-AABB overlap test - if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; - - TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBBCollider::_Collide(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform OBB-AABB overlap test - if(!BoxBoxOverlap(Extents, Center)) return; - - TEST_BOX_IN_OBB(Center, Extents) - - if(node->IsLeaf()) - { - OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos()); - - if(ContactFound()) return; - - _Collide(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform OBB-AABB overlap test - if(!BoxBoxOverlap(Extents, Center)) return; - - TEST_BOX_IN_OBB(Center, Extents) - - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBBCollider::_Collide(const AABBNoLeafNode* node) -{ - // Perform OBB-AABB overlap test - if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; - - TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) -{ - // Perform OBB-AABB overlap test - if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; - - TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBBCollider::_Collide(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform OBB-AABB overlap test - if(!BoxBoxOverlap(Extents, Center)) return; - - TEST_BOX_IN_OBB(Center, Extents) - - if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform OBB-AABB overlap test - if(!BoxBoxOverlap(Extents, Center)) return; - - TEST_BOX_IN_OBB(Center, Extents) - - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg()); -} - - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridOBBCollider::HybridOBBCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridOBBCollider::~HybridOBBCollider() -{ -} - -bool HybridOBBCollider::Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb, const Matrix4x4* worldm) -{ - // We don't want primitive tests here! - mFlags |= OPC_NO_PRIMITIVE_TESTS; - - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, box, worldb, worldm)) return true; - - // Special case for 1-leaf trees - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles - udword Nb = mIMesh->GetNbTriangles(); - - // Loop through all triangles - for(udword i=0;imCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - } - - // We only have a list of boxes so far - if(GetContactStatus()) - { - // Reset contact status, since it currently only reflects collisions with leaf boxes - Collider::InitQuery(); - - // Change dest container so that we can use built-in overlap tests and get collided primitives - cache.TouchedPrimitives.Reset(); - mTouchedPrimitives = &cache.TouchedPrimitives; - - // Read touched leaf boxes - udword Nb = mTouchedBoxes.GetNbEntries(); - const udword* Touched = mTouchedBoxes.GetEntries(); - - const LeafTriangles* LT = model.GetLeafTriangles(); - const udword* Indices = model.GetIndices(); - - // Loop through touched leaves - while(Nb--) - { - const LeafTriangles& CurrentLeaf = LT[*Touched++]; - - // Each leaf box has a set of triangles - udword NbTris = CurrentLeaf.GetNbTriangles(); - if(Indices) - { - const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; - - // Loop through triangles and test each of them - while(NbTris--) - { - udword TriangleIndex = *T++; - OBB_PRIM(TriangleIndex, OPC_CONTACT) - } - } - else - { - udword BaseIndex = CurrentLeaf.GetTriangleIndex(); - - // Loop through triangles and test each of them - while(NbTris--) - { - udword TriangleIndex = BaseIndex++; - OBB_PRIM(TriangleIndex, OPC_CONTACT) - } - } - } - } - - return true; -} diff --git a/contrib/Opcode/OPC_OBBCollider.h b/contrib/Opcode/OPC_OBBCollider.h deleted file mode 100644 index 9753384..0000000 --- a/contrib/Opcode/OPC_OBBCollider.h +++ /dev/null @@ -1,142 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for an OBB collider. - * \file OPC_OBBCollider.h - * \author Pierre Terdiman - * \date January, 1st, 2002 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_OBBCOLLIDER_H__ -#define __OPC_OBBCOLLIDER_H__ - - struct OPCODE_API OBBCache : VolumeCache - { - OBBCache() : FatCoeff(1.1f) - { - FatBox.mCenter.Zero(); - FatBox.mExtents.Zero(); - FatBox.mRot.Identity(); - } - - // Cached faces signature - OBB FatBox; //!< Box used when performing the query resulting in cached faces - // User settings - float FatCoeff; //!< extents multiplier used to create a fat box - }; - - class OPCODE_API OBBCollider : public VolumeCollider - { - public: - // Constructor / Destructor - OBBCollider(); - virtual ~OBBCollider(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] a box cache - * \param box [in] collision OBB in local space - * \param model [in] Opcode model to collide with - * \param worldb [in] OBB's world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); - - // Settings - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Settings: select between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) - * \param flag [in] true for full tests, false for coarse tests - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } - - // Settings - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. - * \return null if everything is ok, else a string describing the problem - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(Collider) const char* ValidateSettings(); - - protected: - // Precomputed data - Matrix3x3 mAR; //!< Absolute rotation matrix - Matrix3x3 mRModelToBox; //!< Rotation from model space to obb space - Matrix3x3 mRBoxToModel; //!< Rotation from obb space to model space - IcePoint mTModelToBox; //!< Translation from model space to obb space - IcePoint mTBoxToModel; //!< Translation from obb space to model space - - IcePoint mBoxExtents; - IcePoint mB0; //!< - mTModelToBox + mBoxExtents - IcePoint mB1; //!< - mTModelToBox - mBoxExtents - - float mBBx1; - float mBBy1; - float mBBz1; - - float mBB_1; - float mBB_2; - float mBB_3; - float mBB_4; - float mBB_5; - float mBB_6; - float mBB_7; - float mBB_8; - float mBB_9; - - // Leaf description - IcePoint mLeafVerts[3]; //!< Triangle vertices - // Settings - bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) - // Internal methods - void _Collide(const AABBCollisionNode* node); - void _Collide(const AABBNoLeafNode* node); - void _Collide(const AABBQuantizedNode* node); - void _Collide(const AABBQuantizedNoLeafNode* node); - void _CollideNoPrimitiveTest(const AABBCollisionNode* node); - void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); - void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); - void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); - // Overlap tests - inline_ BOOL OBBContainsBox(const IcePoint& bc, const IcePoint& be); - inline_ BOOL BoxBoxOverlap(const IcePoint& extents, const IcePoint& center); - inline_ BOOL TriBoxOverlap(); - // Init methods - BOOL InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); - }; - - class OPCODE_API HybridOBBCollider : public OBBCollider - { - public: - // Constructor / Destructor - HybridOBBCollider(); - virtual ~HybridOBBCollider(); - - bool Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); - protected: - Container mTouchedBoxes; - }; - -#endif // __OPC_OBBCOLLIDER_H__ diff --git a/contrib/Opcode/OPC_OptimizedTree.cpp b/contrib/Opcode/OPC_OptimizedTree.cpp deleted file mode 100644 index a84ac5a..0000000 --- a/contrib/Opcode/OPC_OptimizedTree.cpp +++ /dev/null @@ -1,782 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for optimized trees. Implements 4 trees: - * - normal - * - no leaf - * - quantized - * - no leaf / quantized - * - * \file OPC_OptimizedTree.cpp - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A standard AABB tree. - * - * \class AABBCollisionTree - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A no-leaf AABB tree. - * - * \class AABBNoLeafTree - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A quantized AABB tree. - * - * \class AABBQuantizedTree - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A quantized no-leaf AABB tree. - * - * \class AABBQuantizedNoLeafTree - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -//! Compilation flag: -//! - true to fix quantized boxes (i.e. make sure they enclose the original ones) -//! - false to see the effects of quantization errors (faster, but wrong results in some cases) -static bool gFixQuantized = true; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds an implicit tree from a standard one. An implicit tree is a complete tree (2*N-1 nodes) whose negative - * box pointers and primitive pointers have been made implicit, hence packing 3 pointers in one. - * - * Layout for implicit trees: - * Node: - * - box - * - data (32-bits value) - * - * if data's LSB = 1 => remaining bits are a primitive pointer - * else remaining bits are a P-node pointer, and N = P + 1 - * - * \relates AABBCollisionNode - * \fn _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) - * \param linear [in] base address of destination nodes - * \param box_id [in] index of destination node - * \param current_id [in] current running index - * \param current_node [in] current node from input tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static void _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) -{ - // Current node from input tree is "current_node". Must be flattened into "linear[boxid]". - - // Store the AABB - current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); - current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); - // Store remaining info - if(current_node->IsLeaf()) - { - // The input tree must be complete => i.e. one primitive/leaf - ASSERT(current_node->GetNbPrimitives()==1); - // Get the primitive index from the input tree - udword PrimitiveIndex = current_node->GetPrimitives()[0]; - // Setup box data as the primitive index, marked as leaf - linear[box_id].mData = (PrimitiveIndex<<1)|1; - } - else - { - // To make the negative one implicit, we must store P and N in successive order - udword PosID = current_id++; // Get a new id for positive child - udword NegID = current_id++; // Get a new id for negative child - // Setup box data as the forthcoming new P pointer - linear[box_id].mData = (udword)&linear[PosID]; - // Make sure it's not marked as leaf - ASSERT(!(linear[box_id].mData&1)); - // Recurse with new IDs - _BuildCollisionTree(linear, PosID, current_id, current_node->GetPos()); - _BuildCollisionTree(linear, NegID, current_id, current_node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds a "no-leaf" tree from a standard one. This is a tree whose leaf nodes have been removed. - * - * Layout for no-leaf trees: - * - * Node: - * - box - * - P pointer => a node (LSB=0) or a primitive (LSB=1) - * - N pointer => a node (LSB=0) or a primitive (LSB=1) - * - * \relates AABBNoLeafNode - * \fn _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) - * \param linear [in] base address of destination nodes - * \param box_id [in] index of destination node - * \param current_id [in] current running index - * \param current_node [in] current node from input tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static void _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) -{ - const AABBTreeNode* P = current_node->GetPos(); - const AABBTreeNode* N = current_node->GetNeg(); - // Leaf nodes here?! - ASSERT(P); - ASSERT(N); - // Internal node => keep the box - current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); - current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); - - if(P->IsLeaf()) - { - // The input tree must be complete => i.e. one primitive/leaf - ASSERT(P->GetNbPrimitives()==1); - // Get the primitive index from the input tree - udword PrimitiveIndex = P->GetPrimitives()[0]; - // Setup prev box data as the primitive index, marked as leaf - linear[box_id].mPosData = (PrimitiveIndex<<1)|1; - } - else - { - // Get a new id for positive child - udword PosID = current_id++; - // Setup box data - linear[box_id].mPosData = (udword)&linear[PosID]; - // Make sure it's not marked as leaf - ASSERT(!(linear[box_id].mPosData&1)); - // Recurse - _BuildNoLeafTree(linear, PosID, current_id, P); - } - - if(N->IsLeaf()) - { - // The input tree must be complete => i.e. one primitive/leaf - ASSERT(N->GetNbPrimitives()==1); - // Get the primitive index from the input tree - udword PrimitiveIndex = N->GetPrimitives()[0]; - // Setup prev box data as the primitive index, marked as leaf - linear[box_id].mNegData = (PrimitiveIndex<<1)|1; - } - else - { - // Get a new id for negative child - udword NegID = current_id++; - // Setup box data - linear[box_id].mNegData = (udword)&linear[NegID]; - // Make sure it's not marked as leaf - ASSERT(!(linear[box_id].mNegData&1)); - // Recurse - _BuildNoLeafTree(linear, NegID, current_id, N); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBCollisionTree::AABBCollisionTree() : mNodes(null) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBCollisionTree::~AABBCollisionTree() -{ - DELETEARRAY(mNodes); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds the collision tree from a generic AABB tree. - * \param tree [in] generic AABB tree - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBCollisionTree::Build(AABBTree* tree) -{ - // Checkings - if(!tree) return false; - // Check the input tree is complete - udword NbTriangles = tree->GetNbPrimitives(); - udword NbNodes = tree->GetNbNodes(); - if(NbNodes!=NbTriangles*2-1) return false; - - // Get nodes - if(mNbNodes!=NbNodes) // Same number of nodes => keep moving - { - mNbNodes = NbNodes; - DELETEARRAY(mNodes); - mNodes = new AABBCollisionNode[mNbNodes]; - CHECKALLOC(mNodes); - } - - // Build the tree - udword CurID = 1; - _BuildCollisionTree(mNodes, 0, CurID, tree); - ASSERT(CurID==mNbNodes); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Refits the collision tree after vertices have been modified. - * \param mesh_interface [in] mesh interface for current model - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBCollisionTree::Refit(const MeshInterface* mesh_interface) -{ - ASSERT(!"Not implemented since AABBCollisionTrees have twice as more nodes to refit as AABBNoLeafTrees!"); - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Walks the tree and call the user back for each node. - * \param callback [in] walking callback - * \param user_data [in] callback's user data - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBCollisionTree::Walk(GenericWalkingCallback callback, void* user_data) const -{ - if(!callback) return false; - - struct Local - { - static void _Walk(const AABBCollisionNode* current_node, GenericWalkingCallback callback, void* user_data) - { - if(!current_node || !(callback)(current_node, user_data)) return; - - if(!current_node->IsLeaf()) - { - _Walk(current_node->GetPos(), callback, user_data); - _Walk(current_node->GetNeg(), callback, user_data); - } - } - }; - Local::_Walk(mNodes, callback, user_data); - return true; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBNoLeafTree::AABBNoLeafTree() : mNodes(null) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBNoLeafTree::~AABBNoLeafTree() -{ - DELETEARRAY(mNodes); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds the collision tree from a generic AABB tree. - * \param tree [in] generic AABB tree - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBNoLeafTree::Build(AABBTree* tree) -{ - // Checkings - if(!tree) return false; - // Check the input tree is complete - udword NbTriangles = tree->GetNbPrimitives(); - udword NbNodes = tree->GetNbNodes(); - if(NbNodes!=NbTriangles*2-1) return false; - - // Get nodes - if(mNbNodes!=NbTriangles-1) // Same number of nodes => keep moving - { - mNbNodes = NbTriangles-1; - DELETEARRAY(mNodes); - mNodes = new AABBNoLeafNode[mNbNodes]; - CHECKALLOC(mNodes); - } - - // Build the tree - udword CurID = 1; - _BuildNoLeafTree(mNodes, 0, CurID, tree); - ASSERT(CurID==mNbNodes); - - return true; -} - -inline_ void ComputeMinMax(IcePoint& min, IcePoint& max, const VertexPointers& vp) -{ - // Compute triangle's AABB = a leaf box -#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much - min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); - max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); - - min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); - max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); - - min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); - max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); -#else - min = *vp.Vertex[0]; - max = *vp.Vertex[0]; - min.Min(*vp.Vertex[1]); - max.Max(*vp.Vertex[1]); - min.Min(*vp.Vertex[2]); - max.Max(*vp.Vertex[2]); -#endif -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Refits the collision tree after vertices have been modified. - * \param mesh_interface [in] mesh interface for current model - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface) -{ - // Checkings - if(!mesh_interface) return false; - - // Bottom-up update - VertexPointers VP; - IcePoint Min,Max; - IcePoint Min_,Max_; - udword Index = mNbNodes; - while(Index--) - { - AABBNoLeafNode& Current = mNodes[Index]; - - if(Current.HasPosLeaf()) - { - mesh_interface->GetTriangle(VP, Current.GetPosPrimitive()); - ComputeMinMax(Min, Max, VP); - } - else - { - const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; - CurrentBox.GetMin(Min); - CurrentBox.GetMax(Max); - } - - if(Current.HasNegLeaf()) - { - mesh_interface->GetTriangle(VP, Current.GetNegPrimitive()); - ComputeMinMax(Min_, Max_, VP); - } - else - { - const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; - CurrentBox.GetMin(Min_); - CurrentBox.GetMax(Max_); - } -#ifdef OPC_USE_FCOMI - Min.x = FCMin2(Min.x, Min_.x); - Max.x = FCMax2(Max.x, Max_.x); - Min.y = FCMin2(Min.y, Min_.y); - Max.y = FCMax2(Max.y, Max_.y); - Min.z = FCMin2(Min.z, Min_.z); - Max.z = FCMax2(Max.z, Max_.z); -#else - Min.Min(Min_); - Max.Max(Max_); -#endif - Current.mAABB.SetMinMax(Min, Max); - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Walks the tree and call the user back for each node. - * \param callback [in] walking callback - * \param user_data [in] callback's user data - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const -{ - if(!callback) return false; - - struct Local - { - static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data) - { - if(!current_node || !(callback)(current_node, user_data)) return; - - if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); - if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); - } - }; - Local::_Walk(mNodes, callback, user_data); - return true; -} - -// Quantization notes: -// - We could use the highest bits of mData to store some more quantized bits. Dequantization code -// would be slightly more complex, but number of overlap tests would be reduced (and anyhow those -// bits are currently wasted). Of course it's not possible if we move to 16 bits mData. -// - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion. -// - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some -// lazy-dequantization which may save some work in case of early exits). At the very least some -// muls could be saved by precomputing several more matrices. But maybe not worth the pain. -// - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has -// been scaled, for example. -// - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed -// number of quantization bits. Even better, could probably be best delta-encoded. - - -// Find max values. Some people asked why I wasn't simply using the first node. Well, I can't. -// I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal -// centers/extents in order to quantize them. The first node would only give a single center and -// a single extents. While extents would be the biggest, the center wouldn't. -#define FIND_MAX_VALUES \ - /* Get max values */ \ - IcePoint CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ - IcePoint EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ - for(udword i=0;iCMax.x) CMax.x = fabsf(Nodes[i].mAABB.mCenter.x); \ - if(fabsf(Nodes[i].mAABB.mCenter.y)>CMax.y) CMax.y = fabsf(Nodes[i].mAABB.mCenter.y); \ - if(fabsf(Nodes[i].mAABB.mCenter.z)>CMax.z) CMax.z = fabsf(Nodes[i].mAABB.mCenter.z); \ - if(fabsf(Nodes[i].mAABB.mExtents.x)>EMax.x) EMax.x = fabsf(Nodes[i].mAABB.mExtents.x); \ - if(fabsf(Nodes[i].mAABB.mExtents.y)>EMax.y) EMax.y = fabsf(Nodes[i].mAABB.mExtents.y); \ - if(fabsf(Nodes[i].mAABB.mExtents.z)>EMax.z) EMax.z = fabsf(Nodes[i].mAABB.mExtents.z); \ - } - -#define INIT_QUANTIZATION \ - udword nbc=15; /* Keep one bit for sign */ \ - udword nbe=15; /* Keep one bit for fix */ \ - if(!gFixQuantized) nbe++; \ - \ - /* Compute quantization coeffs */ \ - IcePoint CQuantCoeff, EQuantCoeff; \ - CQuantCoeff.x = CMax.x!=0.0f ? float((1<Min[j]) mNodes[i].mAABB.mExtents[j]++; \ - else FixMe=false; \ - /* Prevent wrapping */ \ - if(!mNodes[i].mAABB.mExtents[j]) \ - { \ - mNodes[i].mAABB.mExtents[j]=0xffff; \ - FixMe=false; \ - } \ - }while(FixMe); \ - } \ - } - -#define REMAP_DATA(member) \ - /* Fix data */ \ - Data = Nodes[i].member; \ - if(!(Data&1)) \ - { \ - /* Compute box number */ \ - udword Nb = (Data - udword(Nodes))/Nodes[i].GetNodeSize(); \ - Data = udword(&mNodes[Nb]); \ - } \ - /* ...remapped */ \ - mNodes[i].member = Data; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBQuantizedTree::AABBQuantizedTree() : mNodes(null) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBQuantizedTree::~AABBQuantizedTree() -{ - DELETEARRAY(mNodes); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds the collision tree from a generic AABB tree. - * \param tree [in] generic AABB tree - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBQuantizedTree::Build(AABBTree* tree) -{ - // Checkings - if(!tree) return false; - // Check the input tree is complete - udword NbTriangles = tree->GetNbPrimitives(); - udword NbNodes = tree->GetNbNodes(); - if(NbNodes!=NbTriangles*2-1) return false; - - // Get nodes - mNbNodes = NbNodes; - DELETEARRAY(mNodes); - AABBCollisionNode* Nodes = new AABBCollisionNode[mNbNodes]; - CHECKALLOC(Nodes); - - // Build the tree - udword CurID = 1; - _BuildCollisionTree(Nodes, 0, CurID, tree); - - // Quantize - { - mNodes = new AABBQuantizedNode[mNbNodes]; - CHECKALLOC(mNodes); - - // Get max values - FIND_MAX_VALUES - - // Quantization - INIT_QUANTIZATION - - // Quantize - udword Data; - for(udword i=0;iIsLeaf()) - { - _Walk(current_node->GetPos(), callback, user_data); - _Walk(current_node->GetNeg(), callback, user_data); - } - } - }; - Local::_Walk(mNodes, callback, user_data); - return true; -} - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree() -{ - DELETEARRAY(mNodes); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Builds the collision tree from a generic AABB tree. - * \param tree [in] generic AABB tree - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBQuantizedNoLeafTree::Build(AABBTree* tree) -{ - // Checkings - if(!tree) return false; - // Check the input tree is complete - udword NbTriangles = tree->GetNbPrimitives(); - udword NbNodes = tree->GetNbNodes(); - if(NbNodes!=NbTriangles*2-1) return false; - - // Get nodes - mNbNodes = NbTriangles-1; - DELETEARRAY(mNodes); - AABBNoLeafNode* Nodes = new AABBNoLeafNode[mNbNodes]; - CHECKALLOC(Nodes); - - // Build the tree - udword CurID = 1; - _BuildNoLeafTree(Nodes, 0, CurID, tree); - ASSERT(CurID==mNbNodes); - - // Quantize - { - mNodes = new AABBQuantizedNoLeafNode[mNbNodes]; - CHECKALLOC(mNodes); - - // Get max values - FIND_MAX_VALUES - - // Quantization - INIT_QUANTIZATION - - // Quantize - udword Data; - for(udword i=0;iHasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); - if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); - } - }; - Local::_Walk(mNodes, callback, user_data); - return true; -} diff --git a/contrib/Opcode/OPC_OptimizedTree.h b/contrib/Opcode/OPC_OptimizedTree.h deleted file mode 100644 index c36e21e..0000000 --- a/contrib/Opcode/OPC_OptimizedTree.h +++ /dev/null @@ -1,206 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for optimized trees. - * \file OPC_OptimizedTree.h - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_OPTIMIZEDTREE_H__ -#define __OPC_OPTIMIZEDTREE_H__ - - //! Common interface for a node of an implicit tree - #define IMPLEMENT_IMPLICIT_NODE(base_class, volume) \ - public: \ - /* Constructor / Destructor */ \ - inline_ base_class() : mData(0) {} \ - inline_ ~base_class() {} \ - /* Leaf test */ \ - inline_ BOOL IsLeaf() const { return mData&1; } \ - /* Data access */ \ - inline_ const base_class* GetPos() const { return (base_class*)mData; } \ - inline_ const base_class* GetNeg() const { return ((base_class*)mData)+1; } \ - inline_ udword GetPrimitive() const { return (mData>>1); } \ - /* Stats */ \ - inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ - \ - volume mAABB; \ - udword mData; - - //! Common interface for a node of a no-leaf tree - #define IMPLEMENT_NOLEAF_NODE(base_class, volume) \ - public: \ - /* Constructor / Destructor */ \ - inline_ base_class() : mPosData(0), mNegData(0) {} \ - inline_ ~base_class() {} \ - /* Leaf tests */ \ - inline_ BOOL HasPosLeaf() const { return mPosData&1; } \ - inline_ BOOL HasNegLeaf() const { return mNegData&1; } \ - /* Data access */ \ - inline_ const base_class* GetPos() const { return (base_class*)mPosData; } \ - inline_ const base_class* GetNeg() const { return (base_class*)mNegData; } \ - inline_ udword GetPosPrimitive() const { return (mPosData>>1); } \ - inline_ udword GetNegPrimitive() const { return (mNegData>>1); } \ - /* Stats */ \ - inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ - \ - volume mAABB; \ - udword mPosData; \ - udword mNegData; - - class OPCODE_API AABBCollisionNode - { - IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB) - - inline_ float GetVolume() const { return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z; } - inline_ float GetSize() const { return mAABB.mExtents.SquareMagnitude(); } - inline_ udword GetRadius() const - { - udword* Bits = (udword*)&mAABB.mExtents.x; - udword Max = Bits[0]; - if(Bits[1]>Max) Max = Bits[1]; - if(Bits[2]>Max) Max = Bits[2]; - return Max; - } - - // NB: using the square-magnitude or the true volume of the box, seems to yield better results - // (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size" - // otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's - // needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is - // always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices - // whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very - // good strategy. - }; - - class OPCODE_API AABBQuantizedNode - { - IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB) - - inline_ uword GetSize() const - { - const uword* Bits = mAABB.mExtents; - uword Max = Bits[0]; - if(Bits[1]>Max) Max = Bits[1]; - if(Bits[2]>Max) Max = Bits[2]; - return Max; - } - // NB: for quantized nodes I don't feel like computing a square-magnitude with integers all - // over the place.......! - }; - - class OPCODE_API AABBNoLeafNode - { - IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB) - }; - - class OPCODE_API AABBQuantizedNoLeafNode - { - IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB) - }; - - //! Common interface for a collision tree - #define IMPLEMENT_COLLISION_TREE(base_class, node) \ - public: \ - /* Constructor / Destructor */ \ - base_class(); \ - virtual ~base_class(); \ - /* Builds from a standard tree */ \ - override(AABBOptimizedTree) bool Build(AABBTree* tree); \ - /* Refits the tree */ \ - override(AABBOptimizedTree) bool Refit(const MeshInterface* mesh_interface); \ - /* Walks the tree */ \ - override(AABBOptimizedTree) bool Walk(GenericWalkingCallback callback, void* user_data) const; \ - /* Data access */ \ - inline_ const node* GetNodes() const { return mNodes; } \ - /* Stats */ \ - override(AABBOptimizedTree) udword GetUsedBytes() const { return mNbNodes*sizeof(node); } \ - private: \ - node* mNodes; - - typedef bool (*GenericWalkingCallback) (const void* current, void* user_data); - - class OPCODE_API AABBOptimizedTree - { - public: - // Constructor / Destructor - AABBOptimizedTree() : - mNbNodes (0) - {} - virtual ~AABBOptimizedTree() {} - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Builds the collision tree from a generic AABB tree. - * \param tree [in] generic AABB tree - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual bool Build(AABBTree* tree) = 0; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Refits the collision tree after vertices have been modified. - * \param mesh_interface [in] mesh interface for current model - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual bool Refit(const MeshInterface* mesh_interface) = 0; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Walks the tree and call the user back for each node. - * \param callback [in] walking callback - * \param user_data [in] callback's user data - * \return true if success - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual bool Walk(GenericWalkingCallback callback, void* user_data) const = 0; - - // Data access - virtual udword GetUsedBytes() const = 0; - inline_ udword GetNbNodes() const { return mNbNodes; } - - protected: - udword mNbNodes; - }; - - class OPCODE_API AABBCollisionTree : public AABBOptimizedTree - { - IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode) - }; - - class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree - { - IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode) - }; - - class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree - { - IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode) - - public: - IcePoint mCenterCoeff; - IcePoint mExtentsCoeff; - }; - - class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree - { - IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode) - - public: - IcePoint mCenterCoeff; - IcePoint mExtentsCoeff; - }; - -#endif // __OPC_OPTIMIZEDTREE_H__ diff --git a/contrib/Opcode/OPC_Picking.cpp b/contrib/Opcode/OPC_Picking.cpp deleted file mode 100644 index 5a48403..0000000 --- a/contrib/Opcode/OPC_Picking.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code to perform "picking". - * \file OPC_Picking.cpp - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -#ifdef OPC_RAYHIT_CALLBACK - -/* - Possible RayCollider usages: - - boolean query (shadow feeler) - - closest hit - - all hits - - number of intersection (boolean) - -*/ - -bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts) -{ - struct Local - { - static void AllContacts(const CollisionFace& hit, void* user_data) - { - CollisionFaces* CF = (CollisionFaces*)user_data; - CF->AddFace(hit); - } - }; - - collider.SetFirstContact(false); - collider.SetHitCallback(Local::AllContacts); - collider.SetUserData(&contacts); - return true; -} - -bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact) -{ - struct Local - { - static void ClosestContact(const CollisionFace& hit, void* user_data) - { - CollisionFace* CF = (CollisionFace*)user_data; - if(hit.mDistancemDistance) *CF = hit; - } - }; - - collider.SetFirstContact(false); - collider.SetHitCallback(Local::ClosestContact); - collider.SetUserData(&closest_contact); - closest_contact.mDistance = MAX_FLOAT; - return true; -} - -bool Opcode::SetupShadowFeeler(RayCollider& collider) -{ - collider.SetFirstContact(true); - collider.SetHitCallback(null); - return true; -} - -bool Opcode::SetupInOutTest(RayCollider& collider) -{ - collider.SetFirstContact(false); - collider.SetHitCallback(null); - // Results with collider.GetNbIntersections() - return true; -} - -bool Opcode::Picking( -CollisionFace& picked_face, -const Ray& world_ray, const Model& model, const Matrix4x4* world, -float min_dist, float max_dist, const IcePoint& view_point, CullModeCallback callback, void* user_data) -{ - struct Local - { - struct CullData - { - CollisionFace* Closest; - float MinLimit; - CullModeCallback Callback; - void* UserData; - IcePoint ViewPoint; - const MeshInterface* IMesh; - }; - - // Called for each stabbed face - static void RenderCullingCallback(const CollisionFace& hit, void* user_data) - { - CullData* Data = (CullData*)user_data; - - // Discard face if we already have a closer hit - if(hit.mDistance>=Data->Closest->mDistance) return; - - // Discard face if hit IcePoint is smaller than min limit. This mainly happens when the face is in front - // of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an - // object that he may not even be able to see, which is very annoying. - if(hit.mDistance<=Data->MinLimit) return; - - // This is the index of currently stabbed triangle. - udword StabbedFaceIndex = hit.mFaceID; - - // We may keep it or not, depending on backface culling - bool KeepIt = true; - - // Catch *render* cull mode for this face - CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData); - - if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles - { - // Compute backface culling for current face - - VertexPointers VP; - Data->IMesh->GetTriangle(VP, StabbedFaceIndex); - if(VP.BackfaceCulling(Data->ViewPoint)) - { - if(CM==CULLMODE_CW) KeepIt = false; - } - else - { - if(CM==CULLMODE_CCW) KeepIt = false; - } - } - - if(KeepIt) *Data->Closest = hit; - } - }; - - RayCollider RC; - RC.SetMaxDist(max_dist); - RC.SetTemporalCoherence(false); - RC.SetCulling(false); // We need all faces since some of them can be double-sided - RC.SetFirstContact(false); - RC.SetHitCallback(Local::RenderCullingCallback); - - picked_face.mFaceID = INVALID_ID; - picked_face.mDistance = MAX_FLOAT; - picked_face.mU = 0.0f; - picked_face.mV = 0.0f; - - Local::CullData Data; - Data.Closest = &picked_face; - Data.MinLimit = min_dist; - Data.Callback = callback; - Data.UserData = user_data; - Data.ViewPoint = view_point; - Data.IMesh = model.GetMeshInterface(); - - if(world) - { - // Get matrices - Matrix4x4 InvWorld; - InvertPRMatrix(InvWorld, *world); - - // Compute camera position in mesh space - Data.ViewPoint *= InvWorld; - } - - RC.SetUserData(&Data); - if(RC.Collide(world_ray, model, world)) - { - return picked_face.mFaceID!=INVALID_ID; - } - return false; -} - -#endif diff --git a/contrib/Opcode/OPC_Picking.h b/contrib/Opcode/OPC_Picking.h deleted file mode 100644 index cae5402..0000000 --- a/contrib/Opcode/OPC_Picking.h +++ /dev/null @@ -1,45 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code to perform "picking". - * \file OPC_Picking.h - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_PICKING_H__ -#define __OPC_PICKING_H__ - -#ifdef OPC_RAYHIT_CALLBACK - - enum CullMode - { - CULLMODE_NONE = 0, - CULLMODE_CW = 1, - CULLMODE_CCW = 2 - }; - - typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data); - - OPCODE_API bool SetupAllHits (RayCollider& collider, CollisionFaces& contacts); - OPCODE_API bool SetupClosestHit (RayCollider& collider, CollisionFace& closest_contact); - OPCODE_API bool SetupShadowFeeler (RayCollider& collider); - OPCODE_API bool SetupInOutTest (RayCollider& collider); - - OPCODE_API bool Picking( - CollisionFace& picked_face, - const Ray& world_ray, const Model& model, const Matrix4x4* world, - float min_dist, float max_dist, const IcePoint& view_point, CullModeCallback callback, void* user_data); -#endif - -#endif //__OPC_PICKING_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_PlanesAABBOverlap.h b/contrib/Opcode/OPC_PlanesAABBOverlap.h deleted file mode 100644 index 2bc70d7..0000000 --- a/contrib/Opcode/OPC_PlanesAABBOverlap.h +++ /dev/null @@ -1,50 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Planes-AABB overlap test. - * - original code by Ville Miettinen, from Umbra/dPVS (released on the GD-Algorithms mailing list) - * - almost used "as-is", I even left the comments (hence the frustum-related notes) - * - * \param center [in] box center - * \param extents [in] box extents - * \param out_clip_mask [out] bitmask for active planes - * \param in_clip_mask [in] bitmask for active planes - * \return TRUE if boxes overlap planes - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL PlanesCollider::PlanesAABBOverlap(const IcePoint& center, const IcePoint& extents, udword& out_clip_mask, udword in_clip_mask) -{ - // Stats - mNbVolumeBVTests++; - - const IcePlane* p = mPlanes; - - // Evaluate through all active frustum planes. We determine the relation - // between the AABB and a plane by using the concept of "near" and "far" - // vertices originally described by Zhang (and later by Möller). Our - // variant here uses 3 fabs ops, 6 muls, 7 adds and two floating IcePoint - // comparisons per plane. The routine early-exits if the AABB is found - // to be outside any of the planes. The loop also constructs a new output - // clip mask. Most FPUs have a native single-cycle fabsf() operation. - - udword Mask = 1; // current mask index (1,2,4,8,..) - udword TmpOutClipMask = 0; // initialize output clip mask into empty. - - while(Mask<=in_clip_mask) // keep looping while we have active planes left... - { - if(in_clip_mask & Mask) // if clip plane is active, process it.. - { - float NP = extents.x*fabsf(p->n.x) + extents.y*fabsf(p->n.y) + extents.z*fabsf(p->n.z); // ### fabsf could be precomputed - float MP = center.x*p->n.x + center.y*p->n.y + center.z*p->n.z + p->d; - - if(NP < MP) // near vertex behind the clip plane... - return FALSE; // .. so there is no intersection.. - if((-NP) < MP) // near and far vertices on different sides of plane.. - TmpOutClipMask |= Mask; // .. so update the clip mask... - } - Mask+=Mask; // mk = (1<Add(prim_index); - -//! Planes-triangle test -#define PLANES_PRIM(prim_index, flag) \ - /* Request vertices from the app */ \ - mIMesh->GetTriangle(mVP, prim_index); \ - /* Perform triangle-box overlap test */ \ - if(PlanesTriOverlap(clip_mask)) \ - { \ - SET_CONTACT(prim_index, flag) \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -PlanesCollider::PlanesCollider() : - mPlanes (null), - mNbPlanes (0) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -PlanesCollider::~PlanesCollider() -{ - DELETEARRAY(mPlanes); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Validates current settings. You should call this method after all the settings and callbacks have been defined. - * \return null if everything is ok, else a string describing the problem - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -const char* PlanesCollider::ValidateSettings() -{ - if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; - - return VolumeCollider::ValidateSettings(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] a planes cache - * \param planes [in] list of planes in world space - * \param nb_planes [in] number of planes - * \param model [in] Opcode model to collide with - * \param worldm [in] model's world matrix, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool PlanesCollider::Collide(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm) -{ - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, planes, nb_planes, worldm)) return true; - - udword PlaneMask = (1<mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); - else _Collide(Tree->GetNodes(), PlaneMask); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); - else _Collide(Tree->GetNodes(), PlaneMask); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); - else _Collide(Tree->GetNodes(), PlaneMask); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); - else _Collide(Tree->GetNodes(), PlaneMask); - } - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Initializes a collision query : - * - reset stats & contact status - * - compute planes in model space - * - check temporal coherence - * - * \param cache [in/out] a planes cache - * \param planes [in] list of planes - * \param nb_planes [in] number of planes - * \param worldm [in] model's world matrix, or null - * \return TRUE if we can return immediately - * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOL PlanesCollider::InitQuery(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const Matrix4x4* worldm) -{ - // 1) Call the base method - VolumeCollider::InitQuery(); - - // 2) Compute planes in model space - if(nb_planes>mNbPlanes) - { - DELETEARRAY(mPlanes); - mPlanes = new IcePlane[nb_planes]; - } - mNbPlanes = nb_planes; - - if(worldm) - { - Matrix4x4 InvWorldM; - InvertPRMatrix(InvWorldM, *worldm); - -// for(udword i=0;iHasSingleNode()) - { - if(!SkipPrimitiveTests()) - { - // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. - mTouchedPrimitives->Reset(); - - // Perform overlap test between the unique triangle and the planes (and set contact status if needed) - udword clip_mask = (1< check results from previous frame before performing the collision query - if(FirstContactEnabled()) - { - // We're only interested in the first contact found => test the unique previously touched face - if(mTouchedPrimitives->GetNbEntries()) - { - // Get index of previously touched face = the first entry in the array - udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); - - // Then reset the array: - // - if the overlap test below is successful, the index we'll get added back anyway - // - if it isn't, then the array should be reset anyway for the normal query - mTouchedPrimitives->Reset(); - - // Perform overlap test between the cached triangle and the planes (and set contact status if needed) - udword clip_mask = (1< we'll have to perform a normal query - } - else mTouchedPrimitives->Reset(); - } - else - { - // Here we don't use temporal coherence => do a normal query - mTouchedPrimitives->Reset(); - } - - return FALSE; -} - -#define TEST_CLIP_MASK \ - /* If the box is completely included, so are its children. We don't need to do extra tests, we */ \ - /* can immediately output a list of visible children. Those ones won't need to be clipped. */ \ - if(!OutClipMask) \ - { \ - /* Set contact status */ \ - mFlags |= OPC_CONTACT; \ - _Dump(node); \ - return; \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void PlanesCollider::_Collide(const AABBCollisionNode* node, udword clip_mask) -{ - // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. - udword OutClipMask; - if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; - - TEST_CLIP_MASK - - // Else the box straddles one or several planes, so we need to recurse down the tree. - if(node->IsLeaf()) - { - PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos(), OutClipMask); - - if(ContactFound()) return; - - _Collide(node->GetNeg(), OutClipMask); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void PlanesCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask) -{ - // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. - udword OutClipMask; - if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; - - TEST_CLIP_MASK - - // Else the box straddles one or several planes, so we need to recurse down the tree. - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void PlanesCollider::_Collide(const AABBQuantizedNode* node, udword clip_mask) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. - udword OutClipMask; - if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; - - TEST_CLIP_MASK - - // Else the box straddles one or several planes, so we need to recurse down the tree. - if(node->IsLeaf()) - { - PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos(), OutClipMask); - - if(ContactFound()) return; - - _Collide(node->GetNeg(), OutClipMask); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. - udword OutClipMask; - if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; - - TEST_CLIP_MASK - - // Else the box straddles one or several planes, so we need to recurse down the tree. - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void PlanesCollider::_Collide(const AABBNoLeafNode* node, udword clip_mask) -{ - // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. - udword OutClipMask; - if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; - - TEST_CLIP_MASK - - // Else the box straddles one or several planes, so we need to recurse down the tree. - if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos(), OutClipMask); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg(), OutClipMask); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void PlanesCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask) -{ - // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. - udword OutClipMask; - if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; - - TEST_CLIP_MASK - - // Else the box straddles one or several planes, so we need to recurse down the tree. - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void PlanesCollider::_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. - udword OutClipMask; - if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; - - TEST_CLIP_MASK - - // Else the box straddles one or several planes, so we need to recurse down the tree. - if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos(), OutClipMask); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg(), OutClipMask); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. - udword OutClipMask; - if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; - - TEST_CLIP_MASK - - // Else the box straddles one or several planes, so we need to recurse down the tree. - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); -} - - - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridPlanesCollider::HybridPlanesCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridPlanesCollider::~HybridPlanesCollider() -{ -} - -bool HybridPlanesCollider::Collide(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm) -{ - // We don't want primitive tests here! - mFlags |= OPC_NO_PRIMITIVE_TESTS; - - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, planes, nb_planes, worldm)) return true; - - // Special case for 1-leaf trees - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles - udword Nb = mIMesh->GetNbTriangles(); - - // Loop through all triangles - udword clip_mask = (1<mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); - } - } - - // We only have a list of boxes so far - if(GetContactStatus()) - { - // Reset contact status, since it currently only reflects collisions with leaf boxes - Collider::InitQuery(); - - // Change dest container so that we can use built-in overlap tests and get collided primitives - cache.TouchedPrimitives.Reset(); - mTouchedPrimitives = &cache.TouchedPrimitives; - - // Read touched leaf boxes - udword Nb = mTouchedBoxes.GetNbEntries(); - const udword* Touched = mTouchedBoxes.GetEntries(); - - const LeafTriangles* LT = model.GetLeafTriangles(); - const udword* Indices = model.GetIndices(); - - // Loop through touched leaves - udword clip_mask = (1<Distance(*mVP.Vertex[0]); - float d1 = p->Distance(*mVP.Vertex[1]); - float d2 = p->Distance(*mVP.Vertex[2]); - if(d0>0.0f && d1>0.0f && d2>0.0f) return FALSE; -// if(!(IR(d0)&SIGN_BITMASK) && !(IR(d1)&SIGN_BITMASK) && !(IR(d2)&SIGN_BITMASK)) return FALSE; - } - Mask+=Mask; - p++; - } -/* - for(udword i=0;i<6;i++) - { - float d0 = p[i].Distance(mLeafVerts[0]); - float d1 = p[i].Distance(mLeafVerts[1]); - float d2 = p[i].Distance(mLeafVerts[2]); - if(d0>0.0f && d1>0.0f && d2>0.0f) return false; - } -*/ - return TRUE; -} diff --git a/contrib/Opcode/OPC_RayAABBOverlap.h b/contrib/Opcode/OPC_RayAABBOverlap.h deleted file mode 100644 index cd2bdfb..0000000 --- a/contrib/Opcode/OPC_RayAABBOverlap.h +++ /dev/null @@ -1,63 +0,0 @@ -// Opcode 1.1: ray-AABB overlap tests based on Woo's code -// Opcode 1.2: ray-AABB overlap tests based on the separating axis theorem -// -// The IcePoint of intersection is not computed anymore. The distance to impact is not needed anymore -// since we now have two different queries for segments or rays. - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes a segment-AABB overlap test using the separating axis theorem. IceSegment is cached within the class. - * \param center [in] AABB center - * \param extents [in] AABB extents - * \return true on overlap - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL RayCollider::SegmentAABBOverlap(const IcePoint& center, const IcePoint& extents) -{ - // Stats - mNbRayBVTests++; - - float Dx = mData2.x - center.x; if(fabsf(Dx) > extents.x + mFDir.x) return FALSE; - float Dy = mData2.y - center.y; if(fabsf(Dy) > extents.y + mFDir.y) return FALSE; - float Dz = mData2.z - center.z; if(fabsf(Dz) > extents.z + mFDir.z) return FALSE; - - float f; - f = mData.y * Dz - mData.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; - f = mData.z * Dx - mData.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; - f = mData.x * Dy - mData.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; - - return TRUE; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes a ray-AABB overlap test using the separating axis theorem. Ray is cached within the class. - * \param center [in] AABB center - * \param extents [in] AABB extents - * \return true on overlap - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL RayCollider::RayAABBOverlap(const IcePoint& center, const IcePoint& extents) -{ - // Stats - mNbRayBVTests++; - -// float Dx = mOrigin.x - center.x; if(fabsf(Dx) > extents.x && Dx*mDir.x>=0.0f) return FALSE; -// float Dy = mOrigin.y - center.y; if(fabsf(Dy) > extents.y && Dy*mDir.y>=0.0f) return FALSE; -// float Dz = mOrigin.z - center.z; if(fabsf(Dz) > extents.z && Dz*mDir.z>=0.0f) return FALSE; - - float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && Dx*mDir.x>=0.0f) return FALSE; - float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && Dy*mDir.y>=0.0f) return FALSE; - float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && Dz*mDir.z>=0.0f) return FALSE; - -// float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && ((SIR(Dx)-1)^SIR(mDir.x))>=0.0f) return FALSE; -// float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && ((SIR(Dy)-1)^SIR(mDir.y))>=0.0f) return FALSE; -// float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && ((SIR(Dz)-1)^SIR(mDir.z))>=0.0f) return FALSE; - - float f; - f = mDir.y * Dz - mDir.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; - f = mDir.z * Dx - mDir.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; - f = mDir.x * Dy - mDir.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; - - return TRUE; -} diff --git a/contrib/Opcode/OPC_RayCollider.cpp b/contrib/Opcode/OPC_RayCollider.cpp deleted file mode 100644 index d1c90a5..0000000 --- a/contrib/Opcode/OPC_RayCollider.cpp +++ /dev/null @@ -1,762 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for a ray collider. - * \file OPC_RayCollider.cpp - * \author Pierre Terdiman - * \date June, 2, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a ray-vs-tree collider. - * This class performs a stabbing query on an AABB tree, i.e. does a ray-mesh collision. - * - * HIGHER DISTANCE BOUND: - * - * If P0 and P1 are two 3D points, let's define: - * - d = distance between P0 and P1 - * - Origin = P0 - * - Direction = (P1 - P0) / d = normalized direction vector - * - A parameter t such as a IcePoint P on the line (P0,P1) is P = Origin + t * Direction - * - t = 0 --> P = P0 - * - t = d --> P = P1 - * - * Then we can define a general "ray" as: - * - * struct Ray - * { - * IcePoint Origin; - * IcePoint Direction; - * }; - * - * But it actually maps three different things: - * - a segment, when 0 <= t <= d - * - a half-line, when 0 <= t < +infinity, or -infinity < t <= d - * - a line, when -infinity < t < +infinity - * - * In Opcode, we support segment queries, which yield half-line queries by setting d = +infinity. - * We don't support line-queries. If you need them, shift the origin along the ray by an appropriate margin. - * - * In short, the lower bound is always 0, and you can setup the higher bound "d" with RayCollider::SetMaxDist(). - * - * Query |segment |half-line |line - * --------|-------------------|---------------|---------------- - * Usages |-shadow feelers |-raytracing |- - * |-sweep tests |-in/out tests | - * - * FIRST CONTACT: - * - * - You can setup "first contact" mode or "all contacts" mode with RayCollider::SetFirstContact(). - * - In "first contact" mode we return as soon as the ray hits one face. If can be useful e.g. for shadow feelers, where - * you want to know whether the path to the light is free or not (a boolean answer is enough). - * - In "all contacts" mode we return all faces hit by the ray. - * - * TEMPORAL COHERENCE: - * - * - You can enable or disable temporal coherence with RayCollider::SetTemporalCoherence(). - * - It currently only works in "first contact" mode. - * - If temporal coherence is enabled, the previously hit triangle is cached during the first query. Then, next queries - * start by colliding the ray against the cached triangle. If they still collide, we return immediately. - * - * CLOSEST HIT: - * - * - You can enable or disable "closest hit" with RayCollider::SetClosestHit(). - * - It currently only works in "all contacts" mode. - * - If closest hit is enabled, faces are sorted by distance on-the-fly and the closest one only is reported. - * - * BACKFACE CULLING: - * - * - You can enable or disable backface culling with RayCollider::SetCulling(). - * - If culling is enabled, ray will not hit back faces (only front faces). - * - * - * - * \class RayCollider - * \author Pierre Terdiman - * \version 1.3 - * \date June, 2, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * This class describes a face hit by a ray or segment. - * This is a particular class dedicated to stabbing queries. - * - * \class CollisionFace - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * This class is a dedicated collection of CollisionFace. - * - * \class CollisionFaces - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -#include "OPC_RayAABBOverlap.h" -#include "OPC_RayTriOverlap.h" - -#define SET_CONTACT(prim_index, flag) \ - mNbIntersections++; \ - /* Set contact status */ \ - mFlags |= flag; \ - /* In any case the contact has been found and recorded in mStabbedFace */ \ - mStabbedFace.mFaceID = prim_index; - -#ifdef OPC_RAYHIT_CALLBACK - - #define HANDLE_CONTACT(prim_index, flag) \ - SET_CONTACT(prim_index, flag) \ - \ - if(mHitCallback) (mHitCallback)(mStabbedFace, mUserData); - - #define UPDATE_CACHE \ - if(cache && GetContactStatus()) \ - { \ - *cache = mStabbedFace.mFaceID; \ - } -#else - - #define HANDLE_CONTACT(prim_index, flag) \ - SET_CONTACT(prim_index, flag) \ - \ - /* Now we can also record it in mStabbedFaces if available */ \ - if(mStabbedFaces) \ - { \ - /* If we want all faces or if that's the first one we hit */ \ - if(!mClosestHit || !mStabbedFaces->GetNbFaces()) \ - { \ - mStabbedFaces->AddFace(mStabbedFace); \ - } \ - else \ - { \ - /* We only keep closest hit */ \ - CollisionFace* Current = const_cast(mStabbedFaces->GetFaces()); \ - if(Current && mStabbedFace.mDistancemDistance) \ - { \ - *Current = mStabbedFace; \ - } \ - } \ - } - - #define UPDATE_CACHE \ - if(cache && GetContactStatus() && mStabbedFaces) \ - { \ - const CollisionFace* Current = mStabbedFaces->GetFaces(); \ - if(Current) *cache = Current->mFaceID; \ - else *cache = INVALID_ID; \ - } -#endif - -#define SEGMENT_PRIM(prim_index, flag) \ - /* Request vertices from the app */ \ - VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ - \ - /* Perform ray-tri overlap test and return */ \ - if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ - { \ - /* Intersection IcePoint is valid if dist < segment's length */ \ - /* We know dist>0 so we can use integers */ \ - if(IR(mStabbedFace.mDistance)GetTriangle(VP, prim_index); \ - \ - /* Perform ray-tri overlap test and return */ \ - if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ - { \ - HANDLE_CONTACT(prim_index, flag) \ - } - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -RayCollider::RayCollider() : - mNbRayBVTests (0), - mNbRayPrimTests (0), - mNbIntersections (0), - mCulling (true), -#ifdef OPC_RAYHIT_CALLBACK - mHitCallback (null), - mUserData (0), -#else - mClosestHit (false), - mStabbedFaces (null), -#endif - mMaxDist (MAX_FLOAT) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -RayCollider::~RayCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Validates current settings. You should call this method after all the settings and callbacks have been defined. - * \return null if everything is ok, else a string describing the problem - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -const char* RayCollider::ValidateSettings() -{ - if(mMaxDist<0.0f) return "Higher distance bound must be positive!"; - if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; -#ifndef OPC_RAYHIT_CALLBACK - if(mClosestHit && FirstContactEnabled()) return "Closest hit doesn't work with ""First contact"" mode!"; - if(TemporalCoherenceEnabled() && mClosestHit) return "Temporal coherence can't guarantee to report closest hit!"; -#endif - if(SkipPrimitiveTests()) return "SkipPrimitiveTests not possible for RayCollider ! (not implemented)"; - return null; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Generic stabbing query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - in the user-provided destination array - * - * \param world_ray [in] stabbing ray in world space - * \param model [in] Opcode model to collide with - * \param world [in] model's world matrix, or null - * \param cache [in] a possibly cached face index, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool RayCollider::Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world, udword* cache) -{ - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(world_ray, world, cache)) return true; - - if(!model.HasLeafNodes()) - { - if(model.IsQuantized()) - { - const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform stabbing query - if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); - else _RayStab(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform stabbing query - if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); - else _RayStab(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform stabbing query - if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); - else _RayStab(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform stabbing query - if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); - else _RayStab(Tree->GetNodes()); - } - } - - // Update cache if needed - UPDATE_CACHE - return true; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Initializes a stabbing query : - * - reset stats & contact status - * - compute ray in local space - * - check temporal coherence - * - * \param world_ray [in] stabbing ray in world space - * \param world [in] object's world matrix, or null - * \param face_id [in] index of previously stabbed triangle - * \return TRUE if we can return immediately - * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword* face_id) -{ - // Reset stats & contact status - Collider::InitQuery(); - mNbRayBVTests = 0; - mNbRayPrimTests = 0; - mNbIntersections = 0; -#ifndef OPC_RAYHIT_CALLBACK - if(mStabbedFaces) mStabbedFaces->Reset(); -#endif - - // Compute ray in local space - // The (Origin/Dir) form is needed for the ray-triangle test anyway (even for segment tests) - if(world) - { - Matrix3x3 InvWorld = *world; - mDir = InvWorld * world_ray.mDir; - - Matrix4x4 World; - InvertPRMatrix(World, *world); - mOrigin = world_ray.mOrig * World; - } - else - { - mDir = world_ray.mDir; - mOrigin = world_ray.mOrig; - } - - // 4) Special case: 1-triangle meshes [Opcode 1.3] - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. - if(!SkipPrimitiveTests()) - { - // Perform overlap test between the unique triangle and the ray (and set contact status if needed) - SEGMENT_PRIM(udword(0), OPC_CONTACT) - - // Return immediately regardless of status - return TRUE; - } - } - - // Check temporal coherence : - - // Test previously colliding primitives first - if(TemporalCoherenceEnabled() && FirstContactEnabled() && face_id && *face_id!=INVALID_ID) - { -#ifdef OLD_CODE -#ifndef OPC_RAYHIT_CALLBACK - if(!mClosestHit) -#endif - { - // Request vertices from the app - VertexPointers VP; - mIMesh->GetTriangle(VP, *face_id); - // Perform ray-cached tri overlap test - if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) - { - // Intersection IcePoint is valid if: - // - distance is positive (else it can just be a face behind the orig IcePoint) - // - distance is smaller than a given max distance (useful for shadow feelers) -// if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistanceAddFace(mStabbedFace); -#endif - return TRUE; - } - } - } -#else - // New code - // We handle both IceSegment/ray queries with the same segment code, and a possible infinite limit - SEGMENT_PRIM(*face_id, OPC_TEMPORAL_CONTACT) - - // Return immediately if possible - if(GetContactStatus()) return TRUE; -#endif - } - - // Precompute data (moved after temporal coherence since only needed for ray-AABB) - if(IR(mMaxDist)!=IEEE_MAX_FLOAT) - { - // For IceSegment-AABB overlap - mData = 0.5f * mDir * mMaxDist; - mData2 = mOrigin + mData; - - // Precompute mFDir; - mFDir.x = fabsf(mData.x); - mFDir.y = fabsf(mData.y); - mFDir.z = fabsf(mData.z); - } - else - { - // For Ray-AABB overlap -// udword x = SIR(mDir.x)-1; -// udword y = SIR(mDir.y)-1; -// udword z = SIR(mDir.z)-1; -// mData.x = FR(x); -// mData.y = FR(y); -// mData.z = FR(z); - - // Precompute mFDir; - mFDir.x = fabsf(mDir.x); - mFDir.y = fabsf(mDir.y); - mFDir.z = fabsf(mDir.z); - } - - return FALSE; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Stabbing query for vanilla AABB trees. - * \param world_ray [in] stabbing ray in world space - * \param tree [in] AABB tree - * \param box_indices [out] indices of stabbed boxes - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool RayCollider::Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices) -{ - // ### bad design here - - // This is typically called for a scene tree, full of -AABBs-, not full of triangles. - // So we don't really have "primitives" to deal with. Hence it doesn't work with - // "FirstContact" + "TemporalCoherence". - ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); - - // Checkings - if(!tree) return false; - - // Init collision query - // Basically this is only called to initialize precomputed data - if(InitQuery(world_ray)) return true; - - // Perform stabbing query - if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(tree, box_indices); - else _RayStab(tree, box_indices); - - return true; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for normal AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_SegmentStab(const AABBCollisionNode* node) -{ - // Perform IceSegment-AABB overlap test - if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - if(node->IsLeaf()) - { - SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _SegmentStab(node->GetPos()); - - if(ContactFound()) return; - - _SegmentStab(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for quantized AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_SegmentStab(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform IceSegment-AABB overlap test - if(!SegmentAABBOverlap(Center, Extents)) return; - - if(node->IsLeaf()) - { - SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _SegmentStab(node->GetPos()); - - if(ContactFound()) return; - - _SegmentStab(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_SegmentStab(const AABBNoLeafNode* node) -{ - // Perform IceSegment-AABB overlap test - if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - if(node->HasPosLeaf()) - { - SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) - } - else _SegmentStab(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) - { - SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) - } - else _SegmentStab(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for quantized no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_SegmentStab(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform IceSegment-AABB overlap test - if(!SegmentAABBOverlap(Center, Extents)) return; - - if(node->HasPosLeaf()) - { - SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) - } - else _SegmentStab(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) - { - SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) - } - else _SegmentStab(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for vanilla AABB trees. - * \param node [in] current collision node - * \param box_indices [out] indices of stabbed boxes - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_SegmentStab(const AABBTreeNode* node, Container& box_indices) -{ - // Test the box against the segment - IcePoint Center, Extents; - node->GetAABB()->GetCenter(Center); - node->GetAABB()->GetExtents(Extents); - if(!SegmentAABBOverlap(Center, Extents)) return; - - if(node->IsLeaf()) - { - box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); - } - else - { - _SegmentStab(node->GetPos(), box_indices); - _SegmentStab(node->GetNeg(), box_indices); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for normal AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_RayStab(const AABBCollisionNode* node) -{ - // Perform Ray-AABB overlap test - if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - if(node->IsLeaf()) - { - RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _RayStab(node->GetPos()); - - if(ContactFound()) return; - - _RayStab(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for quantized AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_RayStab(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform Ray-AABB overlap test - if(!RayAABBOverlap(Center, Extents)) return; - - if(node->IsLeaf()) - { - RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _RayStab(node->GetPos()); - - if(ContactFound()) return; - - _RayStab(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_RayStab(const AABBNoLeafNode* node) -{ - // Perform Ray-AABB overlap test - if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - if(node->HasPosLeaf()) - { - RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) - } - else _RayStab(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) - { - RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) - } - else _RayStab(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for quantized no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_RayStab(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform Ray-AABB overlap test - if(!RayAABBOverlap(Center, Extents)) return; - - if(node->HasPosLeaf()) - { - RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) - } - else _RayStab(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) - { - RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) - } - else _RayStab(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive stabbing query for vanilla AABB trees. - * \param node [in] current collision node - * \param box_indices [out] indices of stabbed boxes - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void RayCollider::_RayStab(const AABBTreeNode* node, Container& box_indices) -{ - // Test the box against the ray - IcePoint Center, Extents; - node->GetAABB()->GetCenter(Center); - node->GetAABB()->GetExtents(Extents); - if(!RayAABBOverlap(Center, Extents)) return; - - if(node->IsLeaf()) - { - mFlags |= OPC_CONTACT; - box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); - } - else - { - _RayStab(node->GetPos(), box_indices); - _RayStab(node->GetNeg(), box_indices); - } -} diff --git a/contrib/Opcode/OPC_RayCollider.h b/contrib/Opcode/OPC_RayCollider.h deleted file mode 100644 index 393bc5f..0000000 --- a/contrib/Opcode/OPC_RayCollider.h +++ /dev/null @@ -1,225 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for a ray collider. - * \file OPC_RayCollider.h - * \author Pierre Terdiman - * \date June, 2, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_RAYCOLLIDER_H__ -#define __OPC_RAYCOLLIDER_H__ - - class OPCODE_API CollisionFace - { - public: - //! Constructor - inline_ CollisionFace() {} - //! Destructor - inline_ ~CollisionFace() {} - - udword mFaceID; //!< Index of touched face - float mDistance; //!< Distance from collider to hitpoint - float mU, mV; //!< Impact barycentric coordinates - }; - - class OPCODE_API CollisionFaces : private Container - { - public: - //! Constructor - CollisionFaces() {} - //! Destructor - ~CollisionFaces() {} - - inline_ udword GetNbFaces() const { return GetNbEntries()>>2; } - inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); } - - inline_ void Reset() { Container::Reset(); } - - inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); } - }; - -#ifdef OPC_RAYHIT_CALLBACK - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * User-callback, called by OPCODE to record a hit. - * \param hit [in] current hit - * \param user_data [in] user-defined data from SetCallback() - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - typedef void (*HitCallback) (const CollisionFace& hit, void* user_data); -#endif - - class OPCODE_API RayCollider : public Collider - { - public: - // Constructor / Destructor - RayCollider(); - virtual ~RayCollider(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Generic stabbing query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - in the user-provided destination array - * - * \param world_ray [in] stabbing ray in world space - * \param model [in] Opcode model to collide with - * \param world [in] model's world matrix, or null - * \param cache [in] a possibly cached face index, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null); - // - bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices); - // Settings - -#ifndef OPC_RAYHIT_CALLBACK - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Settings: enable or disable "closest hit" mode. - * \param flag [in] true to report closest hit only - * \see SetCulling(bool flag) - * \see SetMaxDist(float max_dist) - * \see SetDestination(StabbedFaces* sf) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetClosestHit(bool flag) { mClosestHit = flag; } -#endif - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Settings: enable or disable backface culling. - * \param flag [in] true to enable backface culling - * \see SetClosestHit(bool flag) - * \see SetMaxDist(float max_dist) - * \see SetDestination(StabbedFaces* sf) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetCulling(bool flag) { mCulling = flag; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Settings: sets the higher distance bound. - * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment) - * \see SetClosestHit(bool flag) - * \see SetCulling(bool flag) - * \see SetDestination(StabbedFaces* sf) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; } - -#ifdef OPC_RAYHIT_CALLBACK - inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; } - inline_ void SetUserData(void* user_data) { mUserData = user_data; } -#else - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Settings: sets the destination array for stabbed faces. - * \param cf [in] destination array, filled during queries - * \see SetClosestHit(bool flag) - * \see SetCulling(bool flag) - * \see SetMaxDist(float max_dist) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; } -#endif - // Stats - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Stats: gets the number of Ray-BV overlap tests after a collision query. - * \see GetNbRayPrimTests() - * \see GetNbIntersections() - * \return the number of Ray-BV tests performed during last query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Stats: gets the number of Ray-Triangle overlap tests after a collision query. - * \see GetNbRayBVTests() - * \see GetNbIntersections() - * \return the number of Ray-Triangle tests performed during last query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; } - - // In-out test - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests. - * \see GetNbRayBVTests() - * \see GetNbRayPrimTests() - * \return the number of valid intersections during last query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbIntersections() const { return mNbIntersections; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. - * \return null if everything is ok, else a string describing the problem - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(Collider) const char* ValidateSettings(); - - protected: - // Ray in local space - IcePoint mOrigin; //!< Ray origin - IcePoint mDir; //!< Ray direction (normalized) - IcePoint mFDir; //!< fabsf(mDir) - IcePoint mData, mData2; - // Stabbed faces - CollisionFace mStabbedFace; //!< Current stabbed face -#ifdef OPC_RAYHIT_CALLBACK - HitCallback mHitCallback; //!< Callback used to record a hit - void* mUserData; //!< User-defined data -#else - CollisionFaces* mStabbedFaces; //!< List of stabbed faces -#endif - // Stats - udword mNbRayBVTests; //!< Number of Ray-BV tests - udword mNbRayPrimTests; //!< Number of Ray-Primitive tests - // In-out test - udword mNbIntersections; //!< Number of valid intersections - // Dequantization coeffs - IcePoint mCenterCoeff; - IcePoint mExtentsCoeff; - // Settings - float mMaxDist; //!< Valid segment on the ray -#ifndef OPC_RAYHIT_CALLBACK - bool mClosestHit; //!< Report closest hit only -#endif - bool mCulling; //!< Stab culled faces or not - // Internal methods - void _SegmentStab(const AABBCollisionNode* node); - void _SegmentStab(const AABBNoLeafNode* node); - void _SegmentStab(const AABBQuantizedNode* node); - void _SegmentStab(const AABBQuantizedNoLeafNode* node); - void _SegmentStab(const AABBTreeNode* node, Container& box_indices); - void _RayStab(const AABBCollisionNode* node); - void _RayStab(const AABBNoLeafNode* node); - void _RayStab(const AABBQuantizedNode* node); - void _RayStab(const AABBQuantizedNoLeafNode* node); - void _RayStab(const AABBTreeNode* node, Container& box_indices); - // Overlap tests - inline_ BOOL RayAABBOverlap(const IcePoint& center, const IcePoint& extents); - inline_ BOOL SegmentAABBOverlap(const IcePoint& center, const IcePoint& extents); - inline_ BOOL RayTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); - // Init methods - BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null); - }; - -#endif // __OPC_RAYCOLLIDER_H__ diff --git a/contrib/Opcode/OPC_RayTriOverlap.h b/contrib/Opcode/OPC_RayTriOverlap.h deleted file mode 100644 index 405c7e1..0000000 --- a/contrib/Opcode/OPC_RayTriOverlap.h +++ /dev/null @@ -1,89 +0,0 @@ -#define LOCAL_EPSILON 0.000001f - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes a ray-triangle intersection test. - * Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection". - * It's been optimized a bit with integer code, and modified to return a non-intersection if distance from - * ray origin to triangle is negative. - * - * \param vert0 [in] triangle vertex - * \param vert1 [in] triangle vertex - * \param vert2 [in] triangle vertex - * \return true on overlap. mStabbedFace is filled with relevant info. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL RayCollider::RayTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2) -{ - // Stats - mNbRayPrimTests++; - - // Find vectors for two edges sharing vert0 - IcePoint edge1 = vert1 - vert0; - IcePoint edge2 = vert2 - vert0; - - // Begin calculating determinant - also used to calculate U parameter - IcePoint pvec = mDir^edge2; - - // If determinant is near zero, ray lies in plane of triangle - float det = edge1|pvec; - - if(mCulling) - { - if(det 0. So we can use integer cmp. - - // Calculate distance from vert0 to ray origin - IcePoint tvec = mOrigin - vert0; - - // Calculate U parameter and test bounds - mStabbedFace.mU = tvec|pvec; -// if(IR(u)&0x80000000 || u>det) return FALSE; - if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IR(det)) return FALSE; - - // Prepare to test V parameter - IcePoint qvec = tvec^edge1; - - // Calculate V parameter and test bounds - mStabbedFace.mV = mDir|qvec; - if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>det) return FALSE; - - // Calculate t, scale parameters, ray intersects triangle - mStabbedFace.mDistance = edge2|qvec; - // Det > 0 so we can early exit here - // Intersection IcePoint is valid if distance is positive (else it can just be a face behind the orig IcePoint) - if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; - // Else go on - float OneOverDet = 1.0f / det; - mStabbedFace.mDistance *= OneOverDet; - mStabbedFace.mU *= OneOverDet; - mStabbedFace.mV *= OneOverDet; - } - else - { - // the non-culling branch - if(det>-LOCAL_EPSILON && det1.0f) return FALSE; - if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IEEE_1_0) return FALSE; - - // prepare to test V parameter - IcePoint qvec = tvec^edge1; - - // Calculate V parameter and test bounds - mStabbedFace.mV = (mDir|qvec) * OneOverDet; - if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>1.0f) return FALSE; - - // Calculate t, ray intersects triangle - mStabbedFace.mDistance = (edge2|qvec) * OneOverDet; - // Intersection IcePoint is valid if distance is positive (else it can just be a face behind the orig IcePoint) - if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; - } - return TRUE; -} diff --git a/contrib/Opcode/OPC_Settings.h b/contrib/Opcode/OPC_Settings.h deleted file mode 100644 index 88d2ccd..0000000 --- a/contrib/Opcode/OPC_Settings.h +++ /dev/null @@ -1,49 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains compilation flags. - * \file OPC_Settings.h - * \author Pierre Terdiman - * \date May, 12, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_SETTINGS_H__ -#define __OPC_SETTINGS_H__ - - //! Use CPU comparisons (comment that line to use standard FPU compares) - #define OPC_CPU_COMPARE - - //! Use FCOMI / FCMOV on Pentium-Pro based processors (comment that line to use plain C++) - #define OPC_USE_FCOMI - - //! Use epsilon value in tri-tri overlap test - #define OPC_TRITRI_EPSILON_TEST - - //! Use tree-coherence or not [not implemented yet] -// #define OPC_USE_TREE_COHERENCE - - //! Use callbacks or direct pointers. Using callbacks might be a bit slower (but probably not much) -// #define OPC_USE_CALLBACKS - - //! Support triangle and vertex strides or not. Using strides might be a bit slower (but probably not much) -// #define OPC_USE_STRIDE - - //! Discard negative pointer in vanilla trees - #define OPC_NO_NEG_VANILLA_TREE - - //! Use a callback in the ray collider - #define OPC_RAYHIT_CALLBACK - - // NB: no compilation flag to enable/disable stats since they're actually needed in the box/box overlap test - -#endif //__OPC_SETTINGS_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_SphereAABBOverlap.h b/contrib/Opcode/OPC_SphereAABBOverlap.h deleted file mode 100644 index b7b4376..0000000 --- a/contrib/Opcode/OPC_SphereAABBOverlap.h +++ /dev/null @@ -1,128 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Sphere-AABB overlap test, based on Jim Arvo's code. - * \param center [in] box center - * \param extents [in] box extents - * \return TRUE on overlap - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL SphereCollider::SphereAABBOverlap(const IcePoint& center, const IcePoint& extents) -{ - // Stats - mNbVolumeBVTests++; - - float d = 0.0f; - - //find the square of the distance - //from the sphere to the box -#ifdef OLDIES - for(udword i=0;i<3;i++) - { - float tmp = mCenter[i] - center[i]; - float s = tmp + extents[i]; - - if(s<0.0f) d += s*s; - else - { - s = tmp - extents[i]; - if(s>0.0f) d += s*s; - } - } -#endif - -//#ifdef NEW_TEST - -// float tmp = mCenter.x - center.x; -// float s = tmp + extents.x; - - float tmp,s; - - tmp = mCenter.x - center.x; - s = tmp + extents.x; - - if(s<0.0f) - { - d += s*s; - if(d>mRadius2) return FALSE; - } - else - { - s = tmp - extents.x; - if(s>0.0f) - { - d += s*s; - if(d>mRadius2) return FALSE; - } - } - - tmp = mCenter.y - center.y; - s = tmp + extents.y; - - if(s<0.0f) - { - d += s*s; - if(d>mRadius2) return FALSE; - } - else - { - s = tmp - extents.y; - if(s>0.0f) - { - d += s*s; - if(d>mRadius2) return FALSE; - } - } - - tmp = mCenter.z - center.z; - s = tmp + extents.z; - - if(s<0.0f) - { - d += s*s; - if(d>mRadius2) return FALSE; - } - else - { - s = tmp - extents.z; - if(s>0.0f) - { - d += s*s; - if(d>mRadius2) return FALSE; - } - } -//#endif - -#ifdef OLDIES -// IcePoint Min = center - extents; -// IcePoint Max = center + extents; - - float d = 0.0f; - - //find the square of the distance - //from the sphere to the box - for(udword i=0;i<3;i++) - { -float Min = center[i] - extents[i]; - -// if(mCenter[i]Max[i]) - if(mCenter[i]>Max) - { - float s = mCenter[i] - Max; - d += s*s; - } - } - } -#endif - return d <= mRadius2; -} diff --git a/contrib/Opcode/OPC_SphereCollider.cpp b/contrib/Opcode/OPC_SphereCollider.cpp deleted file mode 100644 index 32af6e6..0000000 --- a/contrib/Opcode/OPC_SphereCollider.cpp +++ /dev/null @@ -1,726 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for a sphere collider. - * \file OPC_SphereCollider.cpp - * \author Pierre Terdiman - * \date June, 2, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains a sphere-vs-tree collider. - * This class performs a collision test between a sphere and an AABB tree. You can use this to do a standard player vs world collision, - * in a Nettle/Telemachos way. It doesn't suffer from all reported bugs in those two classic codes - the "new" one by Paul Nettle is a - * debuggued version I think. Collision response can be driven by reported collision data - it works extremely well for me. In sake of - * efficiency, all meshes (that is, all AABB trees) should of course also be kept in an extra hierarchical structure (octree, whatever). - * - * \class SphereCollider - * \author Pierre Terdiman - * \version 1.3 - * \date June, 2, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -#include "OPC_SphereAABBOverlap.h" -#include "OPC_SphereTriOverlap.h" - -#define SET_CONTACT(prim_index, flag) \ - /* Set contact status */ \ - mFlags |= flag; \ - mTouchedPrimitives->Add(prim_index); - -//! Sphere-triangle overlap test -#define SPHERE_PRIM(prim_index, flag) \ - /* Request vertices from the app */ \ - VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ - \ - /* Perform sphere-tri overlap test */ \ - if(SphereTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ - { \ - SET_CONTACT(prim_index, flag) \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SphereCollider::SphereCollider() -{ - mCenter.Zero(); - mRadius2 = 0.0f; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SphereCollider::~SphereCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] a sphere cache - * \param sphere [in] collision sphere in local space - * \param model [in] Opcode model to collide with - * \param worlds [in] sphere's world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds, const Matrix4x4* worldm) -{ - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, sphere, worlds, worldm)) return true; - - if(!model.HasLeafNodes()) - { - if(model.IsQuantized()) - { - const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); - else _Collide(Tree->GetNodes()); - } - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Initializes a collision query : - * - reset stats & contact status - * - setup matrices - * - check temporal coherence - * - * \param cache [in/out] a sphere cache - * \param sphere [in] sphere in local space - * \param worlds [in] sphere's world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return TRUE if we can return immediately - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOL SphereCollider::InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds, const Matrix4x4* worldm) -{ - // 1) Call the base method - VolumeCollider::InitQuery(); - - // 2) Compute sphere in model space: - // - Precompute R^2 - mRadius2 = sphere.mRadius * sphere.mRadius; - // - Compute center position - mCenter = sphere.mCenter; - // -> to world space - if(worlds) mCenter *= *worlds; - // -> to model space - if(worldm) - { - // Invert model matrix - Matrix4x4 InvWorldM; - InvertPRMatrix(InvWorldM, *worldm); - - mCenter *= InvWorldM; - } - - // 3) Setup destination pointer - mTouchedPrimitives = &cache.TouchedPrimitives; - - // 4) Special case: 1-triangle meshes [Opcode 1.3] - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - if(!SkipPrimitiveTests()) - { - // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. - mTouchedPrimitives->Reset(); - - // Perform overlap test between the unique triangle and the sphere (and set contact status if needed) - SPHERE_PRIM(udword(0), OPC_CONTACT) - - // Return immediately regardless of status - return TRUE; - } - } - - // 5) Check temporal coherence : - if(TemporalCoherenceEnabled()) - { - // Here we use temporal coherence - // => check results from previous frame before performing the collision query - if(FirstContactEnabled()) - { - // We're only interested in the first contact found => test the unique previously touched face - if(mTouchedPrimitives->GetNbEntries()) - { - // Get index of previously touched face = the first entry in the array - udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); - - // Then reset the array: - // - if the overlap test below is successful, the index we'll get added back anyway - // - if it isn't, then the array should be reset anyway for the normal query - mTouchedPrimitives->Reset(); - - // Perform overlap test between the cached triangle and the sphere (and set contact status if needed) - SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) - - // Return immediately if possible - if(GetContactStatus()) return TRUE; - } - // else no face has been touched during previous query - // => we'll have to perform a normal query - } - else - { - // We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious): - float r = sqrtf(cache.FatRadius2) - sphere.mRadius; - if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r) - { - // - if N is included in P, return previous list - // => we simply leave the list (mTouchedFaces) unchanged - - // Set contact status if needed - if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; - - // In any case we don't need to do a query - return TRUE; - } - else - { - // - else do the query using a fat N - - // Reset cache since we'll about to perform a real query - mTouchedPrimitives->Reset(); - - // Make a fat sphere so that coherence will work for subsequent frames - mRadius2 *= cache.FatCoeff; -// mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff); - - // Update cache with query data (signature for cached faces) - cache.Center = mCenter; - cache.FatRadius2 = mRadius2; - } - } - } - else - { - // Here we don't use temporal coherence => do a normal query - mTouchedPrimitives->Reset(); - } - - return FALSE; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Collision query for vanilla AABB trees. - * \param cache [in/out] a sphere cache - * \param sphere [in] collision sphere in world space - * \param tree [in] AABB tree - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree) -{ - // This is typically called for a scene tree, full of -AABBs-, not full of triangles. - // So we don't really have "primitives" to deal with. Hence it doesn't work with - // "FirstContact" + "TemporalCoherence". - ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); - - // Checkings - if(!tree) return false; - - // Init collision query - if(InitQuery(cache, sphere)) return true; - - // Perform collision query - _Collide(tree); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Checks the sphere completely contains the box. In which case we can end the query sooner. - * \param bc [in] box center - * \param be [in] box extents - * \return true if the sphere contains the whole box - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL SphereCollider::SphereContainsBox(const IcePoint& bc, const IcePoint& be) -{ - // I assume if all 8 box vertices are inside the sphere, so does the whole box. - // Sounds ok but maybe there's a better way? - IcePoint p; - p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z+be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; - p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; - p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; - p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; - p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z-be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; - p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; - p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; - p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; - - return TRUE; -} - -#define TEST_BOX_IN_SPHERE(center, extents) \ - if(SphereContainsBox(center, extents)) \ - { \ - /* Set contact status */ \ - mFlags |= OPC_CONTACT; \ - _Dump(node); \ - return; \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_Collide(const AABBCollisionNode* node) -{ - // Perform Sphere-AABB overlap test - if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->IsLeaf()) - { - SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos()); - - if(ContactFound()) return; - - _Collide(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) -{ - // Perform Sphere-AABB overlap test - if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_Collide(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform Sphere-AABB overlap test - if(!SphereAABBOverlap(Center, Extents)) return; - - TEST_BOX_IN_SPHERE(Center, Extents) - - if(node->IsLeaf()) - { - SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _Collide(node->GetPos()); - - if(ContactFound()) return; - - _Collide(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform Sphere-AABB overlap test - if(!SphereAABBOverlap(Center, Extents)) return; - - TEST_BOX_IN_SPHERE(Center, Extents) - - if(node->IsLeaf()) - { - SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) - } - else - { - _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - _CollideNoPrimitiveTest(node->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_Collide(const AABBNoLeafNode* node) -{ - // Perform Sphere-AABB overlap test - if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) -{ - // Perform Sphere-AABB overlap test - if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; - - TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) - - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_Collide(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform Sphere-AABB overlap test - if(!SphereAABBOverlap(Center, Extents)) return; - - TEST_BOX_IN_SPHERE(Center, Extents) - - if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } - else _Collide(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } - else _Collide(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) -{ - // Dequantize box - const QuantizedAABB& Box = node->mAABB; - const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); - const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); - - // Perform Sphere-AABB overlap test - if(!SphereAABBOverlap(Center, Extents)) return; - - TEST_BOX_IN_SPHERE(Center, Extents) - - if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetPos()); - - if(ContactFound()) return; - - if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } - else _CollideNoPrimitiveTest(node->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for vanilla AABB trees. - * \param node [in] current collision node - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void SphereCollider::_Collide(const AABBTreeNode* node) -{ - // Perform Sphere-AABB overlap test - IcePoint Center, Extents; - node->GetAABB()->GetCenter(Center); - node->GetAABB()->GetExtents(Extents); - if(!SphereAABBOverlap(Center, Extents)) return; - - if(node->IsLeaf() || SphereContainsBox(Center, Extents)) - { - mFlags |= OPC_CONTACT; - mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); - } - else - { - _Collide(node->GetPos()); - _Collide(node->GetNeg()); - } -} - - - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridSphereCollider::HybridSphereCollider() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -HybridSphereCollider::~HybridSphereCollider() -{ -} - -bool HybridSphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds, const Matrix4x4* worldm) -{ - // We don't want primitive tests here! - mFlags |= OPC_NO_PRIMITIVE_TESTS; - - // Checkings - if(!Setup(&model)) return false; - - // Init collision query - if(InitQuery(cache, sphere, worlds, worldm)) return true; - - // Special case for 1-leaf trees - if(mCurrentModel && mCurrentModel->HasSingleNode()) - { - // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles - udword Nb = mIMesh->GetNbTriangles(); - - // Loop through all triangles - for(udword i=0;imCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - else - { - const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - } - else - { - if(model.IsQuantized()) - { - const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); - - // Setup dequantization coeffs - mCenterCoeff = Tree->mCenterCoeff; - mExtentsCoeff = Tree->mExtentsCoeff; - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - else - { - const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); - - // Perform collision query - we don't want primitive tests here! - _CollideNoPrimitiveTest(Tree->GetNodes()); - } - } - - // We only have a list of boxes so far - if(GetContactStatus()) - { - // Reset contact status, since it currently only reflects collisions with leaf boxes - Collider::InitQuery(); - - // Change dest container so that we can use built-in overlap tests and get collided primitives - cache.TouchedPrimitives.Reset(); - mTouchedPrimitives = &cache.TouchedPrimitives; - - // Read touched leaf boxes - udword Nb = mTouchedBoxes.GetNbEntries(); - const udword* Touched = mTouchedBoxes.GetEntries(); - - const LeafTriangles* LT = model.GetLeafTriangles(); - const udword* Indices = model.GetIndices(); - - // Loop through touched leaves - while(Nb--) - { - const LeafTriangles& CurrentLeaf = LT[*Touched++]; - - // Each leaf box has a set of triangles - udword NbTris = CurrentLeaf.GetNbTriangles(); - if(Indices) - { - const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; - - // Loop through triangles and test each of them - while(NbTris--) - { - udword TriangleIndex = *T++; - SPHERE_PRIM(TriangleIndex, OPC_CONTACT) - } - } - else - { - udword BaseIndex = CurrentLeaf.GetTriangleIndex(); - - // Loop through triangles and test each of them - while(NbTris--) - { - udword TriangleIndex = BaseIndex++; - SPHERE_PRIM(TriangleIndex, OPC_CONTACT) - } - } - } - } - - return true; -} diff --git a/contrib/Opcode/OPC_SphereCollider.h b/contrib/Opcode/OPC_SphereCollider.h deleted file mode 100644 index 095824a..0000000 --- a/contrib/Opcode/OPC_SphereCollider.h +++ /dev/null @@ -1,96 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for a sphere collider. - * \file OPC_SphereCollider.h - * \author Pierre Terdiman - * \date June, 2, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_SPHERECOLLIDER_H__ -#define __OPC_SPHERECOLLIDER_H__ - - struct OPCODE_API SphereCache : VolumeCache - { - SphereCache() : Center(0.0f,0.0f,0.0f), FatRadius2(0.0f), FatCoeff(1.1f) {} - ~SphereCache() {} - - // Cached faces signature - IcePoint Center; //!< Sphere used when performing the query resulting in cached faces - float FatRadius2; //!< Sphere used when performing the query resulting in cached faces - // User settings - float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere - }; - - class OPCODE_API SphereCollider : public VolumeCollider - { - public: - // Constructor / Destructor - SphereCollider(); - virtual ~SphereCollider(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Generic collision query for generic OPCODE models. After the call, access the results: - * - with GetContactStatus() - * - with GetNbTouchedPrimitives() - * - with GetTouchedPrimitives() - * - * \param cache [in/out] a sphere cache - * \param sphere [in] collision sphere in local space - * \param model [in] Opcode model to collide with - * \param worlds [in] sphere's world matrix, or null - * \param worldm [in] model's world matrix, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); - - // - bool Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree); - protected: - // Sphere in model space - IcePoint mCenter; //!< Sphere center - float mRadius2; //!< Sphere radius squared - // Internal methods - void _Collide(const AABBCollisionNode* node); - void _Collide(const AABBNoLeafNode* node); - void _Collide(const AABBQuantizedNode* node); - void _Collide(const AABBQuantizedNoLeafNode* node); - void _Collide(const AABBTreeNode* node); - void _CollideNoPrimitiveTest(const AABBCollisionNode* node); - void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); - void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); - void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); - // Overlap tests - inline_ BOOL SphereContainsBox(const IcePoint& bc, const IcePoint& be); - inline_ BOOL SphereAABBOverlap(const IcePoint& center, const IcePoint& extents); - BOOL SphereTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); - // Init methods - BOOL InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); - }; - - class OPCODE_API HybridSphereCollider : public SphereCollider - { - public: - // Constructor / Destructor - HybridSphereCollider(); - virtual ~HybridSphereCollider(); - - bool Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); - protected: - Container mTouchedBoxes; - }; - -#endif // __OPC_SPHERECOLLIDER_H__ diff --git a/contrib/Opcode/OPC_SphereTriOverlap.h b/contrib/Opcode/OPC_SphereTriOverlap.h deleted file mode 100644 index 012d9ea..0000000 --- a/contrib/Opcode/OPC_SphereTriOverlap.h +++ /dev/null @@ -1,187 +0,0 @@ - -// This is collision detection. If you do another distance test for collision *response*, -// if might be useful to simply *skip* the test below completely, and report a collision. -// - if sphere-triangle overlap, result is ok -// - if they don't, we'll discard them during collision response with a similar test anyway -// Overall this approach should run faster. - -// Original code by David Eberly in Magic. -BOOL SphereCollider::SphereTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2) -{ - // Stats - mNbVolumePrimTests++; - - // Early exit if one of the vertices is inside the sphere - IcePoint kDiff = vert2 - mCenter; - float fC = kDiff.SquareMagnitude(); - if(fC <= mRadius2) return TRUE; - - kDiff = vert1 - mCenter; - fC = kDiff.SquareMagnitude(); - if(fC <= mRadius2) return TRUE; - - kDiff = vert0 - mCenter; - fC = kDiff.SquareMagnitude(); - if(fC <= mRadius2) return TRUE; - - // Else do the full distance test - IcePoint TriEdge0 = vert1 - vert0; - IcePoint TriEdge1 = vert2 - vert0; - -//IcePoint kDiff = vert0 - mCenter; - float fA00 = TriEdge0.SquareMagnitude(); - float fA01 = TriEdge0 | TriEdge1; - float fA11 = TriEdge1.SquareMagnitude(); - float fB0 = kDiff | TriEdge0; - float fB1 = kDiff | TriEdge1; -//float fC = kDiff.SquareMagnitude(); - float fDet = fabsf(fA00*fA11 - fA01*fA01); - float u = fA01*fB1-fA11*fB0; - float v = fA01*fB0-fA00*fB1; - float SqrDist; - - if(u + v <= fDet) - { - if(u < 0.0f) - { - if(v < 0.0f) // region 4 - { - if(fB0 < 0.0f) - { -// v = 0.0f; - if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } - else { u = -fB0/fA00; SqrDist = fB0*u+fC; } - } - else - { -// u = 0.0f; - if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } - else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } - else { v = -fB1/fA11; SqrDist = fB1*v+fC; } - } - } - else // region 3 - { -// u = 0.0f; - if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } - else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } - else { v = -fB1/fA11; SqrDist = fB1*v+fC; } - } - } - else if(v < 0.0f) // region 5 - { -// v = 0.0f; - if(fB0>=0.0f) { /*u = 0.0f;*/ SqrDist = fC; } - else if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } - else { u = -fB0/fA00; SqrDist = fB0*u+fC; } - } - else // region 0 - { - // minimum at interior IcePoint - if(fDet==0.0f) - { -// u = 0.0f; -// v = 0.0f; - SqrDist = MAX_FLOAT; - } - else - { - float fInvDet = 1.0f/fDet; - u *= fInvDet; - v *= fInvDet; - SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; - } - } - } - else - { - float fTmp0, fTmp1, fNumer, fDenom; - - if(u < 0.0f) // region 2 - { - fTmp0 = fA01 + fB0; - fTmp1 = fA11 + fB1; - if(fTmp1 > fTmp0) - { - fNumer = fTmp1 - fTmp0; - fDenom = fA00-2.0f*fA01+fA11; - if(fNumer >= fDenom) - { -// u = 1.0f; -// v = 0.0f; - SqrDist = fA00+2.0f*fB0+fC; - } - else - { - u = fNumer/fDenom; - v = 1.0f - u; - SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; - } - } - else - { -// u = 0.0f; - if(fTmp1 <= 0.0f) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } - else if(fB1 >= 0.0f) { /*v = 0.0f;*/ SqrDist = fC; } - else { v = -fB1/fA11; SqrDist = fB1*v+fC; } - } - } - else if(v < 0.0f) // region 6 - { - fTmp0 = fA01 + fB1; - fTmp1 = fA00 + fB0; - if(fTmp1 > fTmp0) - { - fNumer = fTmp1 - fTmp0; - fDenom = fA00-2.0f*fA01+fA11; - if(fNumer >= fDenom) - { -// v = 1.0f; -// u = 0.0f; - SqrDist = fA11+2.0f*fB1+fC; - } - else - { - v = fNumer/fDenom; - u = 1.0f - v; - SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; - } - } - else - { -// v = 0.0f; - if(fTmp1 <= 0.0f) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } - else if(fB0 >= 0.0f) { /*u = 0.0f;*/ SqrDist = fC; } - else { u = -fB0/fA00; SqrDist = fB0*u+fC; } - } - } - else // region 1 - { - fNumer = fA11 + fB1 - fA01 - fB0; - if(fNumer <= 0.0f) - { -// u = 0.0f; -// v = 1.0f; - SqrDist = fA11+2.0f*fB1+fC; - } - else - { - fDenom = fA00-2.0f*fA01+fA11; - if(fNumer >= fDenom) - { -// u = 1.0f; -// v = 0.0f; - SqrDist = fA00+2.0f*fB0+fC; - } - else - { - u = fNumer/fDenom; - v = 1.0f - u; - SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; - } - } - } - } - - return fabsf(SqrDist) < mRadius2; -} diff --git a/contrib/Opcode/OPC_SweepAndPrune.cpp b/contrib/Opcode/OPC_SweepAndPrune.cpp deleted file mode 100644 index e56e7ab..0000000 --- a/contrib/Opcode/OPC_SweepAndPrune.cpp +++ /dev/null @@ -1,664 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) - * \file OPC_SweepAndPrune.cpp - * \author Pierre Terdiman - * \date January, 29, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -inline_ void Sort(udword& id0, udword& id1) -{ - if(id0>id1) Swap(id0, id1); -} - - class Opcode::SAP_Element - { - public: - inline_ SAP_Element() {} - inline_ SAP_Element(udword id, SAP_Element* next) : mID(id), mNext(next) {} - inline_ ~SAP_Element() {} - - udword mID; - SAP_Element* mNext; - }; - - class Opcode::SAP_Box - { - public: - SAP_EndPoint* Min[3]; - SAP_EndPoint* Max[3]; - }; - - class Opcode::SAP_EndPoint - { - public: - float Value; // Min or Max value - SAP_EndPoint* Previous; // Previous EndPoint whose Value is smaller than ours (or null) - SAP_EndPoint* Next; // Next EndPoint whose Value is greater than ours (or null) - udword Data; // Parent box ID *2 | MinMax flag - - inline_ void SetData(udword box_id, BOOL is_max) { Data = (box_id<<1)|is_max; } - inline_ BOOL IsMax() const { return Data & 1; } - inline_ udword GetBoxID() const { return Data>>1; } - - inline_ void InsertAfter(SAP_EndPoint* element) - { - if(this!=element && this!=element->Next) - { - // Remove - if(Previous) Previous->Next = Next; - if(Next) Next->Previous = Previous; - - // Insert - Next = element->Next; - if(Next) Next->Previous = this; - - element->Next = this; - Previous = element; - } - } - - inline_ void InsertBefore(SAP_EndPoint* element) - { - if(this!=element && this!=element->Previous) - { - // Remove - if(Previous) Previous->Next = Next; - if(Next) Next->Previous = Previous; - - // Insert - Previous = element->Previous; - element->Previous = this; - - Next = element; - if(Previous) Previous->Next = this; - } - } - }; - - - - - - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SAP_PairData::SAP_PairData() : - mNbElements (0), - mNbUsedElements (0), - mElementPool (null), - mFirstFree (null), - mNbObjects (0), - mArray (null) -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SAP_PairData::~SAP_PairData() -{ - Release(); -} - -void SAP_PairData::Release() -{ - mNbElements = 0; - mNbUsedElements = 0; - mNbObjects = 0; - DELETEARRAY(mElementPool); - DELETEARRAY(mArray); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Initializes. - * \param nb_objects [in] - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool SAP_PairData::Init(udword nb_objects) -{ - // Make sure everything has been released - Release(); - if(!nb_objects) return false; - - mArray = new SAP_Element*[nb_objects]; - CHECKALLOC(mArray); - ZeroMemory(mArray, nb_objects*sizeof(SAP_Element*)); - mNbObjects = nb_objects; - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Remaps a pointer when pool gets resized. - * \param element [in/out] remapped element - * \param delta [in] offset in bytes - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ void Remap(SAP_Element*& element, udword delta) -{ - if(element) element = (SAP_Element*)(udword(element) + delta); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Gets a free element in the pool. - * \param id [in] element id - * \param next [in] next element - * \param remap [out] possible remapping offset - * \return the new element - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SAP_Element* SAP_PairData::GetFreeElem(udword id, SAP_Element* next, udword* remap) -{ - if(remap) *remap = 0; - - SAP_Element* FreeElem; - if(mFirstFree) - { - // Recycle - FreeElem = mFirstFree; - mFirstFree = mFirstFree->mNext; // First free = next free (or null) - } - else - { - if(mNbUsedElements==mNbElements) - { - // Resize - mNbElements = mNbElements ? (mNbElements<<1) : 2; - - SAP_Element* NewElems = new SAP_Element[mNbElements]; - - if(mNbUsedElements) CopyMemory(NewElems, mElementPool, mNbUsedElements*sizeof(SAP_Element)); - - // Remap everything - { - udword Delta = udword(NewElems) - udword(mElementPool); - - for(udword i=0;imID = id; - FreeElem->mNext = next; - - return FreeElem; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Frees an element of the pool. - * \param elem [in] element to free/recycle - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ void SAP_PairData::FreeElem(SAP_Element* elem) -{ - elem->mNext = mFirstFree; // Next free - mFirstFree = elem; -} - -// Add a pair to the set. -void SAP_PairData::AddPair(udword id1, udword id2) -{ - // Order the ids - Sort(id1, id2); - - ASSERT(id1=mNbObjects) return; - - // Select the right list from "mArray". - SAP_Element* Current = mArray[id1]; - - if(!Current) - { - // Empty slot => create new element - mArray[id1] = GetFreeElem(id2, null); - } - else if(Current->mID>id2) - { - // The list is not empty but all elements are greater than id2 => insert id2 in the front. - mArray[id1] = GetFreeElem(id2, mArray[id1]); - } - else - { - // Else find the correct location in the sorted list (ascending order) and insert id2 there. - while(Current->mNext) - { - if(Current->mNext->mID > id2) break; - - Current = Current->mNext; - } - - if(Current->mID==id2) return; // The pair already exists - -// Current->mNext = GetFreeElem(id2, Current->mNext); - udword Delta; - SAP_Element* E = GetFreeElem(id2, Current->mNext, &Delta); - if(Delta) Remap(Current, Delta); - Current->mNext = E; - } -} - -// Delete a pair from the set. -void SAP_PairData::RemovePair(udword id1, udword id2) -{ - // Order the ids. - Sort(id1, id2); - - // Exit if the pair doesn't exist in the set - if(id1>=mNbObjects) return; - - // Otherwise, select the correct list. - SAP_Element* Current = mArray[id1]; - - // If this list is empty, the pair doesn't exist. - if(!Current) return; - - // Otherwise, if id2 is the first element, delete it. - if(Current->mID==id2) - { - mArray[id1] = Current->mNext; - FreeElem(Current); - } - else - { - // If id2 is not the first element, start traversing the sorted list. - while(Current->mNext) - { - // If we have moved too far away without hitting id2, then the pair doesn't exist - if(Current->mNext->mID > id2) return; - - // Otherwise, delete id2. - if(Current->mNext->mID == id2) - { - SAP_Element* Temp = Current->mNext; - Current->mNext = Temp->mNext; - FreeElem(Temp); - return; - } - Current = Current->mNext; - } - } -} - -void SAP_PairData::DumpPairs(Pairs& pairs) const -{ - // ### Ugly and slow - for(udword i=0;imIDmID); - Current = Current->mNext; - } - } -} - -void SAP_PairData::DumpPairs(PairCallback callback, void* user_data) const -{ - if(!callback) return; - - // ### Ugly and slow - for(udword i=0;imIDmID, user_data)) return; - Current = Current->mNext; - } - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Constructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SweepAndPrune::SweepAndPrune() -{ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Destructor. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SweepAndPrune::~SweepAndPrune() -{ -} - -void SweepAndPrune::GetPairs(Pairs& pairs) const -{ - mPairs.DumpPairs(pairs); -} - -void SweepAndPrune::GetPairs(PairCallback callback, void* user_data) const -{ - mPairs.DumpPairs(callback, user_data); -} - -bool SweepAndPrune::Init(udword nb_objects, const AABB** boxes) -{ - // 1) Create sorted lists - mNbObjects = nb_objects; - - mBoxes = new SAP_Box[nb_objects]; -// for(udword i=0;iGetMin(Axis); - Data[i*2+1] = boxes[i]->GetMax(Axis); - } - RadixSort RS; - const udword* Sorted = RS.Sort(Data, nb_objects*2).GetRanks(); - - SAP_EndPoint* PreviousEndPoint = null; - - for(udword i=0;i>1; - - ASSERT(BoxIndexValue = SortedCoord; -// CurrentEndPoint->IsMax = SortedIndex&1; // ### could be implicit ? -// CurrentEndPoint->ID = BoxIndex; // ### could be implicit ? - CurrentEndPoint->SetData(BoxIndex, SortedIndex&1); // ### could be implicit ? - CurrentEndPoint->Previous = PreviousEndPoint; - CurrentEndPoint->Next = null; - if(PreviousEndPoint) PreviousEndPoint->Next = CurrentEndPoint; - - if(CurrentEndPoint->IsMax()) mBoxes[BoxIndex].Max[Axis] = CurrentEndPoint; - else mBoxes[BoxIndex].Min[Axis] = CurrentEndPoint; - - PreviousEndPoint = CurrentEndPoint; - } - } - - DELETEARRAY(Data); - - CheckListsIntegrity(); - - // 2) Quickly find starting pairs - - mPairs.Init(nb_objects); - - { - Pairs P; - CompleteBoxPruning(nb_objects, boxes, P, Axes(AXES_XZY)); - for(udword i=0;iid0; - udword id1 = PP->id1; - - if(id0!=id1 && boxes[id0]->Intersect(*boxes[id1])) - { - mPairs.AddPair(id0, id1); - } - else ASSERT(0); - } - } - - return true; -} - -bool SweepAndPrune::CheckListsIntegrity() -{ - for(udword Axis=0;Axis<3;Axis++) - { - // Find list head - SAP_EndPoint* Current = mList[Axis]; - while(Current->Previous) Current = Current->Previous; - - udword Nb = 0; - - SAP_EndPoint* Previous = null; - while(Current) - { - Nb++; - - if(Previous) - { - ASSERT(Previous->Value <= Current->Value); - if(Previous->Value > Current->Value) return false; - } - - ASSERT(Current->Previous==Previous); - if(Current->Previous!=Previous) return false; - - Previous = Current; - Current = Current->Next; - } - - ASSERT(Nb==mNbObjects*2); - } - return true; -} - -inline_ BOOL Intersect(const AABB& a, const SAP_Box& b) -{ - if(b.Max[0]->Value < a.GetMin(0) || a.GetMax(0) < b.Min[0]->Value - || b.Max[1]->Value < a.GetMin(1) || a.GetMax(1) < b.Min[1]->Value - || b.Max[2]->Value < a.GetMin(2) || a.GetMax(2) < b.Min[2]->Value) return FALSE; - - return TRUE; -} - - - -bool SweepAndPrune::UpdateObject(udword i, const AABB& box) -{ - for(udword Axis=0;Axis<3;Axis++) - { -// udword Base = (udword)&mList[Axis][0]; - - // Update min - { - SAP_EndPoint* const CurrentMin = mBoxes[i].Min[Axis]; - ASSERT(!CurrentMin->IsMax()); - - const float Limit = box.GetMin(Axis); - if(Limit == CurrentMin->Value) - { - } - else if(Limit < CurrentMin->Value) - { - CurrentMin->Value = Limit; - - // Min is moving left: - SAP_EndPoint* NewPos = CurrentMin; - ASSERT(NewPos); - - SAP_EndPoint* tmp; - while((tmp = NewPos->Previous) && tmp->Value > Limit) - { - NewPos = tmp; - - if(NewPos->IsMax()) - { - // Our min passed a max => start overlap - //udword SortedIndex = (udword(CurrentMin) - Base)/sizeof(NS_EndPoint); - const udword id0 = CurrentMin->GetBoxID(); - const udword id1 = NewPos->GetBoxID(); - - if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1); - } - } - - CurrentMin->InsertBefore(NewPos); - } - else// if(Limit > CurrentMin->Value) - { - CurrentMin->Value = Limit; - - // Min is moving right: - SAP_EndPoint* NewPos = CurrentMin; - ASSERT(NewPos); - - SAP_EndPoint* tmp; - while((tmp = NewPos->Next) && tmp->Value < Limit) - { - NewPos = tmp; - - if(NewPos->IsMax()) - { - // Our min passed a max => stop overlap - const udword id0 = CurrentMin->GetBoxID(); - const udword id1 = NewPos->GetBoxID(); - - if(id0!=id1) mPairs.RemovePair(id0, id1); - } - } - - CurrentMin->InsertAfter(NewPos); - } - } - - // Update max - { - SAP_EndPoint* const CurrentMax = mBoxes[i].Max[Axis]; - ASSERT(CurrentMax->IsMax()); - - const float Limit = box.GetMax(Axis); - if(Limit == CurrentMax->Value) - { - } - else if(Limit > CurrentMax->Value) - { - CurrentMax->Value = Limit; - - // Max is moving right: - SAP_EndPoint* NewPos = CurrentMax; - ASSERT(NewPos); - - SAP_EndPoint* tmp; - while((tmp = NewPos->Next) && tmp->Value < Limit) - { - NewPos = tmp; - - if(!NewPos->IsMax()) - { - // Our max passed a min => start overlap - const udword id0 = CurrentMax->GetBoxID(); - const udword id1 = NewPos->GetBoxID(); - - if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1); - } - } - - CurrentMax->InsertAfter(NewPos); - } - else// if(Limit < CurrentMax->Value) - { - CurrentMax->Value = Limit; - - // Max is moving left: - SAP_EndPoint* NewPos = CurrentMax; - ASSERT(NewPos); - - SAP_EndPoint* tmp; - while((tmp = NewPos->Previous) && tmp->Value > Limit) - { - NewPos = tmp; - - if(!NewPos->IsMax()) - { - // Our max passed a min => stop overlap - const udword id0 = CurrentMax->GetBoxID(); - const udword id1 = NewPos->GetBoxID(); - - if(id0!=id1) mPairs.RemovePair(id0, id1); - } - } - - CurrentMax->InsertBefore(NewPos); - } - } - } - - return true; -} diff --git a/contrib/Opcode/OPC_SweepAndPrune.h b/contrib/Opcode/OPC_SweepAndPrune.h deleted file mode 100644 index cbb87ac..0000000 --- a/contrib/Opcode/OPC_SweepAndPrune.h +++ /dev/null @@ -1,86 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) - * \file OPC_SweepAndPrune.h - * \author Pierre Terdiman - * \date January, 29, 2000 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_SWEEPANDPRUNE_H__ -#define __OPC_SWEEPANDPRUNE_H__ - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * User-callback, called by OPCODE for each colliding pairs. - * \param id0 [in] id of colliding object - * \param id1 [in] id of colliding object - * \param user_data [in] user-defined data - * \return TRUE to continue enumeration - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - typedef BOOL (*PairCallback) (udword id0, udword id1, void* user_data); - - class SAP_Element; - class SAP_EndPoint; - class SAP_Box; - - class OPCODE_API SAP_PairData - { - public: - SAP_PairData(); - ~SAP_PairData(); - - bool Init(udword nb_objects); - - void AddPair(udword id1, udword id2); - void RemovePair(udword id1, udword id2); - - void DumpPairs(Pairs& pairs) const; - void DumpPairs(PairCallback callback, void* user_data) const; - private: - udword mNbElements; //!< Total number of elements in the pool - udword mNbUsedElements; //!< Number of used elements - SAP_Element* mElementPool; //!< Array of mNbElements elements - SAP_Element* mFirstFree; //!< First free element in the pool - - udword mNbObjects; //!< Max number of objects we can handle - SAP_Element** mArray; //!< Pointers to pool - // Internal methods - SAP_Element* GetFreeElem(udword id, SAP_Element* next, udword* remap=null); - inline_ void FreeElem(SAP_Element* elem); - void Release(); - }; - - class OPCODE_API SweepAndPrune - { - public: - SweepAndPrune(); - ~SweepAndPrune(); - - bool Init(udword nb_objects, const AABB** boxes); - bool UpdateObject(udword i, const AABB& box); - - void GetPairs(Pairs& pairs) const; - void GetPairs(PairCallback callback, void* user_data) const; - private: - SAP_PairData mPairs; - - udword mNbObjects; - SAP_Box* mBoxes; - SAP_EndPoint* mList[3]; - // Internal methods - bool CheckListsIntegrity(); - }; - -#endif //__OPC_SWEEPANDPRUNE_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_TreeBuilders.cpp b/contrib/Opcode/OPC_TreeBuilders.cpp deleted file mode 100644 index 89dd93b..0000000 --- a/contrib/Opcode/OPC_TreeBuilders.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for tree builders. - * \file OPC_TreeBuilders.cpp - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A builder for AABB-trees of vertices. - * - * \class AABBTreeOfVerticesBuilder - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A builder for AABB-trees of AABBs. - * - * \class AABBTreeOfAABBsBuilder - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A builder for AABB-trees of triangles. - * - * \class AABBTreeOfTrianglesBuilder - * \author Pierre Terdiman - * \version 1.3 - * \date March, 20, 2001 -*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -using namespace Opcode; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the AABB of a set of primitives. - * \param primitives [in] list of indices of primitives - * \param nb_prims [in] number of indices - * \param global_box [out] global AABB enclosing the set of input primitives - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTreeOfAABBsBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const -{ - // Checkings - if(!primitives || !nb_prims) return false; - - // Initialize global box - global_box = mAABBArray[primitives[0]]; - - // Loop through boxes - for(udword i=1;iGetTriangle(VP, *primitives++); - // Update global box - Min.Min(*VP.Vertex[0]).Min(*VP.Vertex[1]).Min(*VP.Vertex[2]); - Max.Max(*VP.Vertex[0]).Max(*VP.Vertex[1]).Max(*VP.Vertex[2]); - } - global_box.SetMinMax(Min, Max); - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the splitting value along a given axis for a given primitive. - * \param index [in] index of the primitive to split - * \param axis [in] axis index (0,1,2) - * \return splitting value - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float AABBTreeOfTrianglesBuilder::GetSplittingValue(udword index, udword axis) const -{ -/* // Compute center of triangle - IcePoint Center; - mTriList[index].Center(mVerts, Center); - // Return value - return Center[axis];*/ - - // Compute correct component from center of triangle -// return (mVerts[mTriList[index].mVRef[0]][axis] -// +mVerts[mTriList[index].mVRef[1]][axis] -// +mVerts[mTriList[index].mVRef[2]][axis])*INV3; - - VertexPointers VP; - mIMesh->GetTriangle(VP, index); - - // Compute correct component from center of triangle - return ((*VP.Vertex[0])[axis] - +(*VP.Vertex[1])[axis] - +(*VP.Vertex[2])[axis])*INV3; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the splitting value along a given axis for a given node. - * \param primitives [in] list of indices of primitives - * \param nb_prims [in] number of indices - * \param global_box [in] global AABB enclosing the set of input primitives - * \param axis [in] axis index (0,1,2) - * \return splitting value - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float AABBTreeOfTrianglesBuilder::GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const -{ - if(mSettings.mRules&SPLIT_GEOM_CENTER) - { - // Loop through triangles - float SplitValue = 0.0f; - VertexPointers VP; - for(udword i=0;iGetTriangle(VP, primitives[i]); - // Update split value - SplitValue += (*VP.Vertex[0])[axis]; - SplitValue += (*VP.Vertex[1])[axis]; - SplitValue += (*VP.Vertex[2])[axis]; - } - return SplitValue / float(nb_prims*3); - } - else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Computes the AABB of a set of primitives. - * \param primitives [in] list of indices of primitives - * \param nb_prims [in] number of indices - * \param global_box [out] global AABB enclosing the set of input primitives - * \return true if success - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTreeOfVerticesBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const -{ - // Checkings - if(!primitives || !nb_prims) return false; - - // Initialize global box - global_box.SetEmpty(); - - // Loop through vertices - for(udword i=0;iHasLeafNodes()!=cache.Model1->HasLeafNodes()) return false; - if(cache.Model0->IsQuantized()!=cache.Model1->IsQuantized()) return false; - - /* - - Rules: - - perform hull test - - when hulls collide, disable hull test - - if meshes overlap, reset countdown - - if countdown reaches 0, enable hull test - - */ - -#ifdef __MESHMERIZER_H__ - // Handle hulls - if(cache.HullTest) - { - if(cache.Model0->GetHull() && cache.Model1->GetHull()) - { - struct Local - { - static IcePoint* SVCallback(const IcePoint& sv, udword& previndex, udword user_data) - { - CollisionHull* Hull = (CollisionHull*)user_data; - previndex = Hull->ComputeSupportingVertex(sv, previndex); - return (IcePoint*)&Hull->GetVerts()[previndex]; - } - }; - - bool Collide; - - if(0) - { - static GJKEngine GJK; - static bool GJKInitDone=false; - if(!GJKInitDone) - { - GJK.Enable(GJK_BACKUP_PROCEDURE); - GJK.Enable(GJK_DEGENERATE); - GJK.Enable(GJK_HILLCLIMBING); - GJKInitDone = true; - } - GJK.SetCallbackObj0(Local::SVCallback); - GJK.SetCallbackObj1(Local::SVCallback); - GJK.SetUserData0(udword(cache.Model0->GetHull())); - GJK.SetUserData1(udword(cache.Model1->GetHull())); - Collide = GJK.Collide(*world0, *world1, &cache.SepVector); - } - else - { - static SVEngine SVE; - SVE.SetCallbackObj0(Local::SVCallback); - SVE.SetCallbackObj1(Local::SVCallback); - SVE.SetUserData0(udword(cache.Model0->GetHull())); - SVE.SetUserData1(udword(cache.Model1->GetHull())); - Collide = SVE.Collide(*world0, *world1, &cache.SepVector); - } - - if(!Collide) - { - // Reset stats & contact status - mFlags &= ~OPC_CONTACT; - mNbBVBVTests = 0; - mNbPrimPrimTests = 0; - mNbBVPrimTests = 0; - mPairs.Reset(); - return true; - } - } - } - - // Here, hulls collide - cache.HullTest = false; -#endif // __MESHMERIZER_H__ - - // Checkings - if(!Setup(cache.Model0->GetMeshInterface(), cache.Model1->GetMeshInterface())) return false; - - // Simple double-dispatch - bool Status; - if(!cache.Model0->HasLeafNodes()) - { - if(cache.Model0->IsQuantized()) - { - const AABBQuantizedNoLeafTree* T0 = (const AABBQuantizedNoLeafTree*)cache.Model0->GetTree(); - const AABBQuantizedNoLeafTree* T1 = (const AABBQuantizedNoLeafTree*)cache.Model1->GetTree(); - Status = Collide(T0, T1, world0, world1, &cache); - } - else - { - const AABBNoLeafTree* T0 = (const AABBNoLeafTree*)cache.Model0->GetTree(); - const AABBNoLeafTree* T1 = (const AABBNoLeafTree*)cache.Model1->GetTree(); - Status = Collide(T0, T1, world0, world1, &cache); - } - } - else - { - if(cache.Model0->IsQuantized()) - { - const AABBQuantizedTree* T0 = (const AABBQuantizedTree*)cache.Model0->GetTree(); - const AABBQuantizedTree* T1 = (const AABBQuantizedTree*)cache.Model1->GetTree(); - Status = Collide(T0, T1, world0, world1, &cache); - } - else - { - const AABBCollisionTree* T0 = (const AABBCollisionTree*)cache.Model0->GetTree(); - const AABBCollisionTree* T1 = (const AABBCollisionTree*)cache.Model1->GetTree(); - Status = Collide(T0, T1, world0, world1, &cache); - } - } - -#ifdef __MESHMERIZER_H__ - if(Status) - { - // Reset counter as long as overlap occurs - if(GetContactStatus()) cache.ResetCountDown(); - - // Enable hull test again when counter reaches zero - cache.CountDown--; - if(!cache.CountDown) - { - cache.ResetCountDown(); - cache.HullTest = true; - } - } -#endif - return Status; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Initializes a collision query : - * - reset stats & contact status - * - setup matrices - * - * \param world0 [in] world matrix for first object - * \param world1 [in] world matrix for second object - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::InitQuery(const Matrix4x4* world0, const Matrix4x4* world1) -{ - // Reset stats & contact status - Collider::InitQuery(); - mNbBVBVTests = 0; - mNbPrimPrimTests = 0; - mNbBVPrimTests = 0; - mPairs.Reset(); - - // Setup matrices - Matrix4x4 InvWorld0, InvWorld1; - if(world0) InvertPRMatrix(InvWorld0, *world0); - else InvWorld0.Identity(); - - if(world1) InvertPRMatrix(InvWorld1, *world1); - else InvWorld1.Identity(); - - Matrix4x4 World0to1 = world0 ? (*world0 * InvWorld1) : InvWorld1; - Matrix4x4 World1to0 = world1 ? (*world1 * InvWorld0) : InvWorld0; - - mR0to1 = World0to1; World0to1.GetTrans(mT0to1); - mR1to0 = World1to0; World1to0.GetTrans(mT1to0); - - // Precompute absolute 1-to-0 rotation matrix - for(udword i=0;i<3;i++) - { - for(udword j=0;j<3;j++) - { - // Epsilon value prevents floating-IcePoint inaccuracies (strategy borrowed from RAPID) - mAR.m[i][j] = 1e-6f + fabsf(mR1to0.m[i][j]); - } - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Takes advantage of temporal coherence. - * \param cache [in] cache for a pair of previously colliding primitives - * \return true if we can return immediately - * \warning only works for "First Contact" mode - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTreeCollider::CheckTemporalCoherence(Pair* cache) -{ - // Checkings - if(!cache) return false; - - // Test previously colliding primitives first - if(TemporalCoherenceEnabled() && FirstContactEnabled()) - { - PrimTest(cache->id0, cache->id1); - if(GetContactStatus()) return true; - } - return false; -} - -#define UPDATE_CACHE \ - if(cache && GetContactStatus()) \ - { \ - cache->id0 = mPairs.GetEntry(0); \ - cache->id1 = mPairs.GetEntry(1); \ - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Collision query for normal AABB trees. - * \param tree0 [in] AABB tree from first object - * \param tree1 [in] AABB tree from second object - * \param world0 [in] world matrix for first object - * \param world1 [in] world matrix for second object - * \param cache [in/out] cache for a pair of previously colliding primitives - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTreeCollider::Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) -{ - // Init collision query - InitQuery(world0, world1); - - // Check previous state - if(CheckTemporalCoherence(cache)) return true; - - // Perform collision query - _Collide(tree0->GetNodes(), tree1->GetNodes()); - - UPDATE_CACHE - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Collision query for no-leaf AABB trees. - * \param tree0 [in] AABB tree from first object - * \param tree1 [in] AABB tree from second object - * \param world0 [in] world matrix for first object - * \param world1 [in] world matrix for second object - * \param cache [in/out] cache for a pair of previously colliding primitives - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTreeCollider::Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) -{ - // Init collision query - InitQuery(world0, world1); - - // Check previous state - if(CheckTemporalCoherence(cache)) return true; - - // Perform collision query - _Collide(tree0->GetNodes(), tree1->GetNodes()); - - UPDATE_CACHE - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Collision query for quantized AABB trees. - * \param tree0 [in] AABB tree from first object - * \param tree1 [in] AABB tree from second object - * \param world0 [in] world matrix for first object - * \param world1 [in] world matrix for second object - * \param cache [in/out] cache for a pair of previously colliding primitives - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTreeCollider::Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) -{ - // Init collision query - InitQuery(world0, world1); - - // Check previous state - if(CheckTemporalCoherence(cache)) return true; - - // Setup dequantization coeffs - mCenterCoeff0 = tree0->mCenterCoeff; - mExtentsCoeff0 = tree0->mExtentsCoeff; - mCenterCoeff1 = tree1->mCenterCoeff; - mExtentsCoeff1 = tree1->mExtentsCoeff; - - // Dequantize box A - const AABBQuantizedNode* N0 = tree0->GetNodes(); - const IcePoint a(float(N0->mAABB.mExtents[0]) * mExtentsCoeff0.x, float(N0->mAABB.mExtents[1]) * mExtentsCoeff0.y, float(N0->mAABB.mExtents[2]) * mExtentsCoeff0.z); - const IcePoint Pa(float(N0->mAABB.mCenter[0]) * mCenterCoeff0.x, float(N0->mAABB.mCenter[1]) * mCenterCoeff0.y, float(N0->mAABB.mCenter[2]) * mCenterCoeff0.z); - // Dequantize box B - const AABBQuantizedNode* N1 = tree1->GetNodes(); - const IcePoint b(float(N1->mAABB.mExtents[0]) * mExtentsCoeff1.x, float(N1->mAABB.mExtents[1]) * mExtentsCoeff1.y, float(N1->mAABB.mExtents[2]) * mExtentsCoeff1.z); - const IcePoint Pb(float(N1->mAABB.mCenter[0]) * mCenterCoeff1.x, float(N1->mAABB.mCenter[1]) * mCenterCoeff1.y, float(N1->mAABB.mCenter[2]) * mCenterCoeff1.z); - - // Perform collision query - _Collide(N0, N1, a, Pa, b, Pb); - - UPDATE_CACHE - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Collision query for quantized no-leaf AABB trees. - * \param tree0 [in] AABB tree from first object - * \param tree1 [in] AABB tree from second object - * \param world0 [in] world matrix for first object - * \param world1 [in] world matrix for second object - * \param cache [in/out] cache for a pair of previously colliding primitives - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool AABBTreeCollider::Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) -{ - // Init collision query - InitQuery(world0, world1); - - // Check previous state - if(CheckTemporalCoherence(cache)) return true; - - // Setup dequantization coeffs - mCenterCoeff0 = tree0->mCenterCoeff; - mExtentsCoeff0 = tree0->mExtentsCoeff; - mCenterCoeff1 = tree1->mCenterCoeff; - mExtentsCoeff1 = tree1->mExtentsCoeff; - - // Perform collision query - _Collide(tree0->GetNodes(), tree1->GetNodes()); - - UPDATE_CACHE - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Standard trees -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// The normal AABB tree can use 2 different descent rules (with different performances) -//#define ORIGINAL_CODE //!< UNC-like descent rules -#define ALTERNATIVE_CODE //!< Alternative descent rules - -#ifdef ORIGINAL_CODE -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees. - * \param b0 [in] collision node from first tree - * \param b1 [in] collision node from second tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) -{ - // Perform BV-BV overlap test - if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) return; - - if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } - - if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) - { - _Collide(b0->GetNeg(), b1); - if(ContactFound()) return; - _Collide(b0->GetPos(), b1); - } - else - { - _Collide(b0, b1->GetNeg()); - if(ContactFound()) return; - _Collide(b0, b1->GetPos()); - } -} -#endif - -#ifdef ALTERNATIVE_CODE -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for normal AABB trees. - * \param b0 [in] collision node from first tree - * \param b1 [in] collision node from second tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) -{ - // Perform BV-BV overlap test - if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) - { - return; - } - - if(b0->IsLeaf()) - { - if(b1->IsLeaf()) - { - PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); - } - else - { - _Collide(b0, b1->GetNeg()); - if(ContactFound()) return; - _Collide(b0, b1->GetPos()); - } - } - else if(b1->IsLeaf()) - { - _Collide(b0->GetNeg(), b1); - if(ContactFound()) return; - _Collide(b0->GetPos(), b1); - } - else - { - _Collide(b0->GetNeg(), b1->GetNeg()); - if(ContactFound()) return; - _Collide(b0->GetNeg(), b1->GetPos()); - if(ContactFound()) return; - _Collide(b0->GetPos(), b1->GetNeg()); - if(ContactFound()) return; - _Collide(b0->GetPos(), b1->GetPos()); - } -} -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// No-leaf trees -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Leaf-leaf test for two primitive indices. - * \param id0 [in] index from first leaf-triangle - * \param id1 [in] index from second leaf-triangle - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::PrimTest(udword id0, udword id1) -{ - // Request vertices from the app - VertexPointers VP0; - VertexPointers VP1; - mIMesh0->GetTriangle(VP0, id0); - mIMesh1->GetTriangle(VP1, id1); - - // Transform from space 1 to space 0 - IcePoint u0,u1,u2; - TransformPoint(u0, *VP1.Vertex[0], mR1to0, mT1to0); - TransformPoint(u1, *VP1.Vertex[1], mR1to0, mT1to0); - TransformPoint(u2, *VP1.Vertex[2], mR1to0, mT1to0); - - // Perform triangle-triangle overlap test - if(TriTriOverlap(*VP0.Vertex[0], *VP0.Vertex[1], *VP0.Vertex[2], u0, u1, u2)) - { - // Keep track of colliding pairs - mPairs.Add(id0).Add(id1); - // Set contact status - mFlags |= OPC_CONTACT; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Leaf-leaf test for a previously fetched triangle from tree A (in B's space) and a new leaf from B. - * \param id1 [in] leaf-triangle index from tree B - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ void AABBTreeCollider::PrimTestTriIndex(udword id1) -{ - // Request vertices from the app - VertexPointers VP; - mIMesh1->GetTriangle(VP, id1); - - // Perform triangle-triangle overlap test - if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) - { - // Keep track of colliding pairs - mPairs.Add(mLeafIndex).Add(id1); - // Set contact status - mFlags |= OPC_CONTACT; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Leaf-leaf test for a previously fetched triangle from tree B (in A's space) and a new leaf from A. - * \param id0 [in] leaf-triangle index from tree A - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ void AABBTreeCollider::PrimTestIndexTri(udword id0) -{ - // Request vertices from the app - VertexPointers VP; - mIMesh0->GetTriangle(VP, id0); - - // Perform triangle-triangle overlap test - if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) - { - // Keep track of colliding pairs - mPairs.Add(id0).Add(mLeafIndex); - // Set contact status - mFlags |= OPC_CONTACT; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision of a leaf node from A and a branch from B. - * \param b [in] collision node from second tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_CollideTriBox(const AABBNoLeafNode* b) -{ - // Perform triangle-box overlap test - if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; - - // Keep same triangle, deal with first child - if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); - else _CollideTriBox(b->GetPos()); - - if(ContactFound()) return; - - // Keep same triangle, deal with second child - if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); - else _CollideTriBox(b->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision of a leaf node from B and a branch from A. - * \param b [in] collision node from first tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_CollideBoxTri(const AABBNoLeafNode* b) -{ - // Perform triangle-box overlap test - if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; - - // Keep same triangle, deal with first child - if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); - else _CollideBoxTri(b->GetPos()); - - if(ContactFound()) return; - - // Keep same triangle, deal with second child - if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); - else _CollideBoxTri(b->GetNeg()); -} - -//! Request triangle vertices from the app and transform them -#define FETCH_LEAF(prim_index, imesh, rot, trans) \ - mLeafIndex = prim_index; \ - /* Request vertices from the app */ \ - VertexPointers VP; imesh->GetTriangle(VP, prim_index); \ - /* Transform them in a common space */ \ - TransformPoint(mLeafVerts[0], *VP.Vertex[0], rot, trans); \ - TransformPoint(mLeafVerts[1], *VP.Vertex[1], rot, trans); \ - TransformPoint(mLeafVerts[2], *VP.Vertex[2], rot, trans); - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for no-leaf AABB trees. - * \param a [in] collision node from first tree - * \param b [in] collision node from second tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b) -{ - // Perform BV-BV overlap test - if(!BoxBoxOverlap(a->mAABB.mExtents, a->mAABB.mCenter, b->mAABB.mExtents, b->mAABB.mCenter)) return; - - // Catch leaf status - BOOL BHasPosLeaf = b->HasPosLeaf(); - BOOL BHasNegLeaf = b->HasNegLeaf(); - - if(a->HasPosLeaf()) - { - FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) - - if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); - else _CollideTriBox(b->GetPos()); - - if(ContactFound()) return; - - if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); - else _CollideTriBox(b->GetNeg()); - } - else - { - if(BHasPosLeaf) - { - FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) - - _CollideBoxTri(a->GetPos()); - } - else _Collide(a->GetPos(), b->GetPos()); - - if(ContactFound()) return; - - if(BHasNegLeaf) - { - FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) - - _CollideBoxTri(a->GetPos()); - } - else _Collide(a->GetPos(), b->GetNeg()); - } - - if(ContactFound()) return; - - if(a->HasNegLeaf()) - { - FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) - - if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); - else _CollideTriBox(b->GetPos()); - - if(ContactFound()) return; - - if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); - else _CollideTriBox(b->GetNeg()); - } - else - { - if(BHasPosLeaf) - { - // ### That leaf has possibly already been fetched - FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) - - _CollideBoxTri(a->GetNeg()); - } - else _Collide(a->GetNeg(), b->GetPos()); - - if(ContactFound()) return; - - if(BHasNegLeaf) - { - // ### That leaf has possibly already been fetched - FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) - - _CollideBoxTri(a->GetNeg()); - } - else _Collide(a->GetNeg(), b->GetNeg()); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantized trees -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized AABB trees. - * \param b0 [in] collision node from first tree - * \param b1 [in] collision node from second tree - * \param a [in] extent from box A - * \param Pa [in] center from box A - * \param b [in] extent from box B - * \param Pb [in] center from box B - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const IcePoint& a, const IcePoint& Pa, const IcePoint& b, const IcePoint& Pb) -{ - // Perform BV-BV overlap test - if(!BoxBoxOverlap(a, Pa, b, Pb)) return; - - if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } - - if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) - { - // Dequantize box - const QuantizedAABB* Box = &b0->GetNeg()->mAABB; - const IcePoint negPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); - const IcePoint nega(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); - _Collide(b0->GetNeg(), b1, nega, negPa, b, Pb); - - if(ContactFound()) return; - - // Dequantize box - Box = &b0->GetPos()->mAABB; - const IcePoint posPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); - const IcePoint posa(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); - _Collide(b0->GetPos(), b1, posa, posPa, b, Pb); - } - else - { - // Dequantize box - const QuantizedAABB* Box = &b1->GetNeg()->mAABB; - const IcePoint negPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); - const IcePoint negb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); - _Collide(b0, b1->GetNeg(), a, Pa, negb, negPb); - - if(ContactFound()) return; - - // Dequantize box - Box = &b1->GetPos()->mAABB; - const IcePoint posPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); - const IcePoint posb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); - _Collide(b0, b1->GetPos(), a, Pa, posb, posPb); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantized no-leaf trees -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision of a leaf node from A and a quantized branch from B. - * \param leaf [in] leaf triangle from first tree - * \param b [in] collision node from second tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_CollideTriBox(const AABBQuantizedNoLeafNode* b) -{ - // Dequantize box - const QuantizedAABB* bb = &b->mAABB; - const IcePoint Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); - const IcePoint eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); - - // Perform triangle-box overlap test - if(!TriBoxOverlap(Pb, eb)) return; - - if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); - else _CollideTriBox(b->GetPos()); - - if(ContactFound()) return; - - if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); - else _CollideTriBox(b->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision of a leaf node from B and a quantized branch from A. - * \param b [in] collision node from first tree - * \param leaf [in] leaf triangle from second tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_CollideBoxTri(const AABBQuantizedNoLeafNode* b) -{ - // Dequantize box - const QuantizedAABB* bb = &b->mAABB; - const IcePoint Pa(float(bb->mCenter[0]) * mCenterCoeff0.x, float(bb->mCenter[1]) * mCenterCoeff0.y, float(bb->mCenter[2]) * mCenterCoeff0.z); - const IcePoint ea(float(bb->mExtents[0]) * mExtentsCoeff0.x, float(bb->mExtents[1]) * mExtentsCoeff0.y, float(bb->mExtents[2]) * mExtentsCoeff0.z); - - // Perform triangle-box overlap test - if(!TriBoxOverlap(Pa, ea)) return; - - if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); - else _CollideBoxTri(b->GetPos()); - - if(ContactFound()) return; - - if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); - else _CollideBoxTri(b->GetNeg()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Recursive collision query for quantized no-leaf AABB trees. - * \param a [in] collision node from first tree - * \param b [in] collision node from second tree - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AABBTreeCollider::_Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b) -{ - // Dequantize box A - const QuantizedAABB* ab = &a->mAABB; - const IcePoint Pa(float(ab->mCenter[0]) * mCenterCoeff0.x, float(ab->mCenter[1]) * mCenterCoeff0.y, float(ab->mCenter[2]) * mCenterCoeff0.z); - const IcePoint ea(float(ab->mExtents[0]) * mExtentsCoeff0.x, float(ab->mExtents[1]) * mExtentsCoeff0.y, float(ab->mExtents[2]) * mExtentsCoeff0.z); - // Dequantize box B - const QuantizedAABB* bb = &b->mAABB; - const IcePoint Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); - const IcePoint eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); - - // Perform BV-BV overlap test - if(!BoxBoxOverlap(ea, Pa, eb, Pb)) return; - - // Catch leaf status - BOOL BHasPosLeaf = b->HasPosLeaf(); - BOOL BHasNegLeaf = b->HasNegLeaf(); - - if(a->HasPosLeaf()) - { - FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) - - if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); - else _CollideTriBox(b->GetPos()); - - if(ContactFound()) return; - - if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); - else _CollideTriBox(b->GetNeg()); - } - else - { - if(BHasPosLeaf) - { - FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) - - _CollideBoxTri(a->GetPos()); - } - else _Collide(a->GetPos(), b->GetPos()); - - if(ContactFound()) return; - - if(BHasNegLeaf) - { - FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) - - _CollideBoxTri(a->GetPos()); - } - else _Collide(a->GetPos(), b->GetNeg()); - } - - if(ContactFound()) return; - - if(a->HasNegLeaf()) - { - FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) - - if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); - else _CollideTriBox(b->GetPos()); - - if(ContactFound()) return; - - if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); - else _CollideTriBox(b->GetNeg()); - } - else - { - if(BHasPosLeaf) - { - // ### That leaf has possibly already been fetched - FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) - - _CollideBoxTri(a->GetNeg()); - } - else _Collide(a->GetNeg(), b->GetPos()); - - if(ContactFound()) return; - - if(BHasNegLeaf) - { - // ### That leaf has possibly already been fetched - FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) - - _CollideBoxTri(a->GetNeg()); - } - else _Collide(a->GetNeg(), b->GetNeg()); - } -} diff --git a/contrib/Opcode/OPC_TreeCollider.h b/contrib/Opcode/OPC_TreeCollider.h deleted file mode 100644 index ec0e517..0000000 --- a/contrib/Opcode/OPC_TreeCollider.h +++ /dev/null @@ -1,244 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains code for a tree collider. - * \file OPC_TreeCollider.h - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_TREECOLLIDER_H__ -#define __OPC_TREECOLLIDER_H__ - - //! This structure holds cached information used by the algorithm. - //! Two model pointers and two colliding primitives are cached. Model pointers are assigned - //! to their respective meshes, and the pair of colliding primitives is used for temporal - //! coherence. That is, in case temporal coherence is enabled, those two primitives are - //! tested for overlap before everything else. If they still collide, we're done before - //! even entering the recursive collision code. - struct OPCODE_API BVTCache : Pair - { - //! Constructor - inline_ BVTCache() - { - ResetCache(); - ResetCountDown(); - } - - void ResetCache() - { - Model0 = null; - Model1 = null; - id0 = 0; - id1 = 1; -#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! - HullTest = true; - SepVector.pid = 0; - SepVector.qid = 0; - SepVector.SV = IcePoint(1.0f, 0.0f, 0.0f); -#endif // __MESHMERIZER_H__ - } - - inline_ void ResetCountDown() - { -#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! - CountDown = 50; -#endif // __MESHMERIZER_H__ - } - - const Model* Model0; //!< Model for first object - const Model* Model1; //!< Model for second object - -#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! - SVCache SepVector; - udword CountDown; - bool HullTest; -#endif // __MESHMERIZER_H__ - }; - - class OPCODE_API AABBTreeCollider : public Collider - { - public: - // Constructor / Destructor - AABBTreeCollider(); - virtual ~AABBTreeCollider(); - // Generic collision query - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Generic collision query for generic OPCODE models. After the call, access the results with: - * - GetContactStatus() - * - GetNbPairs() - * - GetPairs() - * - * \param cache [in] collision cache for model pointers and a colliding pair of primitives - * \param world0 [in] world matrix for first object, or null - * \param world1 [in] world matrix for second object, or null - * \return true if success - * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Collide(BVTCache& cache, const Matrix4x4* world0=null, const Matrix4x4* world1=null); - - // Collision queries - bool Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); - bool Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); - bool Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); - bool Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); - // Settings - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Settings: selects between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) - * \param flag [in] true for full tests, false for coarse tests - * \see SetFullPrimBoxTest(bool flag) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Settings: selects between full triangle-box tests or "SAT-lite" tests (where Class III axes are discarded) - * \param flag [in] true for full tests, false for coarse tests - * \see SetFullBoxBoxTest(bool flag) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ void SetFullPrimBoxTest(bool flag) { mFullPrimBoxTest = flag; } - - // Stats - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Stats: gets the number of BV-BV overlap tests after a collision query. - * \see GetNbPrimPrimTests() - * \see GetNbBVPrimTests() - * \return the number of BV-BV tests performed during last query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbBVBVTests() const { return mNbBVBVTests; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Stats: gets the number of Triangle-Triangle overlap tests after a collision query. - * \see GetNbBVBVTests() - * \see GetNbBVPrimTests() - * \return the number of Triangle-Triangle tests performed during last query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbPrimPrimTests() const { return mNbPrimPrimTests; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Stats: gets the number of BV-Triangle overlap tests after a collision query. - * \see GetNbBVBVTests() - * \see GetNbPrimPrimTests() - * \return the number of BV-Triangle tests performed during last query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbBVPrimTests() const { return mNbBVPrimTests; } - - // Data access - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the number of contacts after a collision query. - * \see GetContactStatus() - * \see GetPairs() - * \return the number of contacts / colliding pairs. - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbPairs() const { return mPairs.GetNbEntries()>>1; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the pairs of colliding triangles after a collision query. - * \see GetContactStatus() - * \see GetNbPairs() - * \return the list of colliding pairs (triangle indices) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ const Pair* GetPairs() const { return (const Pair*)mPairs.GetEntries(); } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. - * \return null if everything is ok, else a string describing the problem - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(Collider) const char* ValidateSettings(); - - protected: - // Colliding pairs - Container mPairs; //!< Pairs of colliding primitives - // User mesh interfaces - const MeshInterface* mIMesh0; //!< User-defined mesh interface for object0 - const MeshInterface* mIMesh1; //!< User-defined mesh interface for object1 - // Stats - udword mNbBVBVTests; //!< Number of BV-BV tests - udword mNbPrimPrimTests; //!< Number of Primitive-Primitive tests - udword mNbBVPrimTests; //!< Number of BV-Primitive tests - // Precomputed data - Matrix3x3 mAR; //!< Absolute rotation matrix - Matrix3x3 mR0to1; //!< Rotation from object0 to object1 - Matrix3x3 mR1to0; //!< Rotation from object1 to object0 - IcePoint mT0to1; //!< Translation from object0 to object1 - IcePoint mT1to0; //!< Translation from object1 to object0 - // Dequantization coeffs - IcePoint mCenterCoeff0; - IcePoint mExtentsCoeff0; - IcePoint mCenterCoeff1; - IcePoint mExtentsCoeff1; - // Leaf description - IcePoint mLeafVerts[3]; //!< Triangle vertices - udword mLeafIndex; //!< Triangle index - // Settings - bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) - bool mFullPrimBoxTest; //!< Perform full Primitive-BV tests (true) or SAT-lite tests (false) - // Internal methods - - // Standard AABB trees - void _Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1); - // Quantized AABB trees - void _Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const IcePoint& a, const IcePoint& Pa, const IcePoint& b, const IcePoint& Pb); - // No-leaf AABB trees - void _CollideTriBox(const AABBNoLeafNode* b); - void _CollideBoxTri(const AABBNoLeafNode* b); - void _Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b); - // Quantized no-leaf AABB trees - void _CollideTriBox(const AABBQuantizedNoLeafNode* b); - void _CollideBoxTri(const AABBQuantizedNoLeafNode* b); - void _Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b); - // Overlap tests - void PrimTest(udword id0, udword id1); - inline_ void PrimTestTriIndex(udword id1); - inline_ void PrimTestIndexTri(udword id0); - - inline_ BOOL BoxBoxOverlap(const IcePoint& ea, const IcePoint& ca, const IcePoint& eb, const IcePoint& cb); - inline_ BOOL TriBoxOverlap(const IcePoint& center, const IcePoint& extents); - inline_ BOOL TriTriOverlap(const IcePoint& V0, const IcePoint& V1, const IcePoint& V2, const IcePoint& U0, const IcePoint& U1, const IcePoint& U2); - // Init methods - void InitQuery(const Matrix4x4* world0=null, const Matrix4x4* world1=null); - bool CheckTemporalCoherence(Pair* cache); - - inline_ BOOL Setup(const MeshInterface* mi0, const MeshInterface* mi1) - { - mIMesh0 = mi0; - mIMesh1 = mi1; - - if(!mIMesh0 || !mIMesh1) return FALSE; - - return TRUE; - } - }; - -#endif // __OPC_TREECOLLIDER_H__ diff --git a/contrib/Opcode/OPC_TriBoxOverlap.h b/contrib/Opcode/OPC_TriBoxOverlap.h deleted file mode 100644 index e32673b..0000000 --- a/contrib/Opcode/OPC_TriBoxOverlap.h +++ /dev/null @@ -1,339 +0,0 @@ - -//! This macro quickly finds the min & max values among 3 variables -#define FINDMINMAX(x0, x1, x2, min, max) \ - min = max = x0; \ - if(x1max) max=x1; \ - if(x2max) max=x2; - -//! TO BE DOCUMENTED -inline_ BOOL planeBoxOverlap(const IcePoint& normal, const float d, const IcePoint& maxbox) -{ - IcePoint vmin, vmax; - for(udword q=0;q<=2;q++) - { - if(normal[q]>0.0f) { vmin[q]=-maxbox[q]; vmax[q]=maxbox[q]; } - else { vmin[q]=maxbox[q]; vmax[q]=-maxbox[q]; } - } - if((normal|vmin)+d>0.0f) return FALSE; - if((normal|vmax)+d>=0.0f) return TRUE; - - return FALSE; -} - -//! TO BE DOCUMENTED -#define AXISTEST_X01(a, b, fa, fb) \ - min = a*v0.y - b*v0.z; \ - max = a*v2.y - b*v2.z; \ - if(min>max) {const float tmp=max; max=min; min=tmp; } \ - rad = fa * extents.y + fb * extents.z; \ - if(min>rad || max<-rad) return FALSE; - -//! TO BE DOCUMENTED -#define AXISTEST_X2(a, b, fa, fb) \ - min = a*v0.y - b*v0.z; \ - max = a*v1.y - b*v1.z; \ - if(min>max) {const float tmp=max; max=min; min=tmp; } \ - rad = fa * extents.y + fb * extents.z; \ - if(min>rad || max<-rad) return FALSE; - -//! TO BE DOCUMENTED -#define AXISTEST_Y02(a, b, fa, fb) \ - min = b*v0.z - a*v0.x; \ - max = b*v2.z - a*v2.x; \ - if(min>max) {const float tmp=max; max=min; min=tmp; } \ - rad = fa * extents.x + fb * extents.z; \ - if(min>rad || max<-rad) return FALSE; - -//! TO BE DOCUMENTED -#define AXISTEST_Y1(a, b, fa, fb) \ - min = b*v0.z - a*v0.x; \ - max = b*v1.z - a*v1.x; \ - if(min>max) {const float tmp=max; max=min; min=tmp; } \ - rad = fa * extents.x + fb * extents.z; \ - if(min>rad || max<-rad) return FALSE; - -//! TO BE DOCUMENTED -#define AXISTEST_Z12(a, b, fa, fb) \ - min = a*v1.x - b*v1.y; \ - max = a*v2.x - b*v2.y; \ - if(min>max) {const float tmp=max; max=min; min=tmp; } \ - rad = fa * extents.x + fb * extents.y; \ - if(min>rad || max<-rad) return FALSE; - -//! TO BE DOCUMENTED -#define AXISTEST_Z0(a, b, fa, fb) \ - min = a*v0.x - b*v0.y; \ - max = a*v1.x - b*v1.y; \ - if(min>max) {const float tmp=max; max=min; min=tmp; } \ - rad = fa * extents.x + fb * extents.y; \ - if(min>rad || max<-rad) return FALSE; - -// compute triangle edges -// - edges lazy evaluated to take advantage of early exits -// - fabs precomputed (half less work, possible since extents are always >0) -// - customized macros to take advantage of the null component -// - axis vector discarded, possibly saves useless movs -#define IMPLEMENT_CLASS3_TESTS \ - float rad; \ - float min, max; \ - \ - const float fey0 = fabsf(e0.y); \ - const float fez0 = fabsf(e0.z); \ - AXISTEST_X01(e0.z, e0.y, fez0, fey0); \ - const float fex0 = fabsf(e0.x); \ - AXISTEST_Y02(e0.z, e0.x, fez0, fex0); \ - AXISTEST_Z12(e0.y, e0.x, fey0, fex0); \ - \ - const float fey1 = fabsf(e1.y); \ - const float fez1 = fabsf(e1.z); \ - AXISTEST_X01(e1.z, e1.y, fez1, fey1); \ - const float fex1 = fabsf(e1.x); \ - AXISTEST_Y02(e1.z, e1.x, fez1, fex1); \ - AXISTEST_Z0(e1.y, e1.x, fey1, fex1); \ - \ - const IcePoint e2 = mLeafVerts[0] - mLeafVerts[2]; \ - const float fey2 = fabsf(e2.y); \ - const float fez2 = fabsf(e2.z); \ - AXISTEST_X2(e2.z, e2.y, fez2, fey2); \ - const float fex2 = fabsf(e2.x); \ - AXISTEST_Y1(e2.z, e2.x, fez2, fex2); \ - AXISTEST_Z12(e2.y, e2.x, fey2, fex2); - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Triangle-Box overlap test using the separating axis theorem. - * This is the code from Tomas Möller, a bit optimized: - * - with some more lazy evaluation (faster path on PC) - * - with a tiny bit of assembly - * - with "SAT-lite" applied if needed - * - and perhaps with some more minor modifs... - * - * \param center [in] box center - * \param extents [in] box extents - * \return true if triangle & box overlap - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL AABBTreeCollider::TriBoxOverlap(const IcePoint& center, const IcePoint& extents) -{ - // Stats - mNbBVPrimTests++; - - // use separating axis theorem to test overlap between triangle and box - // need to test for overlap in these directions: - // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle - // we do not even need to test these) - // 2) normal of the triangle - // 3) crossproduct(edge from tri, {x,y,z}-directin) - // this gives 3x3=9 more tests - - // move everything so that the boxcenter is in (0,0,0) - IcePoint v0, v1, v2; - v0.x = mLeafVerts[0].x - center.x; - v1.x = mLeafVerts[1].x - center.x; - v2.x = mLeafVerts[2].x - center.x; - - // First, test overlap in the {x,y,z}-directions -#ifdef OPC_USE_FCOMI - // find min, max of the triangle in x-direction, and test for overlap in X - if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; - if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; - - // same for Y - v0.y = mLeafVerts[0].y - center.y; - v1.y = mLeafVerts[1].y - center.y; - v2.y = mLeafVerts[2].y - center.y; - - if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; - if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; - - // same for Z - v0.z = mLeafVerts[0].z - center.z; - v1.z = mLeafVerts[1].z - center.z; - v2.z = mLeafVerts[2].z - center.z; - - if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; - if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; -#else - float min,max; - // Find min, max of the triangle in x-direction, and test for overlap in X - FINDMINMAX(v0.x, v1.x, v2.x, min, max); - if(min>extents.x || max<-extents.x) return FALSE; - - // Same for Y - v0.y = mLeafVerts[0].y - center.y; - v1.y = mLeafVerts[1].y - center.y; - v2.y = mLeafVerts[2].y - center.y; - - FINDMINMAX(v0.y, v1.y, v2.y, min, max); - if(min>extents.y || max<-extents.y) return FALSE; - - // Same for Z - v0.z = mLeafVerts[0].z - center.z; - v1.z = mLeafVerts[1].z - center.z; - v2.z = mLeafVerts[2].z - center.z; - - FINDMINMAX(v0.z, v1.z, v2.z, min, max); - if(min>extents.z || max<-extents.z) return FALSE; -#endif - // 2) Test if the box intersects the plane of the triangle - // compute plane equation of triangle: normal*x+d=0 - // ### could be precomputed since we use the same leaf triangle several times - const IcePoint e0 = v1 - v0; - const IcePoint e1 = v2 - v1; - const IcePoint normal = e0 ^ e1; - const float d = -normal|v0; - if(!planeBoxOverlap(normal, d, extents)) return FALSE; - - // 3) "Class III" tests - if(mFullPrimBoxTest) - { - IMPLEMENT_CLASS3_TESTS - } - return TRUE; -} - -//! A dedicated version where the box is constant -inline_ BOOL OBBCollider::TriBoxOverlap() -{ - // Stats - mNbVolumePrimTests++; - - // Hook - const IcePoint& extents = mBoxExtents; - const IcePoint& v0 = mLeafVerts[0]; - const IcePoint& v1 = mLeafVerts[1]; - const IcePoint& v2 = mLeafVerts[2]; - - // use separating axis theorem to test overlap between triangle and box - // need to test for overlap in these directions: - // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle - // we do not even need to test these) - // 2) normal of the triangle - // 3) crossproduct(edge from tri, {x,y,z}-directin) - // this gives 3x3=9 more tests - - // Box center is already in (0,0,0) - - // First, test overlap in the {x,y,z}-directions -#ifdef OPC_USE_FCOMI - // find min, max of the triangle in x-direction, and test for overlap in X - if(FCMin3(v0.x, v1.x, v2.x)>mBoxExtents.x) return FALSE; - if(FCMax3(v0.x, v1.x, v2.x)<-mBoxExtents.x) return FALSE; - - if(FCMin3(v0.y, v1.y, v2.y)>mBoxExtents.y) return FALSE; - if(FCMax3(v0.y, v1.y, v2.y)<-mBoxExtents.y) return FALSE; - - if(FCMin3(v0.z, v1.z, v2.z)>mBoxExtents.z) return FALSE; - if(FCMax3(v0.z, v1.z, v2.z)<-mBoxExtents.z) return FALSE; -#else - float min,max; - // Find min, max of the triangle in x-direction, and test for overlap in X - FINDMINMAX(v0.x, v1.x, v2.x, min, max); - if(min>mBoxExtents.x || max<-mBoxExtents.x) return FALSE; - - FINDMINMAX(v0.y, v1.y, v2.y, min, max); - if(min>mBoxExtents.y || max<-mBoxExtents.y) return FALSE; - - FINDMINMAX(v0.z, v1.z, v2.z, min, max); - if(min>mBoxExtents.z || max<-mBoxExtents.z) return FALSE; -#endif - // 2) Test if the box intersects the plane of the triangle - // compute plane equation of triangle: normal*x+d=0 - // ### could be precomputed since we use the same leaf triangle several times - const IcePoint e0 = v1 - v0; - const IcePoint e1 = v2 - v1; - const IcePoint normal = e0 ^ e1; - const float d = -normal|v0; - if(!planeBoxOverlap(normal, d, mBoxExtents)) return FALSE; - - // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) - { - IMPLEMENT_CLASS3_TESTS - } - return TRUE; -} - -//! ...and another one, jeez -inline_ BOOL AABBCollider::TriBoxOverlap() -{ - // Stats - mNbVolumePrimTests++; - - // Hook - const IcePoint& center = mBox.mCenter; - const IcePoint& extents = mBox.mExtents; - - // use separating axis theorem to test overlap between triangle and box - // need to test for overlap in these directions: - // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle - // we do not even need to test these) - // 2) normal of the triangle - // 3) crossproduct(edge from tri, {x,y,z}-directin) - // this gives 3x3=9 more tests - - // move everything so that the boxcenter is in (0,0,0) - IcePoint v0, v1, v2; - v0.x = mLeafVerts[0].x - center.x; - v1.x = mLeafVerts[1].x - center.x; - v2.x = mLeafVerts[2].x - center.x; - - // First, test overlap in the {x,y,z}-directions -#ifdef OPC_USE_FCOMI - // find min, max of the triangle in x-direction, and test for overlap in X - if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; - if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; - - // same for Y - v0.y = mLeafVerts[0].y - center.y; - v1.y = mLeafVerts[1].y - center.y; - v2.y = mLeafVerts[2].y - center.y; - - if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; - if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; - - // same for Z - v0.z = mLeafVerts[0].z - center.z; - v1.z = mLeafVerts[1].z - center.z; - v2.z = mLeafVerts[2].z - center.z; - - if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; - if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; -#else - float min,max; - // Find min, max of the triangle in x-direction, and test for overlap in X - FINDMINMAX(v0.x, v1.x, v2.x, min, max); - if(min>extents.x || max<-extents.x) return FALSE; - - // Same for Y - v0.y = mLeafVerts[0].y - center.y; - v1.y = mLeafVerts[1].y - center.y; - v2.y = mLeafVerts[2].y - center.y; - - FINDMINMAX(v0.y, v1.y, v2.y, min, max); - if(min>extents.y || max<-extents.y) return FALSE; - - // Same for Z - v0.z = mLeafVerts[0].z - center.z; - v1.z = mLeafVerts[1].z - center.z; - v2.z = mLeafVerts[2].z - center.z; - - FINDMINMAX(v0.z, v1.z, v2.z, min, max); - if(min>extents.z || max<-extents.z) return FALSE; -#endif - // 2) Test if the box intersects the plane of the triangle - // compute plane equation of triangle: normal*x+d=0 - // ### could be precomputed since we use the same leaf triangle several times - const IcePoint e0 = v1 - v0; - const IcePoint e1 = v2 - v1; - const IcePoint normal = e0 ^ e1; - const float d = -normal|v0; - if(!planeBoxOverlap(normal, d, extents)) return FALSE; - - // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) - { - IMPLEMENT_CLASS3_TESTS - } - return TRUE; -} diff --git a/contrib/Opcode/OPC_TriTriOverlap.h b/contrib/Opcode/OPC_TriTriOverlap.h deleted file mode 100644 index a9ee9c5..0000000 --- a/contrib/Opcode/OPC_TriTriOverlap.h +++ /dev/null @@ -1,279 +0,0 @@ - -//! if OPC_TRITRI_EPSILON_TEST is true then we do a check (if |dv|b) \ - { \ - const float c=a; \ - a=b; \ - b=c; \ - } - -//! Edge to edge test based on Franlin Antonio's gem: "Faster Line IceSegment Intersection", in Graphics Gems III, pp. 199-202 -#define EDGE_EDGE_TEST(V0, U0, U1) \ - Bx = U0[i0] - U1[i0]; \ - By = U0[i1] - U1[i1]; \ - Cx = V0[i0] - U0[i0]; \ - Cy = V0[i1] - U0[i1]; \ - f = Ay*Bx - Ax*By; \ - d = By*Cx - Bx*Cy; \ - if((f>0.0f && d>=0.0f && d<=f) || (f<0.0f && d<=0.0f && d>=f)) \ - { \ - const float e=Ax*Cy - Ay*Cx; \ - if(f>0.0f) \ - { \ - if(e>=0.0f && e<=f) return TRUE; \ - } \ - else \ - { \ - if(e<=0.0f && e>=f) return TRUE; \ - } \ - } - -//! TO BE DOCUMENTED -#define EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2) \ -{ \ - float Bx,By,Cx,Cy,d,f; \ - const float Ax = V1[i0] - V0[i0]; \ - const float Ay = V1[i1] - V0[i1]; \ - /* test edge U0,U1 against V0,V1 */ \ - EDGE_EDGE_TEST(V0, U0, U1); \ - /* test edge U1,U2 against V0,V1 */ \ - EDGE_EDGE_TEST(V0, U1, U2); \ - /* test edge U2,U1 against V0,V1 */ \ - EDGE_EDGE_TEST(V0, U2, U0); \ -} - -//! TO BE DOCUMENTED -#define POINT_IN_TRI(V0, U0, U1, U2) \ -{ \ - /* is T1 completly inside T2? */ \ - /* check if V0 is inside tri(U0,U1,U2) */ \ - float a = U1[i1] - U0[i1]; \ - float b = -(U1[i0] - U0[i0]); \ - float c = -a*U0[i0] - b*U0[i1]; \ - float d0 = a*V0[i0] + b*V0[i1] + c; \ - \ - a = U2[i1] - U1[i1]; \ - b = -(U2[i0] - U1[i0]); \ - c = -a*U1[i0] - b*U1[i1]; \ - const float d1 = a*V0[i0] + b*V0[i1] + c; \ - \ - a = U0[i1] - U2[i1]; \ - b = -(U0[i0] - U2[i0]); \ - c = -a*U2[i0] - b*U2[i1]; \ - const float d2 = a*V0[i0] + b*V0[i1] + c; \ - if(d0*d1>0.0f) \ - { \ - if(d0*d2>0.0f) return TRUE; \ - } \ -} - -//! TO BE DOCUMENTED -BOOL CoplanarTriTri(const IcePoint& n, const IcePoint& v0, const IcePoint& v1, const IcePoint& v2, const IcePoint& u0, const IcePoint& u1, const IcePoint& u2) -{ - float A[3]; - short i0,i1; - /* first project onto an axis-aligned plane, that maximizes the area */ - /* of the triangles, compute indices: i0,i1. */ - A[0] = fabsf(n[0]); - A[1] = fabsf(n[1]); - A[2] = fabsf(n[2]); - if(A[0]>A[1]) - { - if(A[0]>A[2]) - { - i0=1; /* A[0] is greatest */ - i1=2; - } - else - { - i0=0; /* A[2] is greatest */ - i1=1; - } - } - else /* A[0]<=A[1] */ - { - if(A[2]>A[1]) - { - i0=0; /* A[2] is greatest */ - i1=1; - } - else - { - i0=0; /* A[1] is greatest */ - i1=2; - } - } - - /* test all edges of triangle 1 against the edges of triangle 2 */ - EDGE_AGAINST_TRI_EDGES(v0, v1, u0, u1, u2); - EDGE_AGAINST_TRI_EDGES(v1, v2, u0, u1, u2); - EDGE_AGAINST_TRI_EDGES(v2, v0, u0, u1, u2); - - /* finally, test if tri1 is totally contained in tri2 or vice versa */ - POINT_IN_TRI(v0, u0, u1, u2); - POINT_IN_TRI(u0, v0, v1, v2); - - return FALSE; -} - -//! TO BE DOCUMENTED -#define NEWCOMPUTE_INTERVALS(VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, A, B, C, X0, X1) \ -{ \ - if(D0D1>0.0f) \ - { \ - /* here we know that D0D2<=0.0 */ \ - /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ - A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ - } \ - else if(D0D2>0.0f) \ - { \ - /* here we know that d0d1<=0.0 */ \ - A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ - } \ - else if(D1*D2>0.0f || D0!=0.0f) \ - { \ - /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ - A=VV0; B=(VV1 - VV0)*D0; C=(VV2 - VV0)*D0; X0=D0 - D1; X1=D0 - D2; \ - } \ - else if(D1!=0.0f) \ - { \ - A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ - } \ - else if(D2!=0.0f) \ - { \ - A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ - } \ - else \ - { \ - /* triangles are coplanar */ \ - return CoplanarTriTri(N1, V0, V1, V2, U0, U1, U2); \ - } \ -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Triangle/triangle intersection test routine, - * by Tomas Moller, 1997. - * See article "A Fast Triangle-Triangle Intersection Test", - * Journal of Graphics Tools, 2(2), 1997 - * - * Updated June 1999: removed the divisions -- a little faster now! - * Updated October 1999: added {} to CROSS and SUB macros - * - * int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3], - * float U0[3],float U1[3],float U2[3]) - * - * \param V0 [in] triangle 0, vertex 0 - * \param V1 [in] triangle 0, vertex 1 - * \param V2 [in] triangle 0, vertex 2 - * \param U0 [in] triangle 1, vertex 0 - * \param U1 [in] triangle 1, vertex 1 - * \param U2 [in] triangle 1, vertex 2 - * \return true if triangles overlap - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline_ BOOL AABBTreeCollider::TriTriOverlap(const IcePoint& V0, const IcePoint& V1, const IcePoint& V2, const IcePoint& U0, const IcePoint& U1, const IcePoint& U2) -{ - // Stats - mNbPrimPrimTests++; - - // Compute plane equation of triangle(V0,V1,V2) - IcePoint E1 = V1 - V0; - IcePoint E2 = V2 - V0; - const IcePoint N1 = E1 ^ E2; - const float d1 =-N1 | V0; - // IcePlane equation 1: N1.X+d1=0 - - // Put U0,U1,U2 into plane equation 1 to compute signed distances to the plane - float du0 = (N1|U0) + d1; - float du1 = (N1|U1) + d1; - float du2 = (N1|U2) + d1; - - // Coplanarity robustness check -#ifdef OPC_TRITRI_EPSILON_TEST - if(fabsf(du0)0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ? - return FALSE; // no intersection occurs - - // Compute plane of triangle (U0,U1,U2) - E1 = U1 - U0; - E2 = U2 - U0; - const IcePoint N2 = E1 ^ E2; - const float d2=-N2 | U0; - // plane equation 2: N2.X+d2=0 - - // put V0,V1,V2 into plane equation 2 - float dv0 = (N2|V0) + d2; - float dv1 = (N2|V1) + d2; - float dv2 = (N2|V2) + d2; - -#ifdef OPC_TRITRI_EPSILON_TEST - if(fabsf(dv0)0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ? - return FALSE; // no intersection occurs - - // Compute direction of intersection line - const IcePoint D = N1^N2; - - // Compute and index to the largest component of D - float max=fabsf(D[0]); - short index=0; - float bb=fabsf(D[1]); - float cc=fabsf(D[2]); - if(bb>max) max=bb,index=1; - if(cc>max) max=cc,index=2; - - // This is the simplified projection onto L - const float vp0 = V0[index]; - const float vp1 = V1[index]; - const float vp2 = V2[index]; - - const float up0 = U0[index]; - const float up1 = U1[index]; - const float up2 = U2[index]; - - // Compute interval for triangle 1 - float a,b,c,x0,x1; - NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1); - - // Compute interval for triangle 2 - float d,e,f,y0,y1; - NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1); - - const float xx=x0*x1; - const float yy=y0*y1; - const float xxyy=xx*yy; - - float isect1[2], isect2[2]; - - float tmp=a*xxyy; - isect1[0]=tmp+b*x1*yy; - isect1[1]=tmp+c*x0*yy; - - tmp=d*xxyy; - isect2[0]=tmp+e*xx*y1; - isect2[1]=tmp+f*xx*y0; - - SORT(isect1[0],isect1[1]); - SORT(isect2[0],isect2[1]); - - if(isect1[1]HasPosLeaf()) mTouchedPrimitives->Add(node->GetPosPrimitive()); \ - else _Dump(node->GetPos()); \ - \ - if(ContactFound()) return; \ - \ - if(node->HasNegLeaf()) mTouchedPrimitives->Add(node->GetNegPrimitive()); \ - else _Dump(node->GetNeg()); \ -} - -#define IMPLEMENT_LEAFDUMP(type) \ -void VolumeCollider::_Dump(const type* node) \ -{ \ - if(node->IsLeaf()) \ - { \ - mTouchedPrimitives->Add(node->GetPrimitive()); \ - } \ - else \ - { \ - _Dump(node->GetPos()); \ - \ - if(ContactFound()) return; \ - \ - _Dump(node->GetNeg()); \ - } \ -} - -IMPLEMENT_NOLEAFDUMP(AABBNoLeafNode) -IMPLEMENT_NOLEAFDUMP(AABBQuantizedNoLeafNode) - -IMPLEMENT_LEAFDUMP(AABBCollisionNode) -IMPLEMENT_LEAFDUMP(AABBQuantizedNode) diff --git a/contrib/Opcode/OPC_VolumeCollider.h b/contrib/Opcode/OPC_VolumeCollider.h deleted file mode 100644 index 330f6a6..0000000 --- a/contrib/Opcode/OPC_VolumeCollider.h +++ /dev/null @@ -1,138 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Contains base volume collider class. - * \file OPC_VolumeCollider.h - * \author Pierre Terdiman - * \date June, 2, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPC_VOLUMECOLLIDER_H__ -#define __OPC_VOLUMECOLLIDER_H__ - - struct OPCODE_API VolumeCache - { - VolumeCache() : Model(null) {} - ~VolumeCache() {} - - Container TouchedPrimitives; //!< Indices of touched primitives - const BaseModel* Model; //!< Owner - }; - - class OPCODE_API VolumeCollider : public Collider - { - public: - // Constructor / Destructor - VolumeCollider(); - virtual ~VolumeCollider() = 0; - - // Collision report - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the number of touched primitives after a collision query. - * \see GetContactStatus() - * \see GetTouchedPrimitives() - * \return the number of touched primitives - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetNbEntries() : 0; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Gets the list of touched primitives after a collision query. - * \see GetContactStatus() - * \see GetNbTouchedPrimitives() - * \return the list of touched primitives (primitive indices) - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ const udword* GetTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetEntries() : null; } - - // Stats - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Stats: gets the number of Volume-BV overlap tests after a collision query. - * \see GetNbVolumePrimTests() - * \return the number of Volume-BV tests performed during last query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbVolumeBVTests() const { return mNbVolumeBVTests; } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Stats: gets the number of Volume-Triangle overlap tests after a collision query. - * \see GetNbVolumeBVTests() - * \return the number of Volume-Triangle tests performed during last query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline_ udword GetNbVolumePrimTests() const { return mNbVolumePrimTests; } - - // Settings - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. - * \return null if everything is ok, else a string describing the problem - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(Collider) const char* ValidateSettings(); - - protected: - // Touched primitives - Container* mTouchedPrimitives; //!< List of touched primitives - - // Dequantization coeffs - IcePoint mCenterCoeff; - IcePoint mExtentsCoeff; - // Stats - udword mNbVolumeBVTests; //!< Number of Volume-BV tests - udword mNbVolumePrimTests; //!< Number of Volume-Primitive tests - // Internal methods - void _Dump(const AABBCollisionNode* node); - void _Dump(const AABBNoLeafNode* node); - void _Dump(const AABBQuantizedNode* node); - void _Dump(const AABBQuantizedNoLeafNode* node); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** - * Initializes a query - */ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - override(Collider) inline_ void InitQuery() - { - // Reset stats & contact status - mNbVolumeBVTests = 0; - mNbVolumePrimTests = 0; - Collider::InitQuery(); - } - - inline_ BOOL IsCacheValid(VolumeCache& cache) - { - // We're going to do a volume-vs-model query. - if(cache.Model!=mCurrentModel) - { - // Cached list was for another model so we can't keep it - // Keep track of new owner and reset cache - cache.Model = mCurrentModel; - return FALSE; - } - else - { - // Same models, no problem - return TRUE; - } - } - }; - -#endif // __OPC_VOLUMECOLLIDER_H__ diff --git a/contrib/Opcode/Opcode.cpp b/contrib/Opcode/Opcode.cpp deleted file mode 100644 index 7a90153..0000000 --- a/contrib/Opcode/Opcode.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Main file for Opcode.dll. - * \file Opcode.cpp - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/* - Finding a good name is difficult! - Here's the draft for this lib.... Spooky, uh? - - VOID? Very Optimized Interference Detection - ZOID? Zappy's Optimized Interference Detection - CID? Custom/Clever Interference Detection - AID / ACID! Accurate Interference Detection - QUID? Quick Interference Detection - RIDE? Realtime Interference DEtection - WIDE? Wicked Interference DEtection (....) - GUID! - KID ! k-dop interference detection :) - OPCODE! OPtimized COllision DEtection -*/ - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Precompiled Header -#include "StdAfx.h" - -bool Opcode::InitOpcode() -{ - Log("// Initializing OPCODE\n\n"); -// LogAPIInfo(); - return true; -} - -void ReleasePruningSorters(); -bool Opcode::CloseOpcode() -{ - Log("// Closing OPCODE\n\n"); - - ReleasePruningSorters(); - - return true; -} - -#ifdef ICE_MAIN - -void ModuleAttach(HINSTANCE hinstance) -{ -} - -void ModuleDetach() -{ -} - -#endif \ No newline at end of file diff --git a/contrib/Opcode/Opcode.h b/contrib/Opcode/Opcode.h deleted file mode 100644 index a6f4adc..0000000 --- a/contrib/Opcode/Opcode.h +++ /dev/null @@ -1,72 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Main file for Opcode.dll. - * \file Opcode.h - * \author Pierre Terdiman - * \date March, 20, 2001 - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Include Guard -#ifndef __OPCODE_H__ -#define __OPCODE_H__ - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Preprocessor -#ifdef WIN32 - #ifdef OPCODE_EXPORTS - #define OPCODE_API __declspec(dllexport) - #else - #define OPCODE_API __declspec(dllimport) - #endif -#else - #define OPCODE_API -#endif - - #include "OPC_IceHook.h" - - namespace Opcode - { - // Bulk-of-the-work - #include "OPC_Settings.h" - #include "OPC_Common.h" - #include "OPC_MeshInterface.h" - // Builders - #include "OPC_TreeBuilders.h" - // Trees - #include "OPC_AABBTree.h" - #include "OPC_OptimizedTree.h" - // Models - #include "OPC_BaseModel.h" - #include "OPC_Model.h" - #include "OPC_HybridModel.h" - // Colliders - #include "OPC_Collider.h" - #include "OPC_VolumeCollider.h" - #include "OPC_TreeCollider.h" - #include "OPC_RayCollider.h" - #include "OPC_SphereCollider.h" - #include "OPC_OBBCollider.h" - #include "OPC_AABBCollider.h" - #include "OPC_LSSCollider.h" - #include "OPC_PlanesCollider.h" - // Usages - #include "OPC_Picking.h" - // Sweep-and-prune - #include "OPC_BoxPruning.h" - #include "OPC_SweepAndPrune.h" - - FUNCTION OPCODE_API bool InitOpcode(); - FUNCTION OPCODE_API bool CloseOpcode(); - } - -#endif // __OPCODE_H__ diff --git a/contrib/Opcode/ReadMe.txt b/contrib/Opcode/ReadMe.txt deleted file mode 100644 index ee16382..0000000 --- a/contrib/Opcode/ReadMe.txt +++ /dev/null @@ -1,171 +0,0 @@ - - OPCODE distribution 1.3 (june 2003) - ----------------------- - - New in Opcode 1.3: - - fixed the divide by 0 bug that was happening when all centers where located on a coordinate axis (thanks to Jorrit T) - - linearized "complete" vanilla AABB trees - - ANSI-compliant "for" loops (for the ones porting it to Linux...) - - callbacks & pointers moved to mesh interface - - support for triangle & vertex strides - - optimized the sphere-triangle overlap code a bit - - dynamic trees (refit) - - more builders - - ValidateSubdivision in builders - - LSS collider - - primitive-bv tests can now be skipped in most volume queries - - temporal coherence now also works for airborne objects - - temporal coherence completed for boxes / all contacts, LSS, etc - - ray-collider now uses a callback - - some common "usages" have been introduced (only picking for now) - - SPLIT_COMPLETE removed (now implicitely using mLimit = 1) - - hybrid collision models - - sweep-and-prune code added, moved from my old Z-Collide lib - - it now works with meshes made of only 1 triangle (except in mesh-mesh case!) - - Disclaimer: - - - I forced myself to actually *do* the release today no matter what. Else it would never have been done. That's - why the code may not be very polished. I also removed a *lot* of things (more usages, distance queries, etc...) - that weren't ready for prime-time (or that were linked to too many of my supporting libs) - - - Some comments may also be obsolete here and there. The old User Manual for Opcode 1.2 may not fit version 1.3 - either, since there's a new "mesh interface" to support strides, etc. - - - Everything in the "Ice" directory has been hacked out of my engine and edited until everything compiled. Don't - expect anything out there to be cute or something. In particular, some CPP files are not even included when not - needed, so you can expect some linker errors if you try messing around with them... - - Otherwise, it should be just like previous version, only better. In particular, hybrid models can be very - memory-friendly (sometimes using like 10 times less ram than the best trees from version 1.2). The possible - speed hit is often invisible (if it even exists), especially using temporal coherence in "all contacts" mode. - (Admittedly, this depends on your particular usage pattern / what you do on collided triangles). - - The sweep-and-prune code is similar to the "vanilla" version found in V-Collide (but that one's better IMHO...) - The simple "radix" version is often just as good, see for yourself. - - OPCODE distribution 1.2 (august 2002) - ----------------------- - - New in Opcode 1.2: - - new VolumeCollider base class - - simplified callback setup - - you can now use callbacks or pointers (setup at compile time) - - destination array not needed anymore in the RayCollider (faster in-out tests) - - renamed classes: AABBRayCollider => RayCollider, AABBSphereCollider => SphereCollider - - the sphere query now only returns a list of faces (extra info discarded). On the other hand it's a lot faster. - - OBB, AABB and planes queries. Original OBB and AABB queries contributed by Erwin de Vries. - - cosmetic changes in OPC_BoxBoxOverlap.h contributed by Gottfried Chen - - some inlining problems fixed - - faster ray-mesh tests using the separating axis theorem - - new split value in AABB tree construction (contributed by Igor Kravtchenko). Provides faster queries most of the time. - - improved temporal coherence for sphere & AABB queries (works in "All contacts" mode) - - Notes: - - - Everything in the "Ice code" directory (in VC++) is basically copy-pasted from my engine, with a lot - of code removed until there was no link error anymore. Don't expect those files to be cute or anything, - they've never been meant to be released and they're often updated/modified/messy. - - Some experimental features have been removed as well. Else I would never have released the 1.2... - - Not as polished/optimal as I would like it to be, but that's life. I promised myself to release it - before october 2002 (one YEAR later ?!).... That's the only reason why it's there. - - Some people reported ColDet was faster. Uh, come on. They were using Opcode in - "All contacts" mode whereas ColDet was doing "first contact"... - - OPCODE distribution 1.1 (october 2001) - ----------------------- - - New in Opcode 1.1: - - stabbing queries - - sphere queries - - abtract base class for colliders - - settings validation methods - - compilation flags now grouped in OPC_Settings.h - - smaller files, new VC++ virtual dirs (cleaner) - - Notes: - - - "override(baseclass)" is a personal cosmetic thing. It's the same as "virtual", but provides more info. - - I code in 1600*1200, so some lines may look a bit long.. - - This version is not as polished as the previous one due to lack of time. The stabbing & sphere queries - can still be optimized: for example by trying other atomic overlap tests. I'm using my first ray-AABB - code, but the newer one seems better. Tim Schröder's one is good as well. See: www.codercorner.com/RayAABB.cpp - - The trees can easily be compressed even more, I save this for later (lack of time, lack of time!) - - I removed various tests before releasing this one: - - a separation line, a.k.a. "front" in QuickCD, because gains were unclear - - distance queries in a PQP style, because it was way too slow - - support for deformable models, too slow as well - - You can easily use Opcode to do your player-vs-world collision detection, in a Nettle/Telemachos way. - If someone out there wants to donate some art / level for the cause, I'd be glad to release a demo. (current - demo uses copyrighted art I'm not allowed to spread) - - Sorry for the lack of real docs and/or solid examples. I just don't have enough time. - - OPCODE distribution 1.0 (march 2001) - ----------------------- - - - First release - - =============================================================================== - - WHAT ? - - OPCODE means OPtimized COllision DEtection. - So this is a collision detection package similar to RAPID. Here's a - quick list of features: - - - C++ interface, developed for Windows systems using VC++ 6.0 - - Works on arbitrary meshes (convex or non-convex), even polygon soups - - Current implementation uses AABB-trees - - Introduces Primitive-BV overlap tests during recursive collision queries (whereas - standard libraries only rely on Primitive-Primitive and BV-BV tests) - - Introduces no-leaf trees, i.e. collision trees whose leaf nodes have been removed - - Supports collision queries on quantized trees (decompressed on-the-fly) - - Supports "first contact" or "all contacts" modes (à la RAPID) - - Uses temporal coherence for "first contact" mode (~10 to 20 times faster, useful - in rigid body simulation during bisection) - - Memory footprint is 7.2 times smaller than RAPID's one, which is ideal for console - games with limited ram (actually, if you use the unmodified RAPID code using double - precision, it's more like 13 times smaller...) - - And yet it often runs faster than RAPID (according to RDTSC, sometimes more than 5 - times faster when objects are deeply overlapping) - - Performance is usually close to RAPID's one in close-proximity situations - - Stabbing, planes & volume queries (sphere, AABB, OBB, LSS) - - Sweep-and-prune - - Now works with deformable meshes - - Hybrid trees - - - What it can be used for: - - standard mesh-mesh collision detection (similar to RAPID, SOLID, QuickCD, PQP, ColDet...) - - N-body collisions (similar to V-Collide) - - camera-vs-world collisions (similar to Telemachos/Paul Nettle/Stan Melax articles) - - shadow feelers to speed up lightmap computations - - in-out tests to speed up voxelization processes - - picking - - rigid body simulation - - view frustum culling - - etc - - WHY ? - - - Because RAPID uses too many bytes. - - Because the idea was nice... - - WHEN ? - - It's been coded in march 2001 following a thread on the GD-Algorithms list. - - GDAlgorithms-list mailing list - GDAlgorithms-list@lists.sourceforge.net - http://lists.sourceforge.net/lists/listinfo/gdalgorithms-list - - WHO ? - - Pierre Terdiman - June, 1, 2003 - - p.terdiman@wanadoo.fr - p.terdiman@codercorner.com - - http://www.codercorner.com - http://www.codercorner.com/Opcode.htm diff --git a/contrib/Opcode/StdAfx.cpp b/contrib/Opcode/StdAfx.cpp deleted file mode 100644 index 2350f92..0000000 --- a/contrib/Opcode/StdAfx.cpp +++ /dev/null @@ -1,10 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//#define ICE_MAIN -#include "StdAfx.h" diff --git a/contrib/Opcode/StdAfx.h b/contrib/Opcode/StdAfx.h deleted file mode 100644 index 0223a6c..0000000 --- a/contrib/Opcode/StdAfx.h +++ /dev/null @@ -1,24 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/* - * OPCODE - Optimized Collision Detection - * Copyright (C) 2001 Pierre Terdiman - * Homepage: http://www.codercorner.com/Opcode.htm - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) -#define AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -// Insert your headers here -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - -#include "Opcode.h" - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) diff --git a/contrib/Opcode/TemporalCoherence.txt b/contrib/Opcode/TemporalCoherence.txt deleted file mode 100644 index 8fde158..0000000 --- a/contrib/Opcode/TemporalCoherence.txt +++ /dev/null @@ -1,32 +0,0 @@ - -> Hi John, -> -> I know I'll forget to tell you this if I don't write it right now.... -> -> >(2) How is the receiving geometry for the shadow decided? -> -> I wrote about an LSS-test but actually performing a new VFC test (from the -> light's view) is the same. In both cases, here's a trick to take advantage -> of temporal coherence : test the world against a slightly larger than -> necessary LSS or frustum. Keep the list of touched surfaces. Then next -> frame, if the new volume is still contained within the previous one used -for -> the query, you can reuse the same list immediately. Actually it's a bit -> similar to what you did in your sphere-tree, I think. Anyway, now the -O(log -> N) VFC is O(1) for some frames. It's not worth it for the "real" VFC, but -> when you have N virtual frustum to test to drop N shadows, that's another -> story. -> -> Two downsides: -> - You need more ram to keep track of one list of meshes / shadow, but -> usually it's not a lot. -> - By using a larger volume for the query you possibly touch more -> faces/surfaces, which will be rendered in the shadow pass. Usually it's -not -> a problem either since rendering is simply faster than geometric queries -> those days. But of course, "your mileage may vary". -> -> Happy new year ! -> -> Pierre diff --git a/contrib/gtest/CMakeLists.txt b/contrib/gtest/CMakeLists.txt deleted file mode 100644 index 657bacc..0000000 --- a/contrib/gtest/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(BUILD_GMOCK OFF CACHE INTERNAL "") -set(INSTALL_GTEST OFF CACHE INTERNAL "") -FetchContent_Declare( - GTest - URL https://github.com/google/googletest/archive/refs/tags/v1.13.0.tar.gz - URL_HASH SHA1=bfa4b5131b6eaac06962c251742c96aab3f7aa78 - DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/contrib/infoware/1.current.patch b/contrib/infoware/1.current.patch deleted file mode 100644 index 9ef31bc..0000000 --- a/contrib/infoware/1.current.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff '--color=auto' -ru a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-09 23:00:40.101308564 +0100 -+++ b/CMakeLists.txt 2024-03-09 22:59:36.067973296 +0100 -@@ -84,7 +84,7 @@ - find_package(Git) - endif() - --set(INFOWARE_PCI_DATA_DIR infoware_generated CACHE PATH "Output directory for the PCI ids generator") -+set(INFOWARE_PCI_DATA_DIR "${CMAKE_CURRENT_BINARY_DIR}/infoware_generated" CACHE PATH "Output directory for the PCI ids generator") - set(INFOWARE_PCI_DATA_HPP pci_data.hpp) - set(INFOWARE_PCI_DATA_GEN "${INFOWARE_PCI_DATA_DIR}/${INFOWARE_PCI_DATA_HPP}") - set(infoware_pci_ids_error "\ -@@ -132,13 +132,13 @@ - else() - include(ExternalProject) - ExternalProject_Add(infoware_generate_pcis -- SOURCE_DIR ${CMAKE_SOURCE_DIR} -- PREFIX ${CMAKE_BINARY_DIR}/pci_generator -- BINARY_DIR ${CMAKE_BINARY_DIR}/pci_generator -+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} -+ PREFIX ${CMAKE_CURRENT_BINARY_DIR}/pci_generator -+ BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/pci_generator - BUILD_COMMAND ${CMAKE_COMMAND} --build --target infoware_generate_pcis - INSTALL_COMMAND "" - BUILD_ALWAYS ON -- CMAKE_ARGS -DINFOWARE_PCI_DATA_DIR:PATH=${CMAKE_BINARY_DIR}/${INFOWARE_PCI_DATA_DIR}) -+ CMAKE_ARGS -DINFOWARE_PCI_DATA_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}/${INFOWARE_PCI_DATA_DIR}) - endif() - add_dependencies(infoware infoware_generate_pcis) - diff --git a/contrib/infoware/CMakeLists.txt b/contrib/infoware/CMakeLists.txt deleted file mode 100644 index 81c7b4b..0000000 --- a/contrib/infoware/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -FetchContent_Declare( - infoware - URL https://github.com/ThePhD/infoware/archive/e469b86.tar.gz - URL_HASH SHA1=e844ae80c5ca3f6b944571130ac3795c96a4e9ab - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.current.patch" -P ${PATCH_SCRIPT} - DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/contrib/libpng/1.zlib.patch b/contrib/libpng/1.zlib.patch deleted file mode 100644 index 7a225e9..0000000 --- a/contrib/libpng/1.zlib.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff '--color=auto' -aru a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-03 01:47:51.488773684 +0100 -+++ b/CMakeLists.txt 2024-03-03 01:49:14.398777099 +0100 -@@ -37,10 +37,6 @@ - set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) - set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) - --# needed packages --find_package(ZLIB REQUIRED) --include_directories(${ZLIB_INCLUDE_DIR}) -- - if(NOT WIN32) - find_library(M_LIBRARY - NAMES m -@@ -182,7 +178,7 @@ - endif() - - # NOW BUILD OUR TARGET --include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR}) -+include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - - if(PNG_SHARED) - add_library(${PNG_LIB_NAME} SHARED ${libpng_sources}) -@@ -191,7 +187,7 @@ - set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib") - set_target_properties(${PNG_LIB_NAME} PROPERTIES IMPORT_PREFIX "lib") - endif() -- target_link_libraries(${PNG_LIB_NAME} ${ZLIB_LIBRARY} ${M_LIBRARY}) -+ target_link_libraries(${PNG_LIB_NAME} Zlib::zlib ${M_LIBRARY}) - endif() - - if(PNG_STATIC) -@@ -202,7 +198,7 @@ - # msvc does not append 'lib' - do it here to have consistent name - set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib") - endif() -- target_link_libraries(${PNG_LIB_NAME_STATIC} ${ZLIB_LIBRARY} ${M_LIBRARY}) -+ target_link_libraries(${PNG_LIB_NAME_STATIC} Zlib::zlibstatic ${M_LIBRARY}) - endif() - - diff --git a/contrib/libpng/2.export.patch b/contrib/libpng/2.export.patch deleted file mode 100644 index 089ff85..0000000 --- a/contrib/libpng/2.export.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-03 02:11:53.952166254 +0100 -+++ b/CMakeLists.txt 2024-03-03 02:11:16.832164723 +0100 -@@ -380,12 +380,6 @@ - DESTINATION bin) - endif() - --# On versions of CMake that support it, create an export file CMake --# users can include() to import our targets --if(PNG_EXPORT_RULE AND NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL ) -- install(EXPORT libpng DESTINATION lib/libpng FILE lib${PNG_LIB_NAME}.cmake) --endif() -- - # what's with libpng-$VER%.txt and all the extra files? - - diff --git a/contrib/libpng/3.includes.patch b/contrib/libpng/3.includes.patch deleted file mode 100644 index c48e163..0000000 --- a/contrib/libpng/3.includes.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-03 02:11:16.832164723 +0100 -+++ b/CMakeLists.txt 2024-03-03 02:19:25.775518136 +0100 -@@ -106,7 +106,6 @@ - # Use the prebuilt pnglibconf.h file from the scripts folder - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt - ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h) --include_directories(${CMAKE_CURRENT_BINARY_DIR}) - - # OUR SOURCES - set(libpng_public_hdrs -@@ -177,9 +176,6 @@ - add_definitions(-DPNG_NO_FLOATING_POINT_SUPPORTED) - endif() - --# NOW BUILD OUR TARGET --include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -- - if(PNG_SHARED) - add_library(${PNG_LIB_NAME} SHARED ${libpng_sources}) - if(MSVC) -@@ -187,6 +183,7 @@ - set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib") - set_target_properties(${PNG_LIB_NAME} PROPERTIES IMPORT_PREFIX "lib") - endif() -+ target_include_directories(${PNG_LIB_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(${PNG_LIB_NAME} Zlib::zlib ${M_LIBRARY}) - endif() - -@@ -198,6 +195,7 @@ - # msvc does not append 'lib' - do it here to have consistent name - set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib") - endif() -+ target_include_directories(${PNG_LIB_NAME_STATIC} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(${PNG_LIB_NAME_STATIC} Zlib::zlibstatic ${M_LIBRARY}) - endif() - diff --git a/contrib/libpng/4.aliases.patch b/contrib/libpng/4.aliases.patch deleted file mode 100644 index 14d81d4..0000000 --- a/contrib/libpng/4.aliases.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-03 12:45:31.540235890 +0100 -+++ b/CMakeLists.txt 2024-03-03 12:46:11.986903772 +0100 -@@ -185,6 +185,7 @@ - endif() - target_include_directories(${PNG_LIB_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(${PNG_LIB_NAME} Zlib::zlib ${M_LIBRARY}) -+ add_library(Png::png ALIAS ${PNG_LIB_NAME}) - endif() - - if(PNG_STATIC) -@@ -197,6 +198,7 @@ - endif() - target_include_directories(${PNG_LIB_NAME_STATIC} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(${PNG_LIB_NAME_STATIC} Zlib::zlibstatic ${M_LIBRARY}) -+ add_library(Png::pngstatic ALIAS ${PNG_LIB_NAME_STATIC}) - endif() - - diff --git a/contrib/libpng/CMakeLists.txt b/contrib/libpng/CMakeLists.txt deleted file mode 100644 index c8aafb6..0000000 --- a/contrib/libpng/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -FetchContent_Declare( - libpng - URL - https://download.sourceforge.net/libpng/libpng-1.5.1.tar.gz - https://ftp.ignore.pl/starshatter/resources/mirror/libpng-1.5.1.tar.gz - URL_HASH SHA1=29afc7422d4d8af1066f8783ae148e298520d5ba - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.zlib.patch" -P ${PATCH_SCRIPT} - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/2.export.patch" -P ${PATCH_SCRIPT} - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/3.includes.patch" -P ${PATCH_SCRIPT} - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/4.aliases.patch" -P ${PATCH_SCRIPT} - DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/contrib/libpng/LICENSE b/contrib/libpng/LICENSE deleted file mode 100644 index b28f15c..0000000 --- a/contrib/libpng/LICENSE +++ /dev/null @@ -1,111 +0,0 @@ - -This copy of the libpng notices is provided for your convenience. In case of -any discrepancy between this copy and the notices in the file png.h that is -included in the libpng distribution, the latter shall prevail. - -COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: - -If you modify libpng you may insert additional notices immediately following -this sentence. - -This code is released under the libpng license. - -libpng versions 1.2.6, August 15, 2004, through 1.5.1, February 3, 2011, are -Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.2.5 -with the following individual added to the list of Contributing Authors - - Cosmin Truta - -libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are -Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.0.6 -with the following individuals added to the list of Contributing Authors - - Simon-Pierre Cadieux - Eric S. Raymond - Gilles Vollant - -and with the following additions to the disclaimer: - - There is no warranty against interference with your enjoyment of the - library or against infringement. There is no warranty that our - efforts or the library will fulfill any of your particular purposes - or needs. This library is provided with all faults, and the entire - risk of satisfactory quality, performance, accuracy, and effort is with - the user. - -libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are -Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-0.96, -with the following individuals added to the list of Contributing Authors: - - Tom Lane - Glenn Randers-Pehrson - Willem van Schaik - -libpng versions 0.89, June 1996, through 0.96, May 1997, are -Copyright (c) 1996, 1997 Andreas Dilger -Distributed according to the same disclaimer and license as libpng-0.88, -with the following individuals added to the list of Contributing Authors: - - John Bowler - Kevin Bracey - Sam Bushell - Magnus Holmgren - Greg Roelofs - Tom Tanner - -libpng versions 0.5, May 1995, through 0.88, January 1996, are -Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. - -For the purposes of this copyright and license, "Contributing Authors" -is defined as the following set of individuals: - - Andreas Dilger - Dave Martindale - Guy Eric Schalnat - Paul Schmidt - Tim Wegner - -The PNG Reference Library is supplied "AS IS". The Contributing Authors -and Group 42, Inc. disclaim all warranties, expressed or implied, -including, without limitation, the warranties of merchantability and of -fitness for any purpose. The Contributing Authors and Group 42, Inc. -assume no liability for direct, indirect, incidental, special, exemplary, -or consequential damages, which may result from the use of the PNG -Reference Library, even if advised of the possibility of such damage. - -Permission is hereby granted to use, copy, modify, and distribute this -source code, or portions hereof, for any purpose, without fee, subject -to the following restrictions: - -1. The origin of this source code must not be misrepresented. - -2. Altered versions must be plainly marked as such and must not - be misrepresented as being the original source. - -3. This Copyright notice may not be removed or altered from any - source or altered source distribution. - -The Contributing Authors and Group 42, Inc. specifically permit, without -fee, and encourage the use of this source code as a component to -supporting the PNG file format in commercial products. If you use this -source code in a product, acknowledgment is not required but would be -appreciated. - - -A "png_get_copyright" function is available, for convenient use in "about" -boxes and the like: - - printf("%s",png_get_copyright(NULL)); - -Also, the PNG logo (in PNG format, of course) is supplied in the -files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). - -Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a -certification mark of the Open Source Initiative. - -Glenn Randers-Pehrson -glennrp at users.sourceforge.net -February 3, 2011 diff --git a/contrib/ogg/1.cmake.patch b/contrib/ogg/1.cmake.patch deleted file mode 100644 index 1534d17..0000000 --- a/contrib/ogg/1.cmake.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 -+++ b/CMakeLists.txt 2024-03-03 12:39:28.260224931 +0100 -@@ -0,0 +1,107 @@ -+cmake_minimum_required(VERSION 2.8.7) -+project(libogg) -+ -+# Required modules -+include(GNUInstallDirs) -+include(CheckIncludeFiles) -+ -+# Build options -+option(BUILD_SHARED_LIBS "Build shared library" OFF) -+if(APPLE) -+ option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF) -+endif() -+ -+# Extract project version from configure.ac -+file(READ configure.ac CONFIGURE_AC_CONTENTS) -+string(REGEX MATCH "AC_INIT\\(\\[libogg\\],\\[([0-9]*).([0-9]*).([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) -+set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) -+set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) -+set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3}) -+set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) -+ -+# Helper function to get version-info -+function(get_version_info result current_var_name age_var_name revision_var_name) -+ string(REGEX MATCH "${current_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) -+ set(VERSION_INFO_CURRENT ${CMAKE_MATCH_1}) -+ -+ string(REGEX MATCH "${age_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) -+ set(VERSION_INFO_AGE ${CMAKE_MATCH_1}) -+ -+ string(REGEX MATCH "${revision_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) -+ set(VERSION_INFO_REVISION ${CMAKE_MATCH_1}) -+ -+ math(EXPR VERSION_INFO_CURRENT_MINUS_AGE "${VERSION_INFO_CURRENT} - ${VERSION_INFO_AGE}") -+ -+ set(${result} "${VERSION_INFO_CURRENT_MINUS_AGE}.${VERSION_INFO_AGE}.${VERSION_INFO_REVISION}" PARENT_SCOPE) -+endfunction() -+ -+# Helper function to configure pkg-config files -+function(configure_pkg_config_file pkg_config_file_in) -+ set(prefix ${CMAKE_INSTALL_PREFIX}) -+ set(exec_prefix ${CMAKE_INSTALL_FULL_BINDIR}) -+ set(libdir ${CMAKE_INSTALL_FULL_LIBDIR}) -+ set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR}) -+ set(VERSION ${PROJECT_VERSION}) -+ string(REPLACE ".in" "" pkg_config_file ${pkg_config_file_in}) -+ configure_file(${pkg_config_file_in} ${CMAKE_CURRENT_BINARY_DIR}/${pkg_config_file} @ONLY) -+endfunction() -+ -+message(STATUS "Configuring ${PROJECT_NAME} ${PROJECT_VERSION}") -+ -+# Configure config_type.h -+check_include_files(inttypes.h INCLUDE_INTTYPES_H) -+check_include_files(stdint.h INCLUDE_STDINT_H) -+check_include_files(sys/types.h INCLUDE_SYS_TYPES_H) -+ -+set(SIZE16 int16_t) -+set(USIZE16 uint16_t) -+set(SIZE32 int32_t) -+set(USIZE32 uint32_t) -+set(SIZE64 int64_t) -+ -+configure_file(include/ogg/config_types.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/ogg/config_types.h @ONLY) -+ -+set(OGG_HEADERS -+ ${CMAKE_CURRENT_BINARY_DIR}/include/ogg/config_types.h -+ include/ogg/ogg.h -+ include/ogg/os_types.h -+) -+ -+set(OGG_SOURCES -+ src/bitwise.c -+ src/framing.c -+) -+ -+if(MSVC) -+ list(APPEND OGG_SOURCES win32/ogg.def) -+endif() -+ -+if(BUILD_FRAMEWORK) -+ set(BUILD_SHARED_LIBS TRUE) -+endif() -+ -+include_directories(include ${CMAKE_CURRENT_BINARY_DIR}/include) -+add_library(ogg ${OGG_HEADERS} ${OGG_SOURCES}) -+target_include_directories(ogg PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -+add_library(Ogg::ogg ALIAS ogg) -+ -+get_version_info(OGG_VERSION_INFO "LIB_CURRENT" "LIB_AGE" "LIB_REVISION") -+set_target_properties( -+ ogg PROPERTIES -+ SOVERSION ${OGG_VERSION_INFO} -+ PUBLIC_HEADER "${OGG_HEADERS}" -+) -+ -+if(BUILD_FRAMEWORK) -+ set_target_properties(ogg PROPERTIES -+ FRAMEWORK TRUE -+ FRAMEWORK_VERSION ${PROJECT_VERSION} -+ MACOSX_FRAMEWORK_IDENTIFIER org.xiph.ogg -+ MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PROJECT_VERSION} -+ MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION} -+ XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" -+ OUTPUT_NAME Ogg -+ ) -+endif() -+ -+configure_pkg_config_file(ogg.pc.in) diff --git a/contrib/ogg/CMakeLists.txt b/contrib/ogg/CMakeLists.txt deleted file mode 100644 index a1d2372..0000000 --- a/contrib/ogg/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -FetchContent_Declare( - ogg - URL - https://downloads.xiph.org/releases/ogg/libogg-1.3.3.tar.gz - https://ftp.ignore.pl/starshatter/resources/mirror/libogg-1.3.3.tar.gz - URL_HASH SHA1=28ba40fd2e2d41988f658a0016fa7b534e509bc0 - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.cmake.patch" -P ${PATCH_SCRIPT} - DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/contrib/sha1/CMakeLists.txt b/contrib/sha1/CMakeLists.txt deleted file mode 100644 index cc6fab2..0000000 --- a/contrib/sha1/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project(Sha1) -add_library(${PROJECT_NAME} STATIC Sha1.cpp) -target_include_directories( - ${PROJECT_NAME} - PUBLIC include) diff --git a/contrib/sha1/Sha1.cpp b/contrib/sha1/Sha1.cpp deleted file mode 100644 index 7e3de70..0000000 --- a/contrib/sha1/Sha1.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/* -* Sha1.cpp -* -* Copyright (C) 1998 -* Paul E. Jones -* All Rights Reserved. -* -***************************************************************************** -* $Id: sha1.cpp,v 1.6 2001/03/20 06:54:54 paulej Exp $ -***************************************************************************** -* -* Description: -* This class implements the Secure Hashing Standard as defined -* in FIPS PUB 180-1 published April 17, 1995. -* -* The Secure Hashing Standard, which uses the Secure Hashing -* Algorithm (SHA), produces a 160-bit message digest for a -* given data stream. In theory, it is highly improbable that -* two messages will produce the same message digest. Therefore, -* this algorithm can serve as a means of providing a "fingerprint" -* for a message. -* -* Portability Issues: -* SHA-1 is defined in terms of 32-bit "words". This code was -* written with the expectation that the processor has at least -* a 32-bit machine word size. If the machine word size is larger, -* the code should still function properly. One caveat to that -* is that the input functions taking characters and character arrays -* assume that only 8 bits of information are stored in each character. -* -* Caveats: -* SHA-1 is designed to work with messages less than 2^64 bits long. -* Although SHA-1 allows a message digest to be generated for -* messages of any number of bits less than 2^64, this implementation -* only works with messages with a length that is a multiple of 8 -* bits. -* -*/ - - -#include "Sha1.h" - -/* -* SHA1 -* -* Description: -* This is the constructor for the sha1 class. -* -* Parameters: -* None. -* -* Returns: -* Nothing. -* -* Comments: -* -*/ -SHA1::SHA1() -{ - Reset(); -} - -/* -* ~SHA1 -* -* Description: -* This is the destructor for the sha1 class -* -* Parameters: -* None. -* -* Returns: -* Nothing. -* -* Comments: -* -*/ -SHA1::~SHA1() -{ - // The destructor does nothing -} - -/* -* Reset -* -* Description: -* This function will initialize the sha1 class member variables -* in preparation for computing a new message digest. -* -* Parameters: -* None. -* -* Returns: -* Nothing. -* -* Comments: -* -*/ -void SHA1::Reset() -{ - Length_Low = 0; - Length_High = 0; - Message_Block_Index = 0; - - H[0] = 0x67452301; - H[1] = 0xEFCDAB89; - H[2] = 0x98BADCFE; - H[3] = 0x10325476; - H[4] = 0xC3D2E1F0; - - Computed = false; - Corrupted = false; -} - -/* -* Result -* -* Description: -* This function will return the 160-bit message digest into the -* array provided. -* -* Parameters: -* message_digest_array: [out] -* This is an array of five unsigned integers which will be filled -* with the message digest that has been computed. -* -* Returns: -* True if successful, false if it failed. -* -* Comments: -* -*/ -bool SHA1::Result(unsigned *message_digest_array) -{ - int i; // Counter - - if (Corrupted) - { - return false; - } - - if (!Computed) - { - PadMessage(); - Computed = true; - } - - for(i = 0; i < 5; i++) - { - message_digest_array[i] = H[i]; - } - - return true; -} - -/* -* Input -* -* Description: -* This function accepts an array of octets as the next portion of -* the message. -* -* Parameters: -* message_array: [in] -* An array of characters representing the next portion of the -* message. -* -* Returns: -* Nothing. -* -* Comments: -* -*/ -void SHA1::Input( const unsigned char *message_array, -unsigned length) -{ - if (!length) - { - return; - } - - if (Computed || Corrupted) - { - Corrupted = true; - return; - } - - while(length-- && !Corrupted) - { - Message_Block[Message_Block_Index++] = (*message_array & 0xFF); - - Length_Low += 8; - Length_Low &= 0xFFFFFFFF; // Force it to 32 bits - if (Length_Low == 0) - { - Length_High++; - Length_High &= 0xFFFFFFFF; // Force it to 32 bits - if (Length_High == 0) - { - Corrupted = true; // Message is too long - } - } - - if (Message_Block_Index == 64) - { - ProcessMessageBlock(); - } - - message_array++; - } -} - -/* -* Input -* -* Description: -* This function accepts an array of octets as the next portion of -* the message. -* -* Parameters: -* message_array: [in] -* An array of characters representing the next portion of the -* message. -* length: [in] -* The length of the message_array -* -* Returns: -* Nothing. -* -* Comments: -* -*/ -void SHA1::Input( const char *message_array, -unsigned length) -{ - Input((unsigned char *) message_array, length); -} - -/* -* Input -* -* Description: -* This function accepts a single octets as the next message element. -* -* Parameters: -* message_element: [in] -* The next octet in the message. -* -* Returns: -* Nothing. -* -* Comments: -* -*/ -void SHA1::Input(unsigned char message_element) -{ - Input(&message_element, 1); -} - -/* -* Input -* -* Description: -* This function accepts a single octet as the next message element. -* -* Parameters: -* message_element: [in] -* The next octet in the message. -* -* Returns: -* Nothing. -* -* Comments: -* -*/ -void SHA1::Input(char message_element) -{ - Input((unsigned char *) &message_element, 1); -} - -/* -* operator<< -* -* Description: -* This operator makes it convenient to provide character strings to -* the SHA1 object for processing. -* -* Parameters: -* message_array: [in] -* The character array to take as input. -* -* Returns: -* A reference to the SHA1 object. -* -* Comments: -* Each character is assumed to hold 8 bits of information. -* -*/ -SHA1& SHA1::operator<<(const char *message_array) -{ - const char *p = message_array; - - while(*p) - { - Input(*p); - p++; - } - - return *this; -} - -/* -* operator<< -* -* Description: -* This operator makes it convenient to provide character strings to -* the SHA1 object for processing. -* -* Parameters: -* message_array: [in] -* The character array to take as input. -* -* Returns: -* A reference to the SHA1 object. -* -* Comments: -* Each character is assumed to hold 8 bits of information. -* -*/ -SHA1& SHA1::operator<<(const unsigned char *message_array) -{ - const unsigned char *p = message_array; - - while(*p) - { - Input(*p); - p++; - } - - return *this; -} - -/* -* operator<< -* -* Description: -* This function provides the next octet in the message. -* -* Parameters: -* message_element: [in] -* The next octet in the message -* -* Returns: -* A reference to the SHA1 object. -* -* Comments: -* The character is assumed to hold 8 bits of information. -* -*/ -SHA1& SHA1::operator<<(const char message_element) -{ - Input((unsigned char *) &message_element, 1); - - return *this; -} - -/* -* operator<< -* -* Description: -* This function provides the next octet in the message. -* -* Parameters: -* message_element: [in] -* The next octet in the message -* -* Returns: -* A reference to the SHA1 object. -* -* Comments: -* The character is assumed to hold 8 bits of information. -* -*/ -SHA1& SHA1::operator<<(const unsigned char message_element) -{ - Input(&message_element, 1); - - return *this; -} - -/* -* ProcessMessageBlock -* -* Description: -* This function will process the next 512 bits of the message -* stored in the Message_Block array. -* -* Parameters: -* None. -* -* Returns: -* Nothing. -* -* Comments: -* Many of the variable names in this function, especially the single -* character names, were used because those were the names used -* in the publication. -* -*/ -void SHA1::ProcessMessageBlock() -{ - const unsigned K[] = { // Constants defined for SHA-1 - 0x5A827999, - 0x6ED9EBA1, - 0x8F1BBCDC, - 0xCA62C1D6 - }; - int t; // Loop counter - unsigned temp; // Temporary word value - unsigned W[80]; // Word sequence - unsigned A, B, C, D, E; // Word buffers - - /* - * Initialize the first 16 words in the array W - */ - for(t = 0; t < 16; t++) - { - W[t] = Message_Block[t * 4] << 24; - W[t] |= Message_Block[t * 4 + 1] << 16; - W[t] |= Message_Block[t * 4 + 2] << 8; - W[t] |= Message_Block[t * 4 + 3]; - } - - for(t = 16; t < 80; t++) - { - W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); - } - - A = H[0]; - B = H[1]; - C = H[2]; - D = H[3]; - E = H[4]; - - for(t = 0; t < 20; t++) - { - temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 20; t < 40; t++) - { - temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 40; t < 60; t++) - { - temp = CircularShift(5,A) + - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 60; t < 80; t++) - { - temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = CircularShift(30,B); - B = A; - A = temp; - } - - H[0] = (H[0] + A) & 0xFFFFFFFF; - H[1] = (H[1] + B) & 0xFFFFFFFF; - H[2] = (H[2] + C) & 0xFFFFFFFF; - H[3] = (H[3] + D) & 0xFFFFFFFF; - H[4] = (H[4] + E) & 0xFFFFFFFF; - - Message_Block_Index = 0; -} - -/* -* PadMessage -* -* Description: -* According to the standard, the message must be padded to an even -* 512 bits. The first padding bit must be a '1'. The last 64 bits -* represent the length of the original message. All bits in between -* should be 0. This function will pad the message according to those -* rules by filling the message_block array accordingly. It will also -* call ProcessMessageBlock() appropriately. When it returns, it -* can be assumed that the message digest has been computed. -* -* Parameters: -* None. -* -* Returns: -* Nothing. -* -* Comments: -* -*/ -void SHA1::PadMessage() -{ - /* - * Check to see if the current message block is too small to hold - * the initial padding bits and length. If so, we will pad the - * block, process it, and then continue padding into a second block. - */ - if (Message_Block_Index > 55) - { - Message_Block[Message_Block_Index++] = 0x80; - while(Message_Block_Index < 64) - { - Message_Block[Message_Block_Index++] = 0; - } - - ProcessMessageBlock(); - - while(Message_Block_Index < 56) - { - Message_Block[Message_Block_Index++] = 0; - } - } - else - { - Message_Block[Message_Block_Index++] = 0x80; - while(Message_Block_Index < 56) - { - Message_Block[Message_Block_Index++] = 0; - } - - } - - /* - * Store the message length as the last 8 octets - */ - Message_Block[56] = (Length_High >> 24) & 0xFF; - Message_Block[57] = (Length_High >> 16) & 0xFF; - Message_Block[58] = (Length_High >> 8) & 0xFF; - Message_Block[59] = (Length_High) & 0xFF; - Message_Block[60] = (Length_Low >> 24) & 0xFF; - Message_Block[61] = (Length_Low >> 16) & 0xFF; - Message_Block[62] = (Length_Low >> 8) & 0xFF; - Message_Block[63] = (Length_Low) & 0xFF; - - ProcessMessageBlock(); -} - - -/* -* CircularShift -* -* Description: -* This member function will perform a circular shifting operation. -* -* Parameters: -* bits: [in] -* The number of bits to shift (1-31) -* word: [in] -* The value to shift (assumes a 32-bit integer) -* -* Returns: -* The shifted value. -* -* Comments: -* -*/ -unsigned SHA1::CircularShift(int bits, unsigned word) -{ - return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits)); -} diff --git a/contrib/sha1/include/Sha1.h b/contrib/sha1/include/Sha1.h deleted file mode 100644 index ec64462..0000000 --- a/contrib/sha1/include/Sha1.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -* Sha1.h -* -* Copyright (C) 1998 -* Paul E. Jones -* All Rights Reserved. -* -***************************************************************************** -* $Id: sha1.h,v 1.4 2001/03/20 06:25:06 paulej Exp $ -***************************************************************************** -* -* Description: -* This class implements the Secure Hashing Standard as defined -* in FIPS PUB 180-1 published April 17, 1995. -* -* Many of the variable names in this class, especially the single -* character names, were used because those were the names used -* in the publication. -* -* Please read the file sha1.cpp for more information. -* -*/ - -#ifndef _SHA1_H_ -#define _SHA1_H_ - -class SHA1 -{ - -public: - - SHA1(); - virtual ~SHA1(); - - /* - * Re-initialize the class - */ - void Reset(); - - /* - * Returns the message digest - */ - bool Result(unsigned *message_digest_array); - - /* - * Provide input to SHA1 - */ - void Input( const unsigned char *message_array, - unsigned length); - void Input( const char *message_array, - unsigned length); - void Input(unsigned char message_element); - void Input(char message_element); - SHA1& operator<<(const char *message_array); - SHA1& operator<<(const unsigned char *message_array); - SHA1& operator<<(const char message_element); - SHA1& operator<<(const unsigned char message_element); - -private: - - /* - * Process the next 512 bits of the message - */ - void ProcessMessageBlock(); - - /* - * Pads the current message block to 512 bits - */ - void PadMessage(); - - /* - * Performs a circular left shift operation - */ - inline unsigned CircularShift(int bits, unsigned word); - - unsigned H[5]; // Message digest buffers - - unsigned Length_Low; // Message length in bits - unsigned Length_High; // Message length in bits - - unsigned char Message_Block[64]; // 512-bit message blocks - int Message_Block_Index; // Index into message block array - - bool Computed; // Is the digest computed? - bool Corrupted; // Is the message digest corruped? - -}; - -#endif diff --git a/contrib/vorbis/1.cmake.patch b/contrib/vorbis/1.cmake.patch deleted file mode 100644 index 3737f42..0000000 --- a/contrib/vorbis/1.cmake.patch +++ /dev/null @@ -1,176 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 -+++ b/CMakeLists.txt 2024-03-03 12:44:24.470233876 +0100 -@@ -0,0 +1,59 @@ -+cmake_minimum_required(VERSION 2.8.7) -+project(vorbis) -+ -+# Required modules -+include(GNUInstallDirs) -+include(CheckIncludeFiles) -+ -+# Build options -+option(BUILD_SHARED_LIBS "Build shared library" OFF) -+if(APPLE) -+ option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF) -+endif() -+ -+if(BUILD_FRAMEWORK) -+ set(BUILD_SHARED_LIBS TRUE) -+endif() -+ -+# Extract project version from configure.ac -+file(READ configure.ac CONFIGURE_AC_CONTENTS) -+string(REGEX MATCH "AC_INIT\\(\\[libvorbis\\],\\[([0-9]*).([0-9]*).([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) -+set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) -+set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) -+set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3}) -+set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) -+ -+# Helper function to get version-info -+function(get_version_info result current_var_name age_var_name revision_var_name) -+ string(REGEX MATCH "${current_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) -+ set(VERSION_INFO_CURRENT ${CMAKE_MATCH_1}) -+ -+ string(REGEX MATCH "${age_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) -+ set(VERSION_INFO_AGE ${CMAKE_MATCH_1}) -+ -+ string(REGEX MATCH "${revision_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) -+ set(VERSION_INFO_REVISION ${CMAKE_MATCH_1}) -+ -+ math(EXPR VERSION_INFO_CURRENT_MINUS_AGE "${VERSION_INFO_CURRENT} - ${VERSION_INFO_AGE}") -+ -+ set(${result} "${VERSION_INFO_CURRENT_MINUS_AGE}.${VERSION_INFO_AGE}.${VERSION_INFO_REVISION}" PARENT_SCOPE) -+endfunction() -+ -+# Helper function to configure pkg-config files -+function(configure_pkg_config_file pkg_config_file_in) -+ set(prefix ${CMAKE_INSTALL_PREFIX}) -+ set(exec_prefix ${CMAKE_INSTALL_FULL_BINDIR}) -+ set(libdir ${CMAKE_INSTALL_FULL_LIBDIR}) -+ set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR}) -+ set(VERSION ${PROJECT_VERSION}) -+ string(REPLACE ".in" "" pkg_config_file ${pkg_config_file_in}) -+ configure_file(${pkg_config_file_in} ${pkg_config_file} @ONLY) -+endfunction() -+ -+message(STATUS "Configuring ${PROJECT_NAME} ${PROJECT_VERSION}") -+ -+add_subdirectory(lib) -+ -+configure_pkg_config_file(vorbis.pc.in) -+configure_pkg_config_file(vorbisenc.pc.in) -+configure_pkg_config_file(vorbisfile.pc.in) -diff '--color=auto' -arNu a/lib/CMakeLists.txt b/lib/CMakeLists.txt ---- a/lib/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 -+++ b/lib/CMakeLists.txt 2024-03-03 12:44:45.650234517 +0100 -@@ -0,0 +1,109 @@ -+set(VORBIS_PUBLIC_HEADERS -+ ../include/vorbis/codec.h -+ ../include/vorbis/vorbisenc.h -+ ../include/vorbis/vorbisfile.h -+) -+ -+set(VORBIS_HEADERS -+ envelope.h -+ lpc.h -+ lsp.h -+ codebook.h -+ misc.h -+ psy.h -+ masking.h -+ os.h -+ mdct.h -+ smallft.h -+ highlevel.h -+ registry.h -+ scales.h -+ window.h -+ lookup.h -+ lookup_data.h -+ codec_internal.h -+ backends.h -+ bitrate.h -+) -+ -+set(VORBIS_SOURCES -+ mdct.c -+ smallft.c -+ block.c -+ envelope.c -+ window.c -+ lsp.c -+ lpc.c -+ analysis.c -+ synthesis.c -+ psy.c -+ info.c -+ floor1.c -+ floor0.c -+ res0.c -+ mapping0.c -+ registry.c -+ codebook.c -+ sharedbook.c -+ lookup.c -+ bitrate.c -+) -+ -+set(VORBISFILE_SOURCES -+ vorbisfile.c -+) -+ -+set(VORBISENC_SOURCES -+ vorbisenc.c -+) -+ -+if(WIN32) -+ list(APPEND VORBIS_SOURCES vorbisenc.c) -+endif() -+ -+if(MSVC) -+ list(APPEND VORBIS_SOURCES ../win32/vorbis.def) -+ list(APPEND VORBISENC_SOURCES ../win32/vorbisenc.def) -+ list(APPEND VORBISFILE_SOURCES ../win32/vorbisfile.def) -+endif() -+ -+include_directories(../include) -+include_directories(.) -+ -+if (NOT BUILD_FRAMEWORK) -+ add_library(vorbis ${VORBIS_HEADERS} ${VORBIS_SOURCES}) -+ add_library(vorbisenc ${VORBISENC_SOURCES}) -+ add_library(vorbisfile ${VORBISFILE_SOURCES}) -+ -+ get_version_info(VORBIS_VERSION_INFO "V_LIB_CURRENT" "V_LIB_AGE" "V_LIB_REVISION") -+ set_target_properties(vorbis PROPERTIES SOVERSION ${VORBIS_VERSION_INFO}) -+ get_version_info(VORBISENC_VERSION_INFO "VE_LIB_CURRENT" "VE_LIB_AGE" "VE_LIB_REVISION") -+ set_target_properties(vorbisenc PROPERTIES SOVERSION ${VORBISENC_VERSION_INFO}) -+ get_version_info(VORBISFILE_VERSION_INFO "VF_LIB_CURRENT" "VF_LIB_AGE" "VF_LIB_REVISION") -+ set_target_properties(vorbisfile PROPERTIES SOVERSION ${VORBISFILE_VERSION_INFO}) -+ -+ target_include_directories(vorbis PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) -+ target_include_directories(vorbisenc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) -+ target_include_directories(vorbisfile PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) -+ -+ target_link_libraries(vorbis Ogg::ogg) -+ target_link_libraries(vorbisenc Ogg::ogg vorbis) -+ target_link_libraries(vorbisfile Ogg::ogg vorbis) -+ -+ add_library(Vorbis::vorbis ALIAS vorbis) -+ add_library(Vorbis::vorbisenc ALIAS vorbisenc) -+ add_library(Vorbis::vorbisfile ALIAS vorbisfile) -+else() -+ add_library(vorbis ${VORBIS_PUBLIC_HEADERS} ${VORBIS_HEADERS} ${VORBIS_SOURCES} ${VORBISFILE_SOURCES} ${VORBISENC_SOURCES}) -+ set_target_properties(vorbis PROPERTIES -+ FRAMEWORK TRUE -+ FRAMEWORK_VERSION ${PROJECT_VERSION} -+ MACOSX_FRAMEWORK_IDENTIFIER org.xiph.vorbis -+ MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PROJECT_VERSION} -+ MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION} -+ XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" -+ PUBLIC_HEADER "${VORBIS_PUBLIC_HEADERS}" -+ OUTPUT_NAME Vorbis -+ ) -+ target_link_libraries(vorbis ${OGG_LIBRARIES}) -+endif() diff --git a/contrib/vorbis/CMakeLists.txt b/contrib/vorbis/CMakeLists.txt deleted file mode 100644 index 643da7c..0000000 --- a/contrib/vorbis/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -FetchContent_Declare( - vorbis - URL - https://downloads.xiph.org/releases/vorbis/libvorbis-1.3.6.tar.gz - https://ftp.ignore.pl/starshatter/resources/mirror/libvorbis-1.3.6.tar.gz - URL_HASH SHA1=91f140c220d1fe3376d637dc5f3d046263784b1f - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.cmake.patch" -P ${PATCH_SCRIPT} - DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/contrib/zlib/1.zconf.patch b/contrib/zlib/1.zconf.patch deleted file mode 100644 index eab40b7..0000000 --- a/contrib/zlib/1.zconf.patch +++ /dev/null @@ -1,560 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-03 01:50:38.272113874 +0100 -+++ b/CMakeLists.txt 2024-03-03 01:54:30.605456738 +0100 -@@ -66,18 +66,6 @@ - include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - endif() - --if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) -- # If we're doing an out of source build and the user has a zconf.h -- # in their source tree... -- if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) -- message(STATUS "Renaming") -- message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") -- message(STATUS "to 'zconf.h.included' because this file is included with zlib") -- message(STATUS "but CMake generates it automatically in the build directory.") -- file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) -- endif() --endif() -- - set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) - configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein - ${ZLIB_PC} @ONLY) -diff '--color=auto' -arNu a/zconf.h b/zconf.h ---- a/zconf.h 2024-03-03 01:49:53.568778704 +0100 -+++ b/zconf.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,534 +0,0 @@ --/* zconf.h -- configuration of the zlib compression library -- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler -- * For conditions of distribution and use, see copyright notice in zlib.h -- */ -- --/* @(#) $Id$ */ -- --#ifndef ZCONF_H --#define ZCONF_H -- --/* -- * If you *really* need a unique prefix for all types and library functions, -- * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. -- * Even better than compiling with -DZ_PREFIX would be to use configure to set -- * this permanently in zconf.h using "./configure --zprefix". -- */ --#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ --# define Z_PREFIX_SET -- --/* all linked symbols and init macros */ --# define _dist_code z__dist_code --# define _length_code z__length_code --# define _tr_align z__tr_align --# define _tr_flush_bits z__tr_flush_bits --# define _tr_flush_block z__tr_flush_block --# define _tr_init z__tr_init --# define _tr_stored_block z__tr_stored_block --# define _tr_tally z__tr_tally --# define adler32 z_adler32 --# define adler32_combine z_adler32_combine --# define adler32_combine64 z_adler32_combine64 --# define adler32_z z_adler32_z --# ifndef Z_SOLO --# define compress z_compress --# define compress2 z_compress2 --# define compressBound z_compressBound --# endif --# define crc32 z_crc32 --# define crc32_combine z_crc32_combine --# define crc32_combine64 z_crc32_combine64 --# define crc32_z z_crc32_z --# define deflate z_deflate --# define deflateBound z_deflateBound --# define deflateCopy z_deflateCopy --# define deflateEnd z_deflateEnd --# define deflateGetDictionary z_deflateGetDictionary --# define deflateInit z_deflateInit --# define deflateInit2 z_deflateInit2 --# define deflateInit2_ z_deflateInit2_ --# define deflateInit_ z_deflateInit_ --# define deflateParams z_deflateParams --# define deflatePending z_deflatePending --# define deflatePrime z_deflatePrime --# define deflateReset z_deflateReset --# define deflateResetKeep z_deflateResetKeep --# define deflateSetDictionary z_deflateSetDictionary --# define deflateSetHeader z_deflateSetHeader --# define deflateTune z_deflateTune --# define deflate_copyright z_deflate_copyright --# define get_crc_table z_get_crc_table --# ifndef Z_SOLO --# define gz_error z_gz_error --# define gz_intmax z_gz_intmax --# define gz_strwinerror z_gz_strwinerror --# define gzbuffer z_gzbuffer --# define gzclearerr z_gzclearerr --# define gzclose z_gzclose --# define gzclose_r z_gzclose_r --# define gzclose_w z_gzclose_w --# define gzdirect z_gzdirect --# define gzdopen z_gzdopen --# define gzeof z_gzeof --# define gzerror z_gzerror --# define gzflush z_gzflush --# define gzfread z_gzfread --# define gzfwrite z_gzfwrite --# define gzgetc z_gzgetc --# define gzgetc_ z_gzgetc_ --# define gzgets z_gzgets --# define gzoffset z_gzoffset --# define gzoffset64 z_gzoffset64 --# define gzopen z_gzopen --# define gzopen64 z_gzopen64 --# ifdef _WIN32 --# define gzopen_w z_gzopen_w --# endif --# define gzprintf z_gzprintf --# define gzputc z_gzputc --# define gzputs z_gzputs --# define gzread z_gzread --# define gzrewind z_gzrewind --# define gzseek z_gzseek --# define gzseek64 z_gzseek64 --# define gzsetparams z_gzsetparams --# define gztell z_gztell --# define gztell64 z_gztell64 --# define gzungetc z_gzungetc --# define gzvprintf z_gzvprintf --# define gzwrite z_gzwrite --# endif --# define inflate z_inflate --# define inflateBack z_inflateBack --# define inflateBackEnd z_inflateBackEnd --# define inflateBackInit z_inflateBackInit --# define inflateBackInit_ z_inflateBackInit_ --# define inflateCodesUsed z_inflateCodesUsed --# define inflateCopy z_inflateCopy --# define inflateEnd z_inflateEnd --# define inflateGetDictionary z_inflateGetDictionary --# define inflateGetHeader z_inflateGetHeader --# define inflateInit z_inflateInit --# define inflateInit2 z_inflateInit2 --# define inflateInit2_ z_inflateInit2_ --# define inflateInit_ z_inflateInit_ --# define inflateMark z_inflateMark --# define inflatePrime z_inflatePrime --# define inflateReset z_inflateReset --# define inflateReset2 z_inflateReset2 --# define inflateResetKeep z_inflateResetKeep --# define inflateSetDictionary z_inflateSetDictionary --# define inflateSync z_inflateSync --# define inflateSyncPoint z_inflateSyncPoint --# define inflateUndermine z_inflateUndermine --# define inflateValidate z_inflateValidate --# define inflate_copyright z_inflate_copyright --# define inflate_fast z_inflate_fast --# define inflate_table z_inflate_table --# ifndef Z_SOLO --# define uncompress z_uncompress --# define uncompress2 z_uncompress2 --# endif --# define zError z_zError --# ifndef Z_SOLO --# define zcalloc z_zcalloc --# define zcfree z_zcfree --# endif --# define zlibCompileFlags z_zlibCompileFlags --# define zlibVersion z_zlibVersion -- --/* all zlib typedefs in zlib.h and zconf.h */ --# define Byte z_Byte --# define Bytef z_Bytef --# define alloc_func z_alloc_func --# define charf z_charf --# define free_func z_free_func --# ifndef Z_SOLO --# define gzFile z_gzFile --# endif --# define gz_header z_gz_header --# define gz_headerp z_gz_headerp --# define in_func z_in_func --# define intf z_intf --# define out_func z_out_func --# define uInt z_uInt --# define uIntf z_uIntf --# define uLong z_uLong --# define uLongf z_uLongf --# define voidp z_voidp --# define voidpc z_voidpc --# define voidpf z_voidpf -- --/* all zlib structs in zlib.h and zconf.h */ --# define gz_header_s z_gz_header_s --# define internal_state z_internal_state -- --#endif -- --#if defined(__MSDOS__) && !defined(MSDOS) --# define MSDOS --#endif --#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) --# define OS2 --#endif --#if defined(_WINDOWS) && !defined(WINDOWS) --# define WINDOWS --#endif --#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) --# ifndef WIN32 --# define WIN32 --# endif --#endif --#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) --# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) --# ifndef SYS16BIT --# define SYS16BIT --# endif --# endif --#endif -- --/* -- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more -- * than 64k bytes at a time (needed on systems with 16-bit int). -- */ --#ifdef SYS16BIT --# define MAXSEG_64K --#endif --#ifdef MSDOS --# define UNALIGNED_OK --#endif -- --#ifdef __STDC_VERSION__ --# ifndef STDC --# define STDC --# endif --# if __STDC_VERSION__ >= 199901L --# ifndef STDC99 --# define STDC99 --# endif --# endif --#endif --#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) --# define STDC --#endif --#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) --# define STDC --#endif --#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) --# define STDC --#endif --#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) --# define STDC --#endif -- --#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ --# define STDC --#endif -- --#ifndef STDC --# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ --# define const /* note: need a more gentle solution here */ --# endif --#endif -- --#if defined(ZLIB_CONST) && !defined(z_const) --# define z_const const --#else --# define z_const --#endif -- --#ifdef Z_SOLO -- typedef unsigned long z_size_t; --#else --# define z_longlong long long --# if defined(NO_SIZE_T) -- typedef unsigned NO_SIZE_T z_size_t; --# elif defined(STDC) --# include -- typedef size_t z_size_t; --# else -- typedef unsigned long z_size_t; --# endif --# undef z_longlong --#endif -- --/* Maximum value for memLevel in deflateInit2 */ --#ifndef MAX_MEM_LEVEL --# ifdef MAXSEG_64K --# define MAX_MEM_LEVEL 8 --# else --# define MAX_MEM_LEVEL 9 --# endif --#endif -- --/* Maximum value for windowBits in deflateInit2 and inflateInit2. -- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files -- * created by gzip. (Files created by minigzip can still be extracted by -- * gzip.) -- */ --#ifndef MAX_WBITS --# define MAX_WBITS 15 /* 32K LZ77 window */ --#endif -- --/* The memory requirements for deflate are (in bytes): -- (1 << (windowBits+2)) + (1 << (memLevel+9)) -- that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) -- plus a few kilobytes for small objects. For example, if you want to reduce -- the default memory requirements from 256K to 128K, compile with -- make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" -- Of course this will generally degrade compression (there's no free lunch). -- -- The memory requirements for inflate are (in bytes) 1 << windowBits -- that is, 32K for windowBits=15 (default value) plus about 7 kilobytes -- for small objects. --*/ -- -- /* Type declarations */ -- --#ifndef OF /* function prototypes */ --# ifdef STDC --# define OF(args) args --# else --# define OF(args) () --# endif --#endif -- --#ifndef Z_ARG /* function prototypes for stdarg */ --# if defined(STDC) || defined(Z_HAVE_STDARG_H) --# define Z_ARG(args) args --# else --# define Z_ARG(args) () --# endif --#endif -- --/* The following definitions for FAR are needed only for MSDOS mixed -- * model programming (small or medium model with some far allocations). -- * This was tested only with MSC; for other MSDOS compilers you may have -- * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, -- * just define FAR to be empty. -- */ --#ifdef SYS16BIT --# if defined(M_I86SM) || defined(M_I86MM) -- /* MSC small or medium model */ --# define SMALL_MEDIUM --# ifdef _MSC_VER --# define FAR _far --# else --# define FAR far --# endif --# endif --# if (defined(__SMALL__) || defined(__MEDIUM__)) -- /* Turbo C small or medium model */ --# define SMALL_MEDIUM --# ifdef __BORLANDC__ --# define FAR _far --# else --# define FAR far --# endif --# endif --#endif -- --#if defined(WINDOWS) || defined(WIN32) -- /* If building or using zlib as a DLL, define ZLIB_DLL. -- * This is not mandatory, but it offers a little performance increase. -- */ --# ifdef ZLIB_DLL --# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) --# ifdef ZLIB_INTERNAL --# define ZEXTERN extern __declspec(dllexport) --# else --# define ZEXTERN extern __declspec(dllimport) --# endif --# endif --# endif /* ZLIB_DLL */ -- /* If building or using zlib with the WINAPI/WINAPIV calling convention, -- * define ZLIB_WINAPI. -- * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. -- */ --# ifdef ZLIB_WINAPI --# ifdef FAR --# undef FAR --# endif --# include -- /* No need for _export, use ZLIB.DEF instead. */ -- /* For complete Windows compatibility, use WINAPI, not __stdcall. */ --# define ZEXPORT WINAPI --# ifdef WIN32 --# define ZEXPORTVA WINAPIV --# else --# define ZEXPORTVA FAR CDECL --# endif --# endif --#endif -- --#if defined (__BEOS__) --# ifdef ZLIB_DLL --# ifdef ZLIB_INTERNAL --# define ZEXPORT __declspec(dllexport) --# define ZEXPORTVA __declspec(dllexport) --# else --# define ZEXPORT __declspec(dllimport) --# define ZEXPORTVA __declspec(dllimport) --# endif --# endif --#endif -- --#ifndef ZEXTERN --# define ZEXTERN extern --#endif --#ifndef ZEXPORT --# define ZEXPORT --#endif --#ifndef ZEXPORTVA --# define ZEXPORTVA --#endif -- --#ifndef FAR --# define FAR --#endif -- --#if !defined(__MACTYPES__) --typedef unsigned char Byte; /* 8 bits */ --#endif --typedef unsigned int uInt; /* 16 bits or more */ --typedef unsigned long uLong; /* 32 bits or more */ -- --#ifdef SMALL_MEDIUM -- /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ --# define Bytef Byte FAR --#else -- typedef Byte FAR Bytef; --#endif --typedef char FAR charf; --typedef int FAR intf; --typedef uInt FAR uIntf; --typedef uLong FAR uLongf; -- --#ifdef STDC -- typedef void const *voidpc; -- typedef void FAR *voidpf; -- typedef void *voidp; --#else -- typedef Byte const *voidpc; -- typedef Byte FAR *voidpf; -- typedef Byte *voidp; --#endif -- --#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) --# include --# if (UINT_MAX == 0xffffffffUL) --# define Z_U4 unsigned --# elif (ULONG_MAX == 0xffffffffUL) --# define Z_U4 unsigned long --# elif (USHRT_MAX == 0xffffffffUL) --# define Z_U4 unsigned short --# endif --#endif -- --#ifdef Z_U4 -- typedef Z_U4 z_crc_t; --#else -- typedef unsigned long z_crc_t; --#endif -- --#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ --# define Z_HAVE_UNISTD_H --#endif -- --#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ --# define Z_HAVE_STDARG_H --#endif -- --#ifdef STDC --# ifndef Z_SOLO --# include /* for off_t */ --# endif --#endif -- --#if defined(STDC) || defined(Z_HAVE_STDARG_H) --# ifndef Z_SOLO --# include /* for va_list */ --# endif --#endif -- --#ifdef _WIN32 --# ifndef Z_SOLO --# include /* for wchar_t */ --# endif --#endif -- --/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and -- * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even -- * though the former does not conform to the LFS document), but considering -- * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as -- * equivalently requesting no 64-bit operations -- */ --#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 --# undef _LARGEFILE64_SOURCE --#endif -- --#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) --# define Z_HAVE_UNISTD_H --#endif --#ifndef Z_SOLO --# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) --# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ --# ifdef VMS --# include /* for off_t */ --# endif --# ifndef z_off_t --# define z_off_t off_t --# endif --# endif --#endif -- --#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 --# define Z_LFS64 --#endif -- --#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) --# define Z_LARGE64 --#endif -- --#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) --# define Z_WANT64 --#endif -- --#if !defined(SEEK_SET) && !defined(Z_SOLO) --# define SEEK_SET 0 /* Seek from beginning of file. */ --# define SEEK_CUR 1 /* Seek from current position. */ --# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ --#endif -- --#ifndef z_off_t --# define z_off_t long --#endif -- --#if !defined(_WIN32) && defined(Z_LARGE64) --# define z_off64_t off64_t --#else --# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) --# define z_off64_t __int64 --# else --# define z_off64_t z_off_t --# endif --#endif -- --/* MVS linker does not support external names larger than 8 bytes */ --#if defined(__MVS__) -- #pragma map(deflateInit_,"DEIN") -- #pragma map(deflateInit2_,"DEIN2") -- #pragma map(deflateEnd,"DEEND") -- #pragma map(deflateBound,"DEBND") -- #pragma map(inflateInit_,"ININ") -- #pragma map(inflateInit2_,"ININ2") -- #pragma map(inflateEnd,"INEND") -- #pragma map(inflateSync,"INSY") -- #pragma map(inflateSetDictionary,"INSEDI") -- #pragma map(compressBound,"CMBND") -- #pragma map(inflate_table,"INTABL") -- #pragma map(inflate_fast,"INFA") -- #pragma map(inflate_copyright,"INCOPY") --#endif -- --#endif /* ZCONF_H */ diff --git a/contrib/zlib/2.includes.patch b/contrib/zlib/2.includes.patch deleted file mode 100644 index b39d18d..0000000 --- a/contrib/zlib/2.includes.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-03 01:56:30.848795009 +0100 -+++ b/CMakeLists.txt 2024-03-03 01:57:13.198796744 +0100 -@@ -63,7 +63,6 @@ - set(CMAKE_DEBUG_POSTFIX "d") - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) - add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) -- include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - endif() - - set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) -@@ -71,7 +70,6 @@ - ${ZLIB_PC} @ONLY) - configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) --include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) - - - #============================================================================ -@@ -173,6 +171,8 @@ - - add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) - add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -+target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) -+target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) - set_target_properties(zlib PROPERTIES SOVERSION 1) - diff --git a/contrib/zlib/3.aliases.patch b/contrib/zlib/3.aliases.patch deleted file mode 100644 index 27cd075..0000000 --- a/contrib/zlib/3.aliases.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-03 01:57:46.865464794 +0100 -+++ b/CMakeLists.txt 2024-03-03 01:58:11.902132479 +0100 -@@ -175,6 +175,8 @@ - target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) - set_target_properties(zlib PROPERTIES SOVERSION 1) -+add_library(Zlib::zlib ALIAS zlib) -+add_library(Zlib::zlibstatic ALIAS zlibstatic) - - if(NOT CYGWIN) - # This property causes shared libraries on Linux to have the full version diff --git a/contrib/zlib/4.examples.patch b/contrib/zlib/4.examples.patch deleted file mode 100644 index 3c21686..0000000 --- a/contrib/zlib/4.examples.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2024-03-03 01:58:26.368799737 +0100 -+++ b/CMakeLists.txt 2024-03-03 01:58:33.615466706 +0100 -@@ -215,25 +215,3 @@ - if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) - install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") - endif() -- --#============================================================================ --# Example binaries --#============================================================================ -- --add_executable(example test/example.c) --target_link_libraries(example zlib) --add_test(example example) -- --add_executable(minigzip test/minigzip.c) --target_link_libraries(minigzip zlib) -- --if(HAVE_OFF64_T) -- add_executable(example64 test/example.c) -- target_link_libraries(example64 zlib) -- set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") -- add_test(example64 example64) -- -- add_executable(minigzip64 test/minigzip.c) -- target_link_libraries(minigzip64 zlib) -- set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") --endif() diff --git a/contrib/zlib/CMakeLists.txt b/contrib/zlib/CMakeLists.txt deleted file mode 100644 index d7a5aec..0000000 --- a/contrib/zlib/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -FetchContent_Declare( - zlib - URL https://www.zlib.net/fossils/zlib-1.2.11.tar.gz https://ftp.ignore.pl/starshatter/mirror/zlib-1.2.11.tar.gz - URL_HASH SHA1=e6d119755acdf9104d7ba236b1242696940ed6dd - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.zconf.patch" -P ${PATCH_SCRIPT} - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/2.includes.patch" -P ${PATCH_SCRIPT} - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/3.aliases.patch" -P ${PATCH_SCRIPT} - PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/4.examples.patch" -P ${PATCH_SCRIPT} - DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/contrib/zlib/LICENSE b/contrib/zlib/LICENSE deleted file mode 100644 index 4bcfe18..0000000 --- a/contrib/zlib/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -zlib.h -- interface of the 'zlib' general purpose compression library -version 1.2.11, January 15th, 2017 - -Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -The data format used by the zlib library is described by RFCs (Request for -Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt new file mode 100644 index 0000000..2c9f2f1 --- /dev/null +++ b/third-party/CMakeLists.txt @@ -0,0 +1,30 @@ +include(ApplyPatch) +include(FetchContent) +include(MakeAvailable) +add_subdirectory(gtest) +add_subdirectory(infoware) +add_subdirectory(libpng) +add_subdirectory(ogg) +add_subdirectory(vorbis) +add_subdirectory(zlib) +make_available(gtest infoware libpng ogg vorbis zlib) +add_subdirectory(Opcode) +add_subdirectory(sha1) +install( + TARGETS png15 Opcode + RUNTIME + COMPONENT Runtime + DESTINATION ${CMAKE_INSTALL_PREFIX} + ) +if(NOT MSVC) + foreach(LIB IN ITEMS "libstdc++-6.dll" "libwinpthread-1.dll" "libgcc_s_dw2-1.dll") + find_file(LIBRARY_${LIB} ${LIB} PATHS ${CMAKE_FIND_ROOT_PATH}/bin) + if(LIBRARY_${LIB}) + install( + PROGRAMS ${LIBRARY_${LIB}} + COMPONENT Runtime + DESTINATION ${CMAKE_INSTALL_PREFIX} + ) + endif() + endforeach() +endif() diff --git a/third-party/Opcode/CMakeLists.txt b/third-party/Opcode/CMakeLists.txt new file mode 100644 index 0000000..6010c50 --- /dev/null +++ b/third-party/Opcode/CMakeLists.txt @@ -0,0 +1,55 @@ +project(Opcode) +add_library( + Opcode + SHARED + OPC_AABBCollider.cpp + OPC_AABBTree.cpp + OPC_BaseModel.cpp + OPC_BoxPruning.cpp + OPC_Collider.cpp + OPC_Common.cpp + OPC_HybridModel.cpp + OPC_LSSCollider.cpp + OPC_MeshInterface.cpp + OPC_Model.cpp + OPC_OBBCollider.cpp + OPC_OptimizedTree.cpp + OPC_Picking.cpp + OPC_PlanesCollider.cpp + OPC_RayCollider.cpp + OPC_SphereCollider.cpp + OPC_SweepAndPrune.cpp + OPC_TreeBuilders.cpp + OPC_TreeCollider.cpp + OPC_VolumeCollider.cpp + Opcode.cpp + StdAfx.cpp + Ice/IceAABB.cpp + Ice/IceContainer.cpp + Ice/IceHPoint.cpp + Ice/IceIndexedTriangle.cpp + Ice/IceMatrix3x3.cpp + Ice/IceMatrix4x4.cpp + Ice/IceOBB.cpp + Ice/IcePlane.cpp + Ice/IcePoint.cpp + Ice/IceRandom.cpp + Ice/IceRay.cpp + Ice/IceRevisitedRadix.cpp + Ice/IceSegment.cpp + Ice/IceTriangle.cpp + Ice/IceUtils.cpp + ) +target_include_directories( + Opcode + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + ) +target_precompile_headers( + Opcode + PUBLIC StdAfx.h + ) +target_compile_definitions( + Opcode + PRIVATE OPCODE_EXPORTS + PUBLIC _ALLOW_KEYWORD_MACROS + ) diff --git a/third-party/Opcode/Doc/OpcodeUserManual.pdf b/third-party/Opcode/Doc/OpcodeUserManual.pdf new file mode 100644 index 0000000..4ca3f12 Binary files /dev/null and b/third-party/Opcode/Doc/OpcodeUserManual.pdf differ diff --git a/third-party/Opcode/Ice/IceAABB.cpp b/third-party/Opcode/Ice/IceAABB.cpp new file mode 100644 index 0000000..03bca6c --- /dev/null +++ b/third-party/Opcode/Ice/IceAABB.cpp @@ -0,0 +1,405 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains AABB-related code. + * \file IceAABB.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * AABB class. + * \class AABB + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the sum of two AABBs. + * \param aabb [in] the other AABB + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABB& AABB::Add(const AABB& aabb) +{ + // Compute new min & max values + IcePoint Min; GetMin(Min); + IcePoint Tmp; aabb.GetMin(Tmp); + Min.Min(Tmp); + + IcePoint Max; GetMax(Max); + aabb.GetMax(Tmp); + Max.Max(Tmp); + + // Update this + SetMinMax(Min, Max); + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Makes a cube from the AABB. + * \param cube [out] the cube AABB + * \return cube edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABB::MakeCube(AABB& cube) const +{ + IcePoint Ext; GetExtents(Ext); + float Max = Ext.Max(); + + IcePoint Cnt; GetCenter(Cnt); + cube.SetCenterExtents(Cnt, IcePoint(Max, Max, Max)); + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Makes a sphere from the AABB. + * \param sphere [out] sphere containing the AABB + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABB::MakeSphere(Sphere& sphere) const +{ + GetExtents(sphere.mCenter); + sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f; // To make sure sphere::Contains(*this) succeeds + GetCenter(sphere.mCenter); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks a box is inside another box. + * \param box [in] the other AABB + * \return true if current box is inside input box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABB::IsInside(const AABB& box) const +{ + if(box.GetMin(0)>GetMin(0)) return false; + if(box.GetMin(1)>GetMin(1)) return false; + if(box.GetMin(2)>GetMin(2)) return false; + if(box.GetMax(0) max.x) ? 2 : 0) // 2 = right + + ((local_eye.y < min.y) ? 4 : 0) // 4 = bottom + + ((local_eye.y > max.y) ? 8 : 0) // 8 = top + + ((local_eye.z < min.z) ? 16 : 0) // 16 = front + + ((local_eye.z > max.z) ? 32 : 0); // 32 = back + + // Look up number of vertices in outline + num = (sdword)gIndexList[pos][7]; + // Zero indicates invalid case + if(!num) return null; + + return &gIndexList[pos][0]; +} + +// calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box + +//const IcePoint& eye, //eye point (in bbox object coordinates) +//const AABB& box, //3d bbox +//const Matrix4x4& mat, //free transformation for bbox +//float width, float height, int& num) +float AABB::ComputeBoxArea(const IcePoint& eye, const Matrix4x4& mat, float width, float height, sdword& num) const +{ + const sbyte* Outline = ComputeOutline(eye, num); + if(!Outline) return -1.0f; + + // Compute box vertices + IcePoint vertexBox[8], dst[8]; + ComputePoints(vertexBox); + + // Transform all outline corners into 2D screen space + for(sdword i=0;i GetMax(0) || p.x < GetMin(0)) return FALSE; \ + if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \ + if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \ + return TRUE; \ + } + + enum AABBType + { + AABB_RENDER = 0, //!< AABB used for rendering. Not visible == not rendered. + AABB_UPDATE = 1, //!< AABB used for dynamic updates. Not visible == not updated. + + AABB_FORCE_DWORD = 0x7fffffff, + }; + +#ifdef USE_MINMAX + + struct ICEMATHS_API ShadowAABB + { + Point mMin; + Point mMax; + }; + + class ICEMATHS_API AABB + { + public: + //! Constructor + inline_ AABB() {} + //! Destructor + inline_ ~AABB() {} + + //! Type-independent methods + AABB_COMMON_METHODS; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from center & extents vectors. + * \param c [in] the center point + * \param e [in] the extents vector + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups a point AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPoint(const Point& pt) { mMin = mMax = pt; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the size of the AABB. The size is defined as the longest extent. + * \return the size of the AABB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float GetSize() const { Point e; GetExtents(e); return e.Max(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Extends the AABB. + * \param p [in] the next point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Extend(const Point& p) + { + if(p.x > mMax.x) mMax.x = p.x; + if(p.x < mMin.x) mMin.x = p.x; + + if(p.y > mMax.y) mMax.y = p.y; + if(p.y < mMin.y) mMin.y = p.y; + + if(p.z > mMax.z) mMax.z = p.z; + if(p.z < mMin.z) mMin.z = p.z; + } + // Data access + + //! Get min point of the box + inline_ void GetMin(Point& min) const { min = mMin; } + //! Get max point of the box + inline_ void GetMax(Point& max) const { max = mMax; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mMin[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mMax[axis]; } + + //! Get box center + inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; } + //! Get box extents + inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; } + + //! Get component of the box's center along a given axis + inline_ float GetCenter(udword axis) const { return (mMax[axis] + mMin[axis])*0.5f; } + //! Get component of the box's extents along a given axis + inline_ float GetExtents(udword axis) const { return (mMax[axis] - mMin[axis])*0.5f; } + + //! Get box diagonal + inline_ void GetDiagonal(Point& diagonal) const { diagonal = mMax - mMin; } + inline_ float GetWidth() const { return mMax.x - mMin.x; } + inline_ float GetHeight() const { return mMax.y - mMin.y; } + inline_ float GetDepth() const { return mMax.z - mMin.z; } + + //! Volume + inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the intersection between two AABBs. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a) const + { + if(mMax.x < a.mMin.x + || a.mMax.x < mMin.x + || mMax.y < a.mMin.y + || a.mMax.y < mMin.y + || mMax.z < a.mMin.z + || a.mMax.z < mMin.z) return FALSE; + + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the 1D-intersection between two AABBs, on a given axis. + * \param a [in] the other AABB + * \param axis [in] the axis (0, 1, 2) + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a, udword axis) const + { + if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. + * Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it) + * \param mtx [in] the transform matrix + * \param aabb [out] the transformed AABB [can be *this] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const + { + // The three edges transformed: you can efficiently transform an X-only vector + // by just getting the "X" column of the matrix + Point vx,vy,vz; + mtx.GetRow(0, vx); vx *= (mMax.x - mMin.x); + mtx.GetRow(1, vy); vy *= (mMax.y - mMin.y); + mtx.GetRow(2, vz); vz *= (mMax.z - mMin.z); + + // Transform the min point + aabb.mMin = aabb.mMax = mMin * mtx; + + // Take the transformed min & axes and find new extents + // Using CPU code in the right place is faster... + if(IS_NEGATIVE_FLOAT(vx.x)) aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x; + if(IS_NEGATIVE_FLOAT(vx.y)) aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y; + if(IS_NEGATIVE_FLOAT(vx.z)) aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z; + if(IS_NEGATIVE_FLOAT(vy.x)) aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x; + if(IS_NEGATIVE_FLOAT(vy.y)) aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y; + if(IS_NEGATIVE_FLOAT(vy.z)) aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z; + if(IS_NEGATIVE_FLOAT(vz.x)) aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x; + if(IS_NEGATIVE_FLOAT(vz.y)) aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y; + if(IS_NEGATIVE_FLOAT(vz.z)) aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the AABB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Min, Max) boxes: min < max + if(mMin.x > mMax.x) return FALSE; + if(mMin.y > mMax.y) return FALSE; + if(mMin.z > mMax.z) return FALSE; + return TRUE; + } + + //! Operator for AABB *= float. Scales the extents, keeps same center. + inline_ AABB& operator*=(float s) + { + Point Center; GetCenter(Center); + Point Extents; GetExtents(Extents); + SetCenterExtents(Center, Extents * s); + return *this; + } + + //! Operator for AABB /= float. Scales the extents, keeps same center. + inline_ AABB& operator/=(float s) + { + Point Center; GetCenter(Center); + Point Extents; GetExtents(Extents); + SetCenterExtents(Center, Extents / s); + return *this; + } + + //! Operator for AABB += Point. Translates the box. + inline_ AABB& operator+=(const Point& trans) + { + mMin+=trans; + mMax+=trans; + return *this; + } + private: + Point mMin; //!< Min point + Point mMax; //!< Max point + }; + +#else + + class ICEMATHS_API AABB + { + public: + //! Constructor + inline_ AABB() {} + //! Destructor + inline_ ~AABB() {} + + //! Type-independent methods + AABB_COMMON_METHODS; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetMinMax(const IcePoint& min, const IcePoint& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from center & extents vectors. + * \param c [in] the center point + * \param e [in] the extents vector + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetCenterExtents(const IcePoint& c, const IcePoint& e) { mCenter = c; mExtents = e; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups a point AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPoint(const IcePoint& pt) { mCenter = pt; mExtents.Zero(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the size of the AABB. The size is defined as the longest extent. + * \return the size of the AABB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float GetSize() const { return mExtents.Max(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Extends the AABB. + * \param p [in] the next point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Extend(const IcePoint& p) + { + IcePoint Max = mCenter + mExtents; + IcePoint Min = mCenter - mExtents; + + if(p.x > Max.x) Max.x = p.x; + if(p.x < Min.x) Min.x = p.x; + + if(p.y > Max.y) Max.y = p.y; + if(p.y < Min.y) Min.y = p.y; + + if(p.z > Max.z) Max.z = p.z; + if(p.z < Min.z) Min.z = p.z; + + SetMinMax(Min, Max); + } + // Data access + + //! Get min point of the box + inline_ void GetMin(IcePoint& min) const { min = mCenter - mExtents; } + //! Get max point of the box + inline_ void GetMax(IcePoint& max) const { max = mCenter + mExtents; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } + + //! Get box center + inline_ void GetCenter(IcePoint& center) const { center = mCenter; } + //! Get box extents + inline_ void GetExtents(IcePoint& extents) const { extents = mExtents; } + + //! Get component of the box's center along a given axis + inline_ float GetCenter(udword axis) const { return mCenter[axis]; } + //! Get component of the box's extents along a given axis + inline_ float GetExtents(udword axis) const { return mExtents[axis]; } + + //! Get box diagonal + inline_ void GetDiagonal(IcePoint& diagonal) const { diagonal = mExtents * 2.0f; } + inline_ float GetWidth() const { return mExtents.x * 2.0f; } + inline_ float GetHeight() const { return mExtents.y * 2.0f; } + inline_ float GetDepth() const { return mExtents.z * 2.0f; } + + //! Volume + inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the intersection between two AABBs. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a) const + { + float tx = mCenter.x - a.mCenter.x; float ex = a.mExtents.x + mExtents.x; if(AIR(tx) > IR(ex)) return FALSE; + float ty = mCenter.y - a.mCenter.y; float ey = a.mExtents.y + mExtents.y; if(AIR(ty) > IR(ey)) return FALSE; + float tz = mCenter.z - a.mCenter.z; float ez = a.mExtents.z + mExtents.z; if(AIR(tz) > IR(ez)) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * The standard intersection method from Gamasutra. Just here to check its speed against the one above. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool GomezIntersect(const AABB& a) + { + IcePoint T = mCenter - a.mCenter; // Vector from A to B + return ((fabsf(T.x) <= (a.mExtents.x + mExtents.x)) + && (fabsf(T.y) <= (a.mExtents.y + mExtents.y)) + && (fabsf(T.z) <= (a.mExtents.z + mExtents.z))); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the 1D-intersection between two AABBs, on a given axis. + * \param a [in] the other AABB + * \param axis [in] the axis (0, 1, 2) + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a, udword axis) const + { + float t = mCenter[axis] - a.mCenter[axis]; + float e = a.mExtents[axis] + mExtents[axis]; + if(AIR(t) > IR(e)) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. + * \param mtx [in] the transform matrix + * \param aabb [out] the transformed AABB [can be *this] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const + { + // Compute new center + aabb.mCenter = mCenter * mtx; + + // Compute new extents. FPU code & CPU code have been interleaved for improved performance. + IcePoint Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x); + IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff; + + IcePoint Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y); + IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff; + + IcePoint Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z); + IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff; + + aabb.mExtents.x = Ex.x + Ey.x + Ez.x; + aabb.mExtents.y = Ex.y + Ey.y + Ez.y; + aabb.mExtents.z = Ex.z + Ey.z + Ez.z; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the AABB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Center, Extents) boxes: Extents >= 0 + if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE; + if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE; + if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE; + return TRUE; + } + + //! Operator for AABB *= float. Scales the extents, keeps same center. + inline_ AABB& operator*=(float s) { mExtents*=s; return *this; } + + //! Operator for AABB /= float. Scales the extents, keeps same center. + inline_ AABB& operator/=(float s) { mExtents/=s; return *this; } + + //! Operator for AABB += Point. Translates the box. + inline_ AABB& operator+=(const IcePoint& trans) + { + mCenter+=trans; + return *this; + } + private: + IcePoint mCenter; //!< AABB Center + IcePoint mExtents; //!< x, y and z extents + }; + +#endif + + inline_ void ComputeMinMax(const IcePoint& p, IcePoint& min, IcePoint& max) + { + if(p.x > max.x) max.x = p.x; + if(p.x < min.x) min.x = p.x; + + if(p.y > max.y) max.y = p.y; + if(p.y < min.y) min.y = p.y; + + if(p.z > max.z) max.z = p.z; + if(p.z < min.z) min.z = p.z; + } + + inline_ void ComputeAABB(AABB& aabb, const IcePoint* list, udword nb_pts) + { + if(list) + { + IcePoint Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); + IcePoint Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT); + while(nb_pts--) + { +// _prefetch(list+1); // off by one ? + ComputeMinMax(*list++, Mini, Maxi); + } + aabb.SetMinMax(Mini, Maxi); + } + } + +#endif // __ICEAABB_H__ diff --git a/third-party/Opcode/Ice/IceAxes.h b/third-party/Opcode/Ice/IceAxes.h new file mode 100644 index 0000000..842b55e --- /dev/null +++ b/third-party/Opcode/Ice/IceAxes.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains axes definition. + * \file IceAxes.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEAXES_H__ +#define __ICEAXES_H__ + + enum PointComponent + { + _X = 0, + _Y = 1, + _Z = 2, + _W = 3, + + _FORCE_DWORD = 0x7fffffff + }; + + enum AxisOrder + { + AXES_XYZ = (_X)|(_Y<<2)|(_Z<<4), + AXES_XZY = (_X)|(_Z<<2)|(_Y<<4), + AXES_YXZ = (_Y)|(_X<<2)|(_Z<<4), + AXES_YZX = (_Y)|(_Z<<2)|(_X<<4), + AXES_ZXY = (_Z)|(_X<<2)|(_Y<<4), + AXES_ZYX = (_Z)|(_Y<<2)|(_X<<4), + + AXES_FORCE_DWORD = 0x7fffffff + }; + + class ICEMATHS_API Axes + { + public: + + inline_ Axes(AxisOrder order) + { + mAxis0 = (order ) & 3; + mAxis1 = (order>>2) & 3; + mAxis2 = (order>>4) & 3; + } + inline_ ~Axes() {} + + udword mAxis0; + udword mAxis1; + udword mAxis2; + }; + +#endif // __ICEAXES_H__ diff --git a/third-party/Opcode/Ice/IceBoundingSphere.h b/third-party/Opcode/Ice/IceBoundingSphere.h new file mode 100644 index 0000000..df2861d --- /dev/null +++ b/third-party/Opcode/Ice/IceBoundingSphere.h @@ -0,0 +1,142 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to compute the minimal bounding sphere. + * \file IceBoundingSphere.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEBOUNDINGSPHERE_H__ +#define __ICEBOUNDINGSPHERE_H__ + + enum BSphereMethod + { + BS_NONE, + BS_GEMS, + BS_MINIBALL, + + BS_FORCE_DWORD = 0x7fffffff + }; + + class ICEMATHS_API Sphere + { + public: + //! Constructor + inline_ Sphere() {} + //! Constructor + inline_ Sphere(const IcePoint& center, float radius) : mCenter(center), mRadius(radius) {} + //! Constructor + Sphere(udword nb_verts, const IcePoint* verts); + //! Copy constructor + inline_ Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius) {} + //! Destructor + inline_ ~Sphere() {} + + BSphereMethod Compute(udword nb_verts, const IcePoint* verts); + bool FastCompute(udword nb_verts, const IcePoint* verts); + + // Access methods + inline_ const IcePoint& GetCenter() const { return mCenter; } + inline_ float GetRadius() const { return mRadius; } + + inline_ const IcePoint& Center() const { return mCenter; } + inline_ float Radius() const { return mRadius; } + + inline_ Sphere& Set(const IcePoint& center, float radius) { mCenter = center; mRadius = radius; return *this; } + inline_ Sphere& SetCenter(const IcePoint& center) { mCenter = center; return *this; } + inline_ Sphere& SetRadius(float radius) { mRadius = radius; return *this; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a IcePoint is contained within the sphere. + * \param p [in] the IcePoint to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const IcePoint& p) const + { + return mCenter.SquareDistance(p) <= mRadius*mRadius; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a sphere is contained within the sphere. + * \param sphere [in] the sphere to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const Sphere& sphere) const + { + // If our radius is the smallest, we can't possibly contain the other sphere + if(mRadius < sphere.mRadius) return false; + // So r is always positive or null now + float r = mRadius - sphere.mRadius; + return mCenter.SquareDistance(sphere.mCenter) <= r*r; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a box is contained within the sphere. + * \param aabb [in] the box to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Contains(const AABB& aabb) const + { + // I assume if all 8 box vertices are inside the sphere, so does the whole box. + // Sounds ok but maybe there's a better way? + float R2 = mRadius * mRadius; +#ifdef USE_MIN_MAX + const IcePoint& Max = ((ShadowAABB&)&aabb).mMax; + const IcePoint& Min = ((ShadowAABB&)&aabb).mMin; +#else + IcePoint Max; aabb.GetMax(Max); + IcePoint Min; aabb.GetMin(Min); +#endif + IcePoint p; + p.x=Max.x; p.y=Max.y; p.z=Max.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Max.y; p.z=Min.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if the sphere intersects another sphere + * \param sphere [in] the other sphere + * \return true if spheres overlap + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Intersect(const Sphere& sphere) const + { + float r = mRadius + sphere.mRadius; + return mCenter.SquareDistance(sphere.mCenter) <= r*r; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the sphere is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for spheres: Radius >= 0.0f + if(mRadius < 0.0f) return FALSE; + return TRUE; + } + public: + IcePoint mCenter; //!< Sphere center + float mRadius; //!< Sphere radius + }; + +#endif // __ICEBOUNDINGSPHERE_H__ diff --git a/third-party/Opcode/Ice/IceContainer.cpp b/third-party/Opcode/Ice/IceContainer.cpp new file mode 100644 index 0000000..dc59602 --- /dev/null +++ b/third-party/Opcode/Ice/IceContainer.cpp @@ -0,0 +1,357 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a simple container class. + * \file IceContainer.cpp + * \author Pierre Terdiman + * \date February, 5, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a list of 32-bits values. + * Use this class when you need to store an unknown number of values. The list is automatically + * resized and can contains 32-bits entities (dwords or floats) + * + * \class Container + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceCore; + +// Static members +#ifdef CONTAINER_STATS +#ifdef OPCODE_EXPORTS +udword Container::mNbContainers = 0; +udword Container::mUsedRam = 0; +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. No entries allocated there. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. Also allocates a given number of entries. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif + SetSize(size); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Copy constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif + *this = object; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. Frees everything and leaves. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::~Container() +{ + Empty(); +#ifdef CONTAINER_STATS + mNbContainers--; + mUsedRam-=GetUsedRam(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Clears the container. All stored values are deleted, and it frees used ram. + * \see Reset() + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container& Container::Empty() +{ +#ifdef CONTAINER_STATS + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + DELETEARRAY(mEntries); + mCurNbEntries = mMaxNbEntries = 0; + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Resizes the container. + * \param needed [in] assume the container can be added at least "needed" values + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Container::Resize(udword needed) +{ +#ifdef CONTAINER_STATS + // Subtract previous amount of bytes + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + + // Get more entries + mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2 + if(mMaxNbEntriesmMaxNbEntries) Resize(nb); + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword)); + mCurNbEntries+=nb; + return *this; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * A O(1) method to add a value in the container. The container is automatically resized if needed. + * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation + * costs a lot more than the call overhead... + * + * \param entry [in] a float to store in the container + * \see Add(udword entry) + * \see Empty() + * \see Contains(udword entry) + * \return Self-Reference + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ Container& Add(float entry) + { + // Resize if needed + if(mCurNbEntries==mMaxNbEntries) Resize(); + + // Add new entry + mEntries[mCurNbEntries++] = IR(entry); + return *this; + } + + inline_ Container& Add(const float* entries, udword nb) + { + // Resize if needed + if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb); + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float)); + mCurNbEntries+=nb; + return *this; + } + + //! Add unique [slow] + inline_ Container& AddUnique(udword entry) + { + if(!Contains(entry)) Add(entry); + return *this; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Clears the container. All stored values are deleted, and it frees used ram. + * \see Reset() + * \return Self-Reference + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Container& Empty(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again. + * That's a kind of temporal coherence. + * \see Empty() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Reset() + { + // Avoid the write if possible + // ### CMOV + if(mCurNbEntries) mCurNbEntries = 0; + } + + // HANDLE WITH CARE + inline_ void ForceSize(udword size) + { + mCurNbEntries = size; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Sets the initial size of the container. If it already contains something, it's discarded. + * \param nb [in] Number of entries + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetSize(udword nb); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the container and get rid of unused bytes. + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Refit(); + + // Checks whether the container already contains a given value. + bool Contains(udword entry, udword* location=null) const; + // Deletes an entry - doesn't preserve insertion order. + bool Delete(udword entry); + // Deletes an entry - does preserve insertion order. + bool DeleteKeepingOrder(udword entry); + //! Deletes the very last entry. + inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; } + //! Deletes the entry whose index is given + inline_ void DeleteIndex(udword index) { mEntries[index] = mEntries[--mCurNbEntries]; } + + // Helpers + Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP); + Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP); + // Data access. + inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries. + inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry + inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries. + + inline_ udword GetFirst() const { return mEntries[0]; } + inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; } + + // Growth control + inline_ float GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor + inline_ void SetGrowthFactor(float growth) { mGrowthFactor = growth; } //!< Sets the growth factor + inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full + inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty + + //! Read-access as an array + inline_ udword operator[](udword i) const { ASSERT(i>=0 && i=0 && i + #include + + #define SIGN_BITMASK 0x80000000 + + //! Integer representation of a floating-point value. + #define IR(x) ((udword&)(x)) + + //! Signed integer representation of a floating-point value. + #define SIR(x) ((sdword&)(x)) + + //! Absolute integer representation of a floating-point value + #define AIR(x) (IR(x)&0x7fffffff) + + //! Floating-point representation of an integer value. + #define FR(x) ((float&)(x)) + + //! Integer-based comparison of a floating point value. + //! Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context. + #define IS_NEGATIVE_FLOAT(x) (IR(x)&0x80000000) + + //! Fast fabs for floating-point values. It just clears the sign bit. + //! Don't use it blindy, it can be faster or slower than the FPU comparison, depends on the context. + inline_ float FastFabs(float x) + { + udword FloatBits = IR(x)&0x7fffffff; + return FR(FloatBits); + } + + //! Fast square root for floating-point values. + inline_ float FastSqrt(float square) + { + return std::sqrt(square); + } + + //! Saturates positive to zero. + inline_ float fsat(float f) + { + udword y = (udword&)f & ~((sdword&)f >>31); + return (float&)y; + } + + //! Computes 1.0f / sqrtf(x). + inline_ float frsqrt(float f) + { + float x = f * 0.5f; + udword y = 0x5f3759df - ((udword&)f >> 1); + // Iteration... + (float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) ); + // Result + return (float&)y; + } + + //! Computes 1.0f / sqrtf(x). Comes from NVIDIA. + inline_ float InvSqrt(const float& x) + { + udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1; + float y = *(float*)&tmp; + return y * (1.47f - 0.47f * x * y * y); + } + + //! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above. + //! See http://www.magic-software.com/3DGEDInvSqrt.html + inline_ float RSqrt(float number) + { + long i; + float x2, y; + const float threehalfs = 1.5f; + + x2 = number * 0.5f; + y = number; + i = * (long *) &y; + i = 0x5f3759df - (i >> 1); + y = * (float *) &i; + y = y * (threehalfs - (x2 * y * y)); + + return y; + } + + //! TO BE DOCUMENTED + inline_ float fsqrt(float f) + { + udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000; + // Iteration...? + // (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f; + // Result + return (float&)y; + } + + //! Returns the float ranged espilon value. + inline_ float fepsilon(float f) + { + udword b = (udword&)f & 0xff800000; + udword a = b | 0x00000001; + (float&)a -= (float&)b; + // Result + return (float&)a; + } + + //! Is the float valid ? + inline_ bool IsNAN(float value) { return (IR(value)&0x7f800000) == 0x7f800000; } + inline_ bool IsIndeterminate(float value) { return IR(value) == 0xffc00000; } + inline_ bool IsPlusInf(float value) { return IR(value) == 0x7f800000; } + inline_ bool IsMinusInf(float value) { return IR(value) == 0xff800000; } + + inline_ bool IsValidFloat(float value) + { + if(IsNAN(value)) return false; + if(IsIndeterminate(value)) return false; + if(IsPlusInf(value)) return false; + if(IsMinusInf(value)) return false; + return true; + } + + #define CHECK_VALID_FLOAT(x) ASSERT(IsValidFloat(x)); + +/* + //! FPU precision setting function. + inline_ void SetFPU() + { + // This function evaluates whether the floating-point + // control word is set to single precision/round to nearest/ + // exceptions disabled. If these conditions don't hold, the + // function changes the control word to set them and returns + // TRUE, putting the old control word value in the passback + // location pointed to by pwOldCW. + { + uword wTemp, wSave; + + __asm fstcw wSave + if (wSave & 0x300 || // Not single mode + 0x3f != (wSave & 0x3f) || // Exceptions enabled + wSave & 0xC00) // Not round to nearest mode + { + __asm + { + mov ax, wSave + and ax, not 300h ;; single mode + or ax, 3fh ;; disable all exceptions + and ax, not 0xC00 ;; round to nearest mode + mov wTemp, ax + fldcw wTemp + } + } + } + } +*/ + //! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON) + inline_ float ComputeFloatEpsilon() + { + float f = 1.0f; + ((udword&)f)^=1; + return f - 1.0f; // You can check it's the same as FLT_EPSILON + } + + inline_ bool IsFloatZero(float x, float epsilon=1e-6f) + { + return x*x < epsilon; + } + + //! A global function to find MAX(a,b) using FCOMI/FCMOV + inline_ float FCMax2(float a, float b) + { + return (std::max)(a, b); + } + + //! A global function to find MIN(a,b) using FCOMI/FCMOV + inline_ float FCMin2(float a, float b) + { + return (std::min)(a, b); + } + + //! A global function to find MAX(a,b,c) using FCOMI/FCMOV + inline_ float FCMax3(float a, float b, float c) + { + return (std::max)((std::max)(a, b), c); + } + + //! A global function to find MIN(a,b,c) using FCOMI/FCMOV + inline_ float FCMin3(float a, float b, float c) + { + return (std::min)((std::min)(a, b), c); + } + + inline_ int ConvertToSortable(float f) + { + int& Fi = (int&)f; + int Fmask = (Fi>>31); + Fi ^= Fmask; + Fmask &= ~(1<<31); + Fi -= Fmask; + return Fi; + } + + enum FPUMode + { + FPU_FLOOR = 0, + FPU_CEIL = 1, + FPU_BEST = 2, + + FPU_FORCE_DWORD = 0x7fffffff + }; + + FUNCTION ICECORE_API FPUMode GetFPUMode(); + FUNCTION ICECORE_API void SaveFPU(); + FUNCTION ICECORE_API void RestoreFPU(); + FUNCTION ICECORE_API void SetFPUFloorMode(); + FUNCTION ICECORE_API void SetFPUCeilMode(); + FUNCTION ICECORE_API void SetFPUBestMode(); + + FUNCTION ICECORE_API void SetFPUPrecision24(); + FUNCTION ICECORE_API void SetFPUPrecision53(); + FUNCTION ICECORE_API void SetFPUPrecision64(); + FUNCTION ICECORE_API void SetFPURoundingChop(); + FUNCTION ICECORE_API void SetFPURoundingUp(); + FUNCTION ICECORE_API void SetFPURoundingDown(); + FUNCTION ICECORE_API void SetFPURoundingNear(); + + FUNCTION ICECORE_API int intChop(const float& f); + FUNCTION ICECORE_API int intFloor(const float& f); + FUNCTION ICECORE_API int intCeil(const float& f); + +#endif // __ICEFPU_H__ diff --git a/third-party/Opcode/Ice/IceHPoint.cpp b/third-party/Opcode/Ice/IceHPoint.cpp new file mode 100644 index 0000000..daa7038 --- /dev/null +++ b/third-party/Opcode/Ice/IceHPoint.cpp @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for homogeneous points. + * \file IceHPoint.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Homogeneous point. + * + * Use it: + * - for clipping in homogeneous space (standard way) + * - to differentiate between points (w=1) and vectors (w=0). + * - in some cases you can also use it instead of IcePoint for padding reasons. + * + * \class HPoint + * \author Pierre Terdiman + * \version 1.0 + * \warning No cross-product in 4D. + * \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// IcePoint Mul = HPoint * Matrix3x3; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +IcePoint HPoint::operator*(const Matrix3x3& mat) const +{ + return IcePoint( + x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0], + x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1], + x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] ); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HPoint Mul = HPoint * Matrix4x4; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HPoint HPoint::operator*(const Matrix4x4& mat) const +{ + return HPoint( + x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0], + x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1], + x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2], + x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HPoint *= Matrix4x4 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HPoint& HPoint::operator*=(const Matrix4x4& mat) +{ + float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0]; + float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1]; + float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2]; + float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]; + + x = xp; y = yp; z = zp; w = wp; + + return *this; +} + diff --git a/third-party/Opcode/Ice/IceHPoint.h b/third-party/Opcode/Ice/IceHPoint.h new file mode 100644 index 0000000..f7d0d16 --- /dev/null +++ b/third-party/Opcode/Ice/IceHPoint.h @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for homogeneous points. + * \file IceHPoint.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEHPOINT_H__ +#define __ICEHPOINT_H__ + + class ICEMATHS_API HPoint : public IcePoint + { + public: + + //! Empty constructor + inline_ HPoint() {} + //! Constructor from floats + inline_ HPoint(float _x, float _y, float _z, float _w=0.0f) : IcePoint(_x, _y, _z), w(_w) {} + //! Constructor from array + inline_ HPoint(const float f[4]) : IcePoint(f), w(f[3]) {} + //! Constructor from a Point + inline_ HPoint(const IcePoint& p, float _w=0.0f) : IcePoint(p), w(_w) {} + //! Destructor + inline_ ~HPoint() {} + + //! Clear the point + inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; } + + //! Assignment from values + inline_ HPoint& Set(float _x, float _y, float _z, float _w ) { x = _x; y = _y; z = _z; w = _w; return *this; } + //! Assignment from array + inline_ HPoint& Set(const float f[4]) { x = f[_X]; y = f[_Y]; z = f[_Z]; w = f[_W]; return *this; } + //! Assignment from another h-point + inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; } + + //! Add a vector + inline_ HPoint& Add(float _x, float _y, float _z, float _w ) { x += _x; y += _y; z += _z; w += _w; return *this; } + //! Add a vector + inline_ HPoint& Add(const float f[4]) { x += f[_X]; y += f[_Y]; z += f[_Z]; w += f[_W]; return *this; } + + //! Subtract a vector + inline_ HPoint& Sub(float _x, float _y, float _z, float _w ) { x -= _x; y -= _y; z -= _z; w -= _w; return *this; } + //! Subtract a vector + inline_ HPoint& Sub(const float f[4]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; w -= f[_W]; return *this; } + + //! Multiplies by a scalar + inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; } + + //! Returns MIN(x, y, z, w); + float Min() const { return MIN(x, MIN(y, MIN(z, w))); } + //! Returns MAX(x, y, z, w); + float Max() const { return MAX(x, MAX(y, MAX(z, w))); } + //! Sets each element to be componentwise minimum + HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; } + //! Sets each element to be componentwise maximum + HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; } + + //! Computes square magnitude + inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; } + //! Computes magnitude + inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); } + + //! Normalize the vector + inline_ HPoint& Normalize() + { + float M = Magnitude(); + if(M) + { + M = 1.0f / M; + x *= M; + y *= M; + z *= M; + w *= M; + } + return *this; + } + + // Arithmetic operators + //! Operator for HPoint Negate = - HPoint; + inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); } + + //! Operator for HPoint Plus = HPoint + HPoint; + inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); } + //! Operator for HPoint Minus = HPoint - HPoint; + inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); } + + //! Operator for HPoint Mul = HPoint * HPoint; + inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); } + //! Operator for HPoint Scale = HPoint * float; + inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); } + //! Operator for HPoint Scale = float * HPoint; + inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); } + + //! Operator for HPoint Div = HPoint / HPoint; + inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); } + //! Operator for HPoint Scale = HPoint / float; + inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); } + //! Operator for HPoint Scale = float / HPoint; + inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); } + + //! Operator for float DotProd = HPoint | HPoint; + inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; } + // No cross-product in 4D + + //! Operator for HPoint += HPoint; + inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; } + //! Operator for HPoint += float; + inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; } + + //! Operator for HPoint -= HPoint; + inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; } + //! Operator for HPoint -= float; + inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; } + + //! Operator for HPoint *= HPoint; + inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; } + //! Operator for HPoint *= float; + inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; } + + //! Operator for HPoint /= HPoint; + inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; } + //! Operator for HPoint /= float; + inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; } + + // Arithmetic operators + + //! Operator for Point Mul = HPoint * Matrix3x3; + IcePoint operator*(const Matrix3x3& mat) const; + //! Operator for HPoint Mul = HPoint * Matrix4x4; + HPoint operator*(const Matrix4x4& mat) const; + + // HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 + //! Operator for HPoint *= Matrix4x4 + HPoint& operator*=(const Matrix4x4& mat); + + // Logical operators + + //! Operator for "if(HPoint==HPoint)" + inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); } + //! Operator for "if(HPoint!=HPoint)" + inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); } + + // Cast operators + + //! Cast a HPoint to a Point. w is discarded. + inline_ operator HPoint() const { return IcePoint(x, y, z); } + + public: + float w; + }; + +#endif // __ICEHPOINT_H__ + diff --git a/third-party/Opcode/Ice/IceIndexedTriangle.cpp b/third-party/Opcode/Ice/IceIndexedTriangle.cpp new file mode 100644 index 0000000..3e74cbb --- /dev/null +++ b/third-party/Opcode/Ice/IceIndexedTriangle.cpp @@ -0,0 +1,548 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy indexed triangle class. + * \file IceIndexedTriangle.cpp + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an indexed triangle class. + * + * \class Triangle + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Flips the winding order. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Flip() +{ + Swap(mVRef[1], mVRef[2]); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle area. + * \param verts [in] the list of indexed vertices + * \return the area + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Area(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + const IcePoint& p0 = verts[0]; + const IcePoint& p1 = verts[1]; + const IcePoint& p2 = verts[2]; + return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle perimeter. + * \param verts [in] the list of indexed vertices + * \return the perimeter + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Perimeter(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + const IcePoint& p0 = verts[0]; + const IcePoint& p1 = verts[1]; + const IcePoint& p2 = verts[2]; + return p0.Distance(p1) + + p0.Distance(p2) + + p1.Distance(p2); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle compacity. + * \param verts [in] the list of indexed vertices + * \return the compacity + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Compacity(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + float P = Perimeter(verts); + if(P==0.0f) return 0.0f; + return (4.0f*PI*Area(verts)/(P*P)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle normal. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Normal(const IcePoint* verts, IcePoint& normal) const +{ + if(!verts) return; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + normal = ((p2-p1)^(p0-p1)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle denormalized normal. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::DenormalizedNormal(const IcePoint* verts, IcePoint& normal) const +{ + if(!verts) return; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + normal = ((p2-p1)^(p0-p1)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle center. + * \param verts [in] the list of indexed vertices + * \param center [out] the computed center + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Center(const IcePoint* verts, IcePoint& center) const +{ + if(!verts) return; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + center = (p0+p1+p2)*INV3; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the centered normal + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed centered normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::CenteredNormal(const IcePoint* verts, IcePoint& normal) const +{ + if(!verts) return; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + IcePoint Center = (p0+p1+p2)*INV3; + normal = Center + ((p2-p1)^(p0-p1)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a random point within the triangle. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed centered normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::RandomPoint(const IcePoint* verts, IcePoint& random) const +{ + if(!verts) return; + + // Random barycentric coords + float Alpha = UnitRandomFloat(); + float Beta = UnitRandomFloat(); + float Gamma = UnitRandomFloat(); + float OneOverTotal = 1.0f / (Alpha + Beta + Gamma); + Alpha *= OneOverTotal; + Beta *= OneOverTotal; + Gamma *= OneOverTotal; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + random = Alpha*p0 + Beta*p1 + Gamma*p2; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes backface culling. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which culling must be computed + * \return true if the triangle is visible from the source point + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::IsVisible(const IcePoint* verts, const IcePoint& source) const +{ + // Checkings + if(!verts) return false; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + + // Compute denormalized normal + IcePoint Normal = (p2 - p1)^(p0 - p1); + + // Backface culling + return (Normal | source) >= 0.0f; + +// Same as: +// IcePlane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); +// return PL.Distance(source) > PL.d; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes backface culling. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which culling must be computed + * \return true if the triangle is visible from the source point + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::BackfaceCulling(const IcePoint* verts, const IcePoint& source) const +{ + // Checkings + if(!verts) return false; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + + // Compute base +// IcePoint Base = (p0 + p1 + p2)*INV3; + + // Compute denormalized normal + IcePoint Normal = (p2 - p1)^(p0 - p1); + + // Backface culling +// return (Normal | (source - Base)) >= 0.0f; + return (Normal | (source - p0)) >= 0.0f; + +// Same as: (but a bit faster) +// IcePlane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); +// return PL.Distance(source)>0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the occlusion potential of the triangle. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which occlusion potential must be computed + * \return the occlusion potential + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::ComputeOcclusionPotential(const IcePoint* verts, const IcePoint& view) const +{ + if(!verts) return 0.0f; + // Occlusion potential: -(A * (N|V) / d^2) + // A = polygon area + // N = polygon normal + // V = view vector + // d = distance viewpoint-center of polygon + + float A = Area(verts); + IcePoint N; Normal(verts, N); + IcePoint C; Center(verts, C); + float d = view.Distance(C); + return -(A*(N|view))/(d*d); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Replaces a vertex reference with another one. + * \param oldref [in] the vertex reference to replace + * \param newref [in] the new vertex reference + * \return true if success, else false if the input vertex reference doesn't belong to the triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::ReplaceVertex(udword oldref, udword newref) +{ + if(mVRef[0]==oldref) { mVRef[0] = newref; return true; } + else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; } + else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle. + * \return true if the triangle is degenerate + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::IsDegenerate() const +{ + if(mVRef[0]==mVRef[1]) return true; + if(mVRef[1]==mVRef[2]) return true; + if(mVRef[2]==mVRef[0]) return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the input vertex reference belongs to the triangle or not. + * \param ref [in] the vertex reference to look for + * \return true if the triangle contains the vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::HasVertex(udword ref) const +{ + if(mVRef[0]==ref) return true; + if(mVRef[1]==ref) return true; + if(mVRef[2]==ref) return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the input vertex reference belongs to the triangle or not. + * \param ref [in] the vertex reference to look for + * \param index [out] the corresponding index in the triangle + * \return true if the triangle contains the vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::HasVertex(udword ref, udword* index) const +{ + if(mVRef[0]==ref) { *index = 0; return true; } + if(mVRef[1]==ref) { *index = 1; return true; } + if(mVRef[2]==ref) { *index = 2; return true; } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Finds an edge in a tri, given two vertex references. + * \param vref0 [in] the edge's first vertex reference + * \param vref1 [in] the edge's second vertex reference + * \return the edge number between 0 and 2, or 0xff if input refs are wrong. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ubyte IndexedTriangle::FindEdge(udword vref0, udword vref1) const +{ + if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0; + else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0; + else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1; + else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1; + else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2; + else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2; + return 0xff; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the last reference given the first two. + * \param vref0 [in] the first vertex reference + * \param vref1 [in] the second vertex reference + * \return the last reference, or INVALID_ID if input refs are wrong. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword IndexedTriangle::OppositeVertex(udword vref0, udword vref1) const +{ + if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2]; + else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2]; + else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1]; + else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1]; + else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0]; + else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0]; + return INVALID_ID; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the three sorted vertex references according to an edge number. + * edgenb = 0 => edge 0-1, returns references 0, 1, 2 + * edgenb = 1 => edge 0-2, returns references 0, 2, 1 + * edgenb = 2 => edge 1-2, returns references 1, 2, 0 + * + * \param edgenb [in] the edge number, 0, 1 or 2 + * \param vref0 [out] the returned first vertex reference + * \param vref1 [out] the returned second vertex reference + * \param vref2 [out] the returned third vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const +{ + if(edgenb==0) + { + vref0 = mVRef[0]; + vref1 = mVRef[1]; + vref2 = mVRef[2]; + } + else if(edgenb==1) + { + vref0 = mVRef[0]; + vref1 = mVRef[2]; + vref2 = mVRef[1]; + } + else if(edgenb==2) + { + vref0 = mVRef[1]; + vref1 = mVRef[2]; + vref2 = mVRef[0]; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's smallest edge length. + * \param verts [in] the list of indexed vertices + * \return the smallest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::MinEdgeLength(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + + float Min = MAX_FLOAT; + float Length01 = verts[0].Distance(verts[1]); + float Length02 = verts[0].Distance(verts[2]); + float Length12 = verts[1].Distance(verts[2]); + if(Length01 < Min) Min = Length01; + if(Length02 < Min) Min = Length02; + if(Length12 < Min) Min = Length12; + return Min; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's largest edge length. + * \param verts [in] the list of indexed vertices + * \return the largest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::MaxEdgeLength(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + + float Max = MIN_FLOAT; + float Length01 = verts[0].Distance(verts[1]); + float Length02 = verts[0].Distance(verts[2]); + float Length12 = verts[1].Distance(verts[2]); + if(Length01 > Max) Max = Length01; + if(Length02 > Max) Max = Length02; + if(Length12 > Max) Max = Length12; + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a point on the triangle according to the stabbing information. + * \param verts [in] the list of indexed vertices + * \param u,v [in] point's barycentric coordinates + * \param pt [out] point on triangle + * \param nearvtx [out] index of nearest vertex + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::ComputePoint(const IcePoint* verts, float u, float v, IcePoint& pt, udword* nearvtx) const +{ + // Checkings + if(!verts) return; + + // Get face in local or global space + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + + // Compute point coordinates + pt = (1.0f - u - v)*p0 + u*p1 + v*p2; + + // Compute nearest vertex if needed + if(nearvtx) + { + // Compute distance vector + IcePoint d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face + p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face + p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face + + // Get smallest distance + *nearvtx = mVRef[d.SmallestAxis()]; + } +} + + //************************************** + // Angle between two vectors (in radians) + // we use this formula + // uv = |u||v| cos(u,v) + // u ^ v = w + // |w| = |u||v| |sin(u,v)| + //************************************** + float Angle(const IcePoint& u, const IcePoint& v) + { + float NormU = u.Magnitude(); // |u| + float NormV = v.Magnitude(); // |v| + float Product = NormU*NormV; // |u||v| + if(Product==0.0f) return 0.0f; + float OneOverProduct = 1.0f / Product; + + // Cosinus + float Cosinus = (u|v) * OneOverProduct; + + // Sinus + IcePoint w = u^v; + float NormW = w.Magnitude(); + + float AbsSinus = NormW * OneOverProduct; + + // Remove degeneracy + if(AbsSinus > 1.0f) AbsSinus = 1.0f; + if(AbsSinus < -1.0f) AbsSinus = -1.0f; + + if(Cosinus>=0.0f) return asinf(AbsSinus); + else return (PI-asinf(AbsSinus)); + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the angle between two triangles. + * \param tri [in] the other triangle + * \param verts [in] the list of indexed vertices + * \return the angle in radians + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Angle(const IndexedTriangle& tri, const IcePoint* verts) const +{ + // Checkings + if(!verts) return 0.0f; + + // Compute face normals + IcePoint n0, n1; + Normal(verts, n0); + tri.Normal(verts, n1); + + // Compute angle + float dp = n0|n1; + if(dp>1.0f) return 0.0f; + if(dp<-1.0f) return PI; + return acosf(dp); + +// return ::Angle(n0,n1); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks a triangle is the same as another one. + * \param tri [in] the other triangle + * \return true if same triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::Equal(const IndexedTriangle& tri) const +{ + // Test all vertex references + return (HasVertex(tri.mVRef[0]) && + HasVertex(tri.mVRef[1]) && + HasVertex(tri.mVRef[2])); +} diff --git a/third-party/Opcode/Ice/IceIndexedTriangle.h b/third-party/Opcode/Ice/IceIndexedTriangle.h new file mode 100644 index 0000000..ef279c2 --- /dev/null +++ b/third-party/Opcode/Ice/IceIndexedTriangle.h @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy indexed triangle class. + * \file IceIndexedTriangle.h + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEINDEXEDTRIANGLE_H__ +#define __ICEINDEXEDTRIANGLE_H__ + + // An indexed triangle class. + class ICEMATHS_API IndexedTriangle + { + public: + //! Constructor + inline_ IndexedTriangle() {} + //! Constructor + inline_ IndexedTriangle(udword r0, udword r1, udword r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; } + //! Copy constructor + inline_ IndexedTriangle(const IndexedTriangle& triangle) + { + mVRef[0] = triangle.mVRef[0]; + mVRef[1] = triangle.mVRef[1]; + mVRef[2] = triangle.mVRef[2]; + } + //! Destructor + inline_ ~IndexedTriangle() {} + //! Vertex-references + udword mVRef[3]; + + // Methods + void Flip(); + float Area(const IcePoint* verts) const; + float Perimeter(const IcePoint* verts) const; + float Compacity(const IcePoint* verts) const; + void Normal(const IcePoint* verts, IcePoint& normal) const; + void DenormalizedNormal(const IcePoint* verts, IcePoint& normal) const; + void Center(const IcePoint* verts, IcePoint& center) const; + void CenteredNormal(const IcePoint* verts, IcePoint& normal) const; + void RandomPoint(const IcePoint* verts, IcePoint& random) const; + bool IsVisible(const IcePoint* verts, const IcePoint& source) const; + bool BackfaceCulling(const IcePoint* verts, const IcePoint& source) const; + float ComputeOcclusionPotential(const IcePoint* verts, const IcePoint& view) const; + bool ReplaceVertex(udword oldref, udword newref); + bool IsDegenerate() const; + bool HasVertex(udword ref) const; + bool HasVertex(udword ref, udword* index) const; + ubyte FindEdge(udword vref0, udword vref1) const; + udword OppositeVertex(udword vref0, udword vref1) const; + inline_ udword OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; } + void GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const; + float MinEdgeLength(const IcePoint* verts) const; + float MaxEdgeLength(const IcePoint* verts) const; + void ComputePoint(const IcePoint* verts, float u, float v, IcePoint& pt, udword* nearvtx=null) const; + float Angle(const IndexedTriangle& tri, const IcePoint* verts) const; + inline_ IcePlane PlaneEquation(const IcePoint* verts) const { return IcePlane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); } + bool Equal(const IndexedTriangle& tri) const; + }; + +#endif // __ICEINDEXEDTRIANGLE_H__ diff --git a/third-party/Opcode/Ice/IceLSS.h b/third-party/Opcode/Ice/IceLSS.h new file mode 100644 index 0000000..e4c9ef8 --- /dev/null +++ b/third-party/Opcode/Ice/IceLSS.h @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for line-swept spheres. + * \file IceLSS.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICELSS_H__ +#define __ICELSS_H__ + + class ICEMATHS_API LSS : public IceSegment + { + public: + //! Constructor + inline_ LSS() {} + //! Constructor + inline_ LSS(const IceSegment& seg, float radius) : IceSegment(seg), mRadius(radius) {} + //! Destructor + inline_ ~LSS() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes an OBB surrounding the LSS. + * \param box [out] the OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeOBB(OBB& box); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a IcePoint is contained within the LSS. + * \param pt [in] the IcePoint to test + * \return true if inside the LSS + * \warning IcePoint and LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const IcePoint& pt) const { return SquareDistance(pt) <= mRadius*mRadius; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a sphere is contained within the LSS. + * \param sphere [in] the sphere to test + * \return true if inside the LSS + * \warning sphere and LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const Sphere& sphere) + { + float d = mRadius - sphere.mRadius; + if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d; + else return false; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if an LSS is contained within the LSS. + * \param lss [in] the LSS to test + * \return true if inside the LSS + * \warning both LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const LSS& lss) + { + // We check the LSS contains the two spheres at the start and end of the sweep + return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius)); + } + + float mRadius; //!< Sphere radius + }; + +#endif // __ICELSS_H__ diff --git a/third-party/Opcode/Ice/IceMatrix3x3.cpp b/third-party/Opcode/Ice/IceMatrix3x3.cpp new file mode 100644 index 0000000..c856366 --- /dev/null +++ b/third-party/Opcode/Ice/IceMatrix3x3.cpp @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3x3 matrices. + * \file IceMatrix3x3.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 3x3 matrix. + * DirectX-compliant, ie row-column order, ie m[Row][Col]. + * Same as: + * m11 m12 m13 first row. + * m21 m22 m23 second row. + * m31 m32 m33 third row. + * Stored in memory as m11 m12 m13 m21... + * + * Multiplication rules: + * + * [x'y'z'] = [xyz][M] + * + * x' = x*m11 + y*m21 + z*m31 + * y' = x*m12 + y*m22 + z*m32 + * z' = x*m13 + y*m23 + z*m33 + * + * \class Matrix3x3 + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +// Cast operator +Matrix3x3::operator Matrix4x4() const +{ + return Matrix4x4( + m[0][0], m[0][1], m[0][2], 0.0f, + m[1][0], m[1][1], m[1][2], 0.0f, + m[2][0], m[2][1], m[2][2], 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); +} diff --git a/third-party/Opcode/Ice/IceMatrix3x3.h b/third-party/Opcode/Ice/IceMatrix3x3.h new file mode 100644 index 0000000..3356103 --- /dev/null +++ b/third-party/Opcode/Ice/IceMatrix3x3.h @@ -0,0 +1,496 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3x3 matrices. + * \file IceMatrix3x3.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMATRIX3X3_H__ +#define __ICEMATRIX3X3_H__ + + // Forward declarations + class Quat; + + #define MATRIX3X3_EPSILON (1.0e-7f) + + class ICEMATHS_API Matrix3x3 + { + public: + //! Empty constructor + inline_ Matrix3x3() {} + //! Constructor from 9 values + inline_ Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + } + //! Copy constructor + inline_ Matrix3x3(const Matrix3x3& mat) { CopyMemory(m, &mat.m, 9*sizeof(float)); } + //! Destructor + inline_ ~Matrix3x3() {} + + //! Assign values + inline_ void Set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + } + + //! Sets the scale from a Point. The point is put on the diagonal. + inline_ void SetScale(const IcePoint& p) { m[0][0] = p.x; m[1][1] = p.y; m[2][2] = p.z; } + + //! Sets the scale from floats. Values are put on the diagonal. + inline_ void SetScale(float sx, float sy, float sz) { m[0][0] = sx; m[1][1] = sy; m[2][2] = sz; } + + //! Scales from a Point. Each row is multiplied by a component. + inline_ void Scale(const IcePoint& p) + { + m[0][0] *= p.x; m[0][1] *= p.x; m[0][2] *= p.x; + m[1][0] *= p.y; m[1][1] *= p.y; m[1][2] *= p.y; + m[2][0] *= p.z; m[2][1] *= p.z; m[2][2] *= p.z; + } + + //! Scales from floats. Each row is multiplied by a value. + inline_ void Scale(float sx, float sy, float sz) + { + m[0][0] *= sx; m[0][1] *= sx; m[0][2] *= sx; + m[1][0] *= sy; m[1][1] *= sy; m[1][2] *= sy; + m[2][0] *= sz; m[2][1] *= sz; m[2][2] *= sz; + } + + //! Copy from a Matrix3x3 + inline_ void Copy(const Matrix3x3& source) { CopyMemory(m, source.m, 9*sizeof(float)); } + + // Row-column access + //! Returns a row. + inline_ void GetRow(const udword r, IcePoint& p) const { p.x = m[r][0]; p.y = m[r][1]; p.z = m[r][2]; } + //! Returns a row. + inline_ const IcePoint& GetRow(const udword r) const { return *(const IcePoint*)&m[r][0]; } + //! Returns a row. + inline_ IcePoint& GetRow(const udword r) { return *(IcePoint*)&m[r][0]; } + //! Sets a row. + inline_ void SetRow(const udword r, const IcePoint& p) { m[r][0] = p.x; m[r][1] = p.y; m[r][2] = p.z; } + //! Returns a column. + inline_ void GetCol(const udword c, IcePoint& p) const { p.x = m[0][c]; p.y = m[1][c]; p.z = m[2][c]; } + //! Sets a column. + inline_ void SetCol(const udword c, const IcePoint& p) { m[0][c] = p.x; m[1][c] = p.y; m[2][c] = p.z; } + + //! Computes the trace. The trace is the sum of the 3 diagonal components. + inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2]; } + //! Clears the matrix. + inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } + //! Sets the identity matrix. + inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = 1.0f; } + //! Checks for identity + inline_ bool IsIdentity() const + { + if(IR(m[0][0])!=IEEE_1_0) return false; + if(IR(m[0][1])!=0) return false; + if(IR(m[0][2])!=0) return false; + + if(IR(m[1][0])!=0) return false; + if(IR(m[1][1])!=IEEE_1_0) return false; + if(IR(m[1][2])!=0) return false; + + if(IR(m[2][0])!=0) return false; + if(IR(m[2][1])!=0) return false; + if(IR(m[2][2])!=IEEE_1_0) return false; + + return true; + } + + //! Checks matrix validity + inline_ BOOL IsValid() const + { + for(udword j=0;j<3;j++) + { + for(udword i=0;i<3;i++) + { + if(!IsValidFloat(m[j][i])) return FALSE; + } + } + return TRUE; + } + + //! Makes a skew-symmetric matrix (a.k.a. Star(*) Matrix) + //! [ 0.0 -a.z a.y ] + //! [ a.z 0.0 -a.x ] + //! [ -a.y a.x 0.0 ] + //! This is also called a "cross matrix" since for any vectors A and B, + //! A^B = Skew(A) * B = - B * Skew(A); + inline_ void SkewSymmetric(const IcePoint& a) + { + m[0][0] = 0.0f; + m[0][1] = -a.z; + m[0][2] = a.y; + + m[1][0] = a.z; + m[1][1] = 0.0f; + m[1][2] = -a.x; + + m[2][0] = -a.y; + m[2][1] = a.x; + m[2][2] = 0.0f; + } + + //! Negates the matrix + inline_ void Neg() + { + m[0][0] = -m[0][0]; m[0][1] = -m[0][1]; m[0][2] = -m[0][2]; + m[1][0] = -m[1][0]; m[1][1] = -m[1][1]; m[1][2] = -m[1][2]; + m[2][0] = -m[2][0]; m[2][1] = -m[2][1]; m[2][2] = -m[2][2]; + } + + //! Neg from another matrix + inline_ void Neg(const Matrix3x3& mat) + { + m[0][0] = -mat.m[0][0]; m[0][1] = -mat.m[0][1]; m[0][2] = -mat.m[0][2]; + m[1][0] = -mat.m[1][0]; m[1][1] = -mat.m[1][1]; m[1][2] = -mat.m[1][2]; + m[2][0] = -mat.m[2][0]; m[2][1] = -mat.m[2][1]; m[2][2] = -mat.m[2][2]; + } + + //! Add another matrix + inline_ void Add(const Matrix3x3& mat) + { + m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; + m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; + m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; + } + + //! Sub another matrix + inline_ void Sub(const Matrix3x3& mat) + { + m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; + m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; + m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; + } + //! Mac + inline_ void Mac(const Matrix3x3& a, const Matrix3x3& b, float s) + { + m[0][0] = a.m[0][0] + b.m[0][0] * s; + m[0][1] = a.m[0][1] + b.m[0][1] * s; + m[0][2] = a.m[0][2] + b.m[0][2] * s; + + m[1][0] = a.m[1][0] + b.m[1][0] * s; + m[1][1] = a.m[1][1] + b.m[1][1] * s; + m[1][2] = a.m[1][2] + b.m[1][2] * s; + + m[2][0] = a.m[2][0] + b.m[2][0] * s; + m[2][1] = a.m[2][1] + b.m[2][1] * s; + m[2][2] = a.m[2][2] + b.m[2][2] * s; + } + //! Mac + inline_ void Mac(const Matrix3x3& a, float s) + { + m[0][0] += a.m[0][0] * s; m[0][1] += a.m[0][1] * s; m[0][2] += a.m[0][2] * s; + m[1][0] += a.m[1][0] * s; m[1][1] += a.m[1][1] * s; m[1][2] += a.m[1][2] * s; + m[2][0] += a.m[2][0] * s; m[2][1] += a.m[2][1] * s; m[2][2] += a.m[2][2] * s; + } + + //! this = A * s + inline_ void Mult(const Matrix3x3& a, float s) + { + m[0][0] = a.m[0][0] * s; m[0][1] = a.m[0][1] * s; m[0][2] = a.m[0][2] * s; + m[1][0] = a.m[1][0] * s; m[1][1] = a.m[1][1] * s; m[1][2] = a.m[1][2] * s; + m[2][0] = a.m[2][0] * s; m[2][1] = a.m[2][1] * s; m[2][2] = a.m[2][2] * s; + } + + inline_ void Add(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] + b.m[0][0]; m[0][1] = a.m[0][1] + b.m[0][1]; m[0][2] = a.m[0][2] + b.m[0][2]; + m[1][0] = a.m[1][0] + b.m[1][0]; m[1][1] = a.m[1][1] + b.m[1][1]; m[1][2] = a.m[1][2] + b.m[1][2]; + m[2][0] = a.m[2][0] + b.m[2][0]; m[2][1] = a.m[2][1] + b.m[2][1]; m[2][2] = a.m[2][2] + b.m[2][2]; + } + + inline_ void Sub(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] - b.m[0][0]; m[0][1] = a.m[0][1] - b.m[0][1]; m[0][2] = a.m[0][2] - b.m[0][2]; + m[1][0] = a.m[1][0] - b.m[1][0]; m[1][1] = a.m[1][1] - b.m[1][1]; m[1][2] = a.m[1][2] - b.m[1][2]; + m[2][0] = a.m[2][0] - b.m[2][0]; m[2][1] = a.m[2][1] - b.m[2][1]; m[2][2] = a.m[2][2] - b.m[2][2]; + } + + //! this = a * b + inline_ void Mult(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[1][0] + a.m[0][2] * b.m[2][0]; + m[0][1] = a.m[0][0] * b.m[0][1] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[2][1]; + m[0][2] = a.m[0][0] * b.m[0][2] + a.m[0][1] * b.m[1][2] + a.m[0][2] * b.m[2][2]; + m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[1][2] * b.m[2][0]; + m[1][1] = a.m[1][0] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[2][1]; + m[1][2] = a.m[1][0] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[1][2] * b.m[2][2]; + m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[1][0] + a.m[2][2] * b.m[2][0]; + m[2][1] = a.m[2][0] * b.m[0][1] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[2][1]; + m[2][2] = a.m[2][0] * b.m[0][2] + a.m[2][1] * b.m[1][2] + a.m[2][2] * b.m[2][2]; + } + + //! this = transpose(a) * b + inline_ void MultAtB(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[1][0] * b.m[1][0] + a.m[2][0] * b.m[2][0]; + m[0][1] = a.m[0][0] * b.m[0][1] + a.m[1][0] * b.m[1][1] + a.m[2][0] * b.m[2][1]; + m[0][2] = a.m[0][0] * b.m[0][2] + a.m[1][0] * b.m[1][2] + a.m[2][0] * b.m[2][2]; + m[1][0] = a.m[0][1] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[2][1] * b.m[2][0]; + m[1][1] = a.m[0][1] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[2][1] * b.m[2][1]; + m[1][2] = a.m[0][1] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[2][1] * b.m[2][2]; + m[2][0] = a.m[0][2] * b.m[0][0] + a.m[1][2] * b.m[1][0] + a.m[2][2] * b.m[2][0]; + m[2][1] = a.m[0][2] * b.m[0][1] + a.m[1][2] * b.m[1][1] + a.m[2][2] * b.m[2][1]; + m[2][2] = a.m[0][2] * b.m[0][2] + a.m[1][2] * b.m[1][2] + a.m[2][2] * b.m[2][2]; + } + + //! this = a * transpose(b) + inline_ void MultABt(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[0][1] + a.m[0][2] * b.m[0][2]; + m[0][1] = a.m[0][0] * b.m[1][0] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[1][2]; + m[0][2] = a.m[0][0] * b.m[2][0] + a.m[0][1] * b.m[2][1] + a.m[0][2] * b.m[2][2]; + m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[0][1] + a.m[1][2] * b.m[0][2]; + m[1][1] = a.m[1][0] * b.m[1][0] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[1][2]; + m[1][2] = a.m[1][0] * b.m[2][0] + a.m[1][1] * b.m[2][1] + a.m[1][2] * b.m[2][2]; + m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[0][1] + a.m[2][2] * b.m[0][2]; + m[2][1] = a.m[2][0] * b.m[1][0] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[1][2]; + m[2][2] = a.m[2][0] * b.m[2][0] + a.m[2][1] * b.m[2][1] + a.m[2][2] * b.m[2][2]; + } + + //! Makes a rotation matrix mapping vector "from" to vector "to". + Matrix3x3& FromTo(const IcePoint& from, const IcePoint& to); + + //! Set a rotation matrix around the X axis. + //! 1 0 0 + //! RX = 0 cx sx + //! 0 -sx cx + void RotX(float angle); + //! Set a rotation matrix around the Y axis. + //! cy 0 -sy + //! RY = 0 1 0 + //! sy 0 cy + void RotY(float angle); + //! Set a rotation matrix around the Z axis. + //! cz sz 0 + //! RZ = -sz cz 0 + //! 0 0 1 + void RotZ(float angle); + //! cy sx.sy -sy.cx + //! RY.RX 0 cx sx + //! sy -sx.cy cx.cy + void RotYX(float y, float x); + + //! Make a rotation matrix about an arbitrary axis + Matrix3x3& Rot(float angle, const IcePoint& axis); + + //! Transpose the matrix. + void Transpose() + { + IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]); + IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]); + IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); + } + + //! this = Transpose(a) + void Transpose(const Matrix3x3& a) + { + m[0][0] = a.m[0][0]; m[0][1] = a.m[1][0]; m[0][2] = a.m[2][0]; + m[1][0] = a.m[0][1]; m[1][1] = a.m[1][1]; m[1][2] = a.m[2][1]; + m[2][0] = a.m[0][2]; m[2][1] = a.m[1][2]; m[2][2] = a.m[2][2]; + } + + //! Compute the determinant of the matrix. We use the rule of Sarrus. + float Determinant() const + { + return (m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1]) + - (m[2][0]*m[1][1]*m[0][2] + m[2][1]*m[1][2]*m[0][0] + m[2][2]*m[1][0]*m[0][1]); + } +/* + //! Compute a cofactor. Used for matrix inversion. + float CoFactor(ubyte row, ubyte column) const + { + static sdword gIndex[3+2] = { 0, 1, 2, 0, 1 }; + return (m[gIndex[row+1]][gIndex[column+1]]*m[gIndex[row+2]][gIndex[column+2]] - m[gIndex[row+2]][gIndex[column+1]]*m[gIndex[row+1]][gIndex[column+2]]); + } +*/ + //! Invert the matrix. Determinant must be different from zero, else matrix can't be inverted. + Matrix3x3& Invert() + { + float Det = Determinant(); // Must be !=0 + float OneOverDet = 1.0f / Det; + + Matrix3x3 Temp; + Temp.m[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDet; + Temp.m[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDet; + Temp.m[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDet; + Temp.m[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDet; + Temp.m[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDet; + Temp.m[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDet; + Temp.m[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDet; + Temp.m[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDet; + Temp.m[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDet; + + *this = Temp; + + return *this; + } + + Matrix3x3& Normalize(); + + //! this = exp(a) + Matrix3x3& Exp(const Matrix3x3& a); + +void FromQuat(const Quat &q); +void FromQuatL2(const Quat &q, float l2); + + // Arithmetic operators + //! Operator for Matrix3x3 Plus = Matrix3x3 + Matrix3x3; + inline_ Matrix3x3 operator+(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0] + mat.m[0][0], m[0][1] + mat.m[0][1], m[0][2] + mat.m[0][2], + m[1][0] + mat.m[1][0], m[1][1] + mat.m[1][1], m[1][2] + mat.m[1][2], + m[2][0] + mat.m[2][0], m[2][1] + mat.m[2][1], m[2][2] + mat.m[2][2]); + } + + //! Operator for Matrix3x3 Minus = Matrix3x3 - Matrix3x3; + inline_ Matrix3x3 operator-(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0] - mat.m[0][0], m[0][1] - mat.m[0][1], m[0][2] - mat.m[0][2], + m[1][0] - mat.m[1][0], m[1][1] - mat.m[1][1], m[1][2] - mat.m[1][2], + m[2][0] - mat.m[2][0], m[2][1] - mat.m[2][1], m[2][2] - mat.m[2][2]); + } + + //! Operator for Matrix3x3 Mul = Matrix3x3 * Matrix3x3; + inline_ Matrix3x3 operator*(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0], + m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1], + m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2], + + m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0], + m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1], + m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2], + + m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0], + m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1], + m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2]); + } + + //! Operator for Point Mul = Matrix3x3 * Point; + inline_ IcePoint operator*(const IcePoint& v) const { return IcePoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v); } + + //! Operator for Matrix3x3 Mul = Matrix3x3 * float; + inline_ Matrix3x3 operator*(float s) const + { + return Matrix3x3( + m[0][0]*s, m[0][1]*s, m[0][2]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s); + } + + //! Operator for Matrix3x3 Mul = float * Matrix3x3; + inline_ friend Matrix3x3 operator*(float s, const Matrix3x3& mat) + { + return Matrix3x3( + s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], + s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], + s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2]); + } + + //! Operator for Matrix3x3 Div = Matrix3x3 / float; + inline_ Matrix3x3 operator/(float s) const + { + if (s) s = 1.0f / s; + return Matrix3x3( + m[0][0]*s, m[0][1]*s, m[0][2]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s); + } + + //! Operator for Matrix3x3 Div = float / Matrix3x3; + inline_ friend Matrix3x3 operator/(float s, const Matrix3x3& mat) + { + return Matrix3x3( + s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], + s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], + s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2]); + } + + //! Operator for Matrix3x3 += Matrix3x3 + inline_ Matrix3x3& operator+=(const Matrix3x3& mat) + { + m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; + m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; + m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 -= Matrix3x3 + inline_ Matrix3x3& operator-=(const Matrix3x3& mat) + { + m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; + m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; + m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 *= Matrix3x3 + inline_ Matrix3x3& operator*=(const Matrix3x3& mat) + { + IcePoint TempRow; + + GetRow(0, TempRow); + m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + + GetRow(1, TempRow); + m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + + GetRow(2, TempRow); + m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 *= float + inline_ Matrix3x3& operator*=(float s) + { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; + return *this; + } + + //! Operator for Matrix3x3 /= float + inline_ Matrix3x3& operator/=(float s) + { + if (s) s = 1.0f / s; + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; + return *this; + } + + // Cast operators + //! Cast a Matrix3x3 to a Matrix4x4. + operator Matrix4x4() const; + //! Cast a Matrix3x3 to a Quat. + operator Quat() const; + + inline_ const IcePoint& operator[](int row) const { return *(const IcePoint*)&m[row][0]; } + inline_ IcePoint& operator[](int row) { return *(IcePoint*)&m[row][0]; } + + public: + + float m[3][3]; + }; + +#endif // __ICEMATRIX3X3_H__ + diff --git a/third-party/Opcode/Ice/IceMatrix4x4.cpp b/third-party/Opcode/Ice/IceMatrix4x4.cpp new file mode 100644 index 0000000..f9d8997 --- /dev/null +++ b/third-party/Opcode/Ice/IceMatrix4x4.cpp @@ -0,0 +1,135 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 4x4 matrices. + * \file IceMatrix4x4.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 4x4 matrix. + * DirectX-compliant, ie row-column order, ie m[Row][Col]. + * Same as: + * m11 m12 m13 m14 first row. + * m21 m22 m23 m24 second row. + * m31 m32 m33 m34 third row. + * m41 m42 m43 m44 fourth row. + * Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1). + * Stored in memory as m11 m12 m13 m14 m21... + * + * Multiplication rules: + * + * [x'y'z'1] = [xyz1][M] + * + * x' = x*m11 + y*m21 + z*m31 + m41 + * y' = x*m12 + y*m22 + z*m32 + m42 + * z' = x*m13 + y*m23 + z*m33 + m43 + * 1' = 0 + 0 + 0 + m44 + * + * \class Matrix4x4 + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Inverts a PR matrix. (which only contains a rotation and a translation) + * This is faster and less subject to FPU errors than the generic inversion code. + * + * \relates Matrix4x4 + * \fn InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src) + * \param dest [out] destination matrix + * \param src [in] source matrix + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src) +{ + dest.m[0][0] = src.m[0][0]; + dest.m[1][0] = src.m[0][1]; + dest.m[2][0] = src.m[0][2]; + dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]); + + dest.m[0][1] = src.m[1][0]; + dest.m[1][1] = src.m[1][1]; + dest.m[2][1] = src.m[1][2]; + dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]); + + dest.m[0][2] = src.m[2][0]; + dest.m[1][2] = src.m[2][1]; + dest.m[2][2] = src.m[2][2]; + dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]); + + dest.m[0][3] = 0.0f; + dest.m[1][3] = 0.0f; + dest.m[2][3] = 0.0f; + dest.m[3][3] = 1.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the cofactor of the Matrix at a specified location +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Matrix4x4::CoFactor(udword row, udword col) const +{ + return (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] + + m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] + + m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3]) + - (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] + + m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] + + m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the determinant of the Matrix +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Matrix4x4::Determinant() const +{ + return m[0][0] * CoFactor(0, 0) + + m[0][1] * CoFactor(0, 1) + + m[0][2] * CoFactor(0, 2) + + m[0][3] * CoFactor(0, 3); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the inverse of the matrix +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Matrix4x4& Matrix4x4::Invert() +{ + float Det = Determinant(); + Matrix4x4 Temp; + + if(fabsf(Det) < MATRIX4X4_EPSILON) + return *this; // The matrix is not invertible! Singular case! + + float IDet = 1.0f / Det; + + Temp.m[0][0] = CoFactor(0,0) * IDet; + Temp.m[1][0] = CoFactor(0,1) * IDet; + Temp.m[2][0] = CoFactor(0,2) * IDet; + Temp.m[3][0] = CoFactor(0,3) * IDet; + Temp.m[0][1] = CoFactor(1,0) * IDet; + Temp.m[1][1] = CoFactor(1,1) * IDet; + Temp.m[2][1] = CoFactor(1,2) * IDet; + Temp.m[3][1] = CoFactor(1,3) * IDet; + Temp.m[0][2] = CoFactor(2,0) * IDet; + Temp.m[1][2] = CoFactor(2,1) * IDet; + Temp.m[2][2] = CoFactor(2,2) * IDet; + Temp.m[3][2] = CoFactor(2,3) * IDet; + Temp.m[0][3] = CoFactor(3,0) * IDet; + Temp.m[1][3] = CoFactor(3,1) * IDet; + Temp.m[2][3] = CoFactor(3,2) * IDet; + Temp.m[3][3] = CoFactor(3,3) * IDet; + + *this = Temp; + + return *this; +} + diff --git a/third-party/Opcode/Ice/IceMatrix4x4.h b/third-party/Opcode/Ice/IceMatrix4x4.h new file mode 100644 index 0000000..82ebc05 --- /dev/null +++ b/third-party/Opcode/Ice/IceMatrix4x4.h @@ -0,0 +1,455 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 4x4 matrices. + * \file IceMatrix4x4.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMATRIX4X4_H__ +#define __ICEMATRIX4X4_H__ + + // Forward declarations + class PRS; + class PR; + + #define MATRIX4X4_EPSILON (1.0e-7f) + + class ICEMATHS_API Matrix4x4 + { +// void LUBackwardSubstitution( sdword *indx, float* b ); +// void LUDecomposition( sdword* indx, float* d ); + + public: + //! Empty constructor. + inline_ Matrix4x4() {} + //! Constructor from 16 values + inline_ Matrix4x4( float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; + m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; + } + //! Copy constructor + inline_ Matrix4x4(const Matrix4x4& mat) { CopyMemory(m, &mat.m, 16*sizeof(float)); } + //! Destructor. + inline_ ~Matrix4x4() {} + + //! Assign values (rotation only) + inline_ Matrix4x4& Set( float m00, float m01, float m02, + float m10, float m11, float m12, + float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + return *this; + } + //! Assign values + inline_ Matrix4x4& Set( float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; + m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; + return *this; + } + + //! Copy from a Matrix4x4 + inline_ void Copy(const Matrix4x4& source) { CopyMemory(m, source.m, 16*sizeof(float)); } + + // Row-column access + //! Returns a row. + inline_ void GetRow(const udword r, HPoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; p.w=m[r][3]; } + //! Returns a row. + inline_ void GetRow(const udword r, IcePoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; } + //! Returns a row. + inline_ const HPoint& GetRow(const udword r) const { return *(const HPoint*)&m[r][0]; } + //! Returns a row. + inline_ HPoint& GetRow(const udword r) { return *(HPoint*)&m[r][0]; } + //! Sets a row. + inline_ void SetRow(const udword r, const HPoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]=p.w; } + //! Sets a row. + inline_ void SetRow(const udword r, const IcePoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]= (r!=3) ? 0.0f : 1.0f; } + //! Returns a column. + inline_ void GetCol(const udword c, HPoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; p.w=m[3][c]; } + //! Returns a column. + inline_ void GetCol(const udword c, IcePoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; } + //! Sets a column. + inline_ void SetCol(const udword c, const HPoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]=p.w; } + //! Sets a column. + inline_ void SetCol(const udword c, const IcePoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]= (c!=3) ? 0.0f : 1.0f; } + + // Translation + //! Returns the translation part of the matrix. + inline_ const HPoint& GetTrans() const { return GetRow(3); } + //! Gets the translation part of the matrix + inline_ void GetTrans(IcePoint& p) const { p.x=m[3][0]; p.y=m[3][1]; p.z=m[3][2]; } + //! Sets the translation part of the matrix, from a Point. + inline_ void SetTrans(const IcePoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; } + //! Sets the translation part of the matrix, from a HPoint. + inline_ void SetTrans(const HPoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; m[3][3]=p.w; } + //! Sets the translation part of the matrix, from floats. + inline_ void SetTrans(float tx, float ty, float tz) { m[3][0]=tx; m[3][1]=ty; m[3][2]=tz; } + + // Scale + //! Sets the scale from a Point. The point is put on the diagonal. + inline_ void SetScale(const IcePoint& p) { m[0][0]=p.x; m[1][1]=p.y; m[2][2]=p.z; } + //! Sets the scale from floats. Values are put on the diagonal. + inline_ void SetScale(float sx, float sy, float sz) { m[0][0]=sx; m[1][1]=sy; m[2][2]=sz; } + //! Scales from a Point. Each row is multiplied by a component. + void Scale(const IcePoint& p) + { + m[0][0] *= p.x; m[1][0] *= p.y; m[2][0] *= p.z; + m[0][1] *= p.x; m[1][1] *= p.y; m[2][1] *= p.z; + m[0][2] *= p.x; m[1][2] *= p.y; m[2][2] *= p.z; + } + //! Scales from floats. Each row is multiplied by a value. + void Scale(float sx, float sy, float sz) + { + m[0][0] *= sx; m[1][0] *= sy; m[2][0] *= sz; + m[0][1] *= sx; m[1][1] *= sy; m[2][1] *= sz; + m[0][2] *= sx; m[1][2] *= sy; m[2][2] *= sz; + } +/* + //! Returns a row. + inline_ HPoint GetRow(const udword row) const { return mRow[row]; } + //! Sets a row. + inline_ Matrix4x4& SetRow(const udword row, const HPoint& p) { mRow[row] = p; return *this; } + //! Sets a row. + Matrix4x4& SetRow(const udword row, const Point& p) + { + m[row][0] = p.x; + m[row][1] = p.y; + m[row][2] = p.z; + m[row][3] = (row != 3) ? 0.0f : 1.0f; + return *this; + } + //! Returns a column. + HPoint GetCol(const udword col) const + { + HPoint Res; + Res.x = m[0][col]; + Res.y = m[1][col]; + Res.z = m[2][col]; + Res.w = m[3][col]; + return Res; + } + //! Sets a column. + Matrix4x4& SetCol(const udword col, const HPoint& p) + { + m[0][col] = p.x; + m[1][col] = p.y; + m[2][col] = p.z; + m[3][col] = p.w; + return *this; + } + //! Sets a column. + Matrix4x4& SetCol(const udword col, const Point& p) + { + m[0][col] = p.x; + m[1][col] = p.y; + m[2][col] = p.z; + m[3][col] = (col != 3) ? 0.0f : 1.0f; + return *this; + } +*/ + //! Computes the trace. The trace is the sum of the 4 diagonal components. + inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2] + m[3][3]; } + //! Computes the trace of the upper 3x3 matrix. + inline_ float Trace3x3() const { return m[0][0] + m[1][1] + m[2][2]; } + //! Clears the matrix. + inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } + //! Sets the identity matrix. + inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; } + //! Checks for identity + inline_ bool IsIdentity() const + { + if(IR(m[0][0])!=IEEE_1_0) return false; + if(IR(m[0][1])!=0) return false; + if(IR(m[0][2])!=0) return false; + if(IR(m[0][3])!=0) return false; + + if(IR(m[1][0])!=0) return false; + if(IR(m[1][1])!=IEEE_1_0) return false; + if(IR(m[1][2])!=0) return false; + if(IR(m[1][3])!=0) return false; + + if(IR(m[2][0])!=0) return false; + if(IR(m[2][1])!=0) return false; + if(IR(m[2][2])!=IEEE_1_0) return false; + if(IR(m[2][3])!=0) return false; + + if(IR(m[3][0])!=0) return false; + if(IR(m[3][1])!=0) return false; + if(IR(m[3][2])!=0) return false; + if(IR(m[3][3])!=IEEE_1_0) return false; + return true; + } + + //! Checks matrix validity + inline_ BOOL IsValid() const + { + for(udword j=0;j<4;j++) + { + for(udword i=0;i<4;i++) + { + if(!IsValidFloat(m[j][i])) return FALSE; + } + } + return TRUE; + } + + //! Sets a rotation matrix around the X axis. + void RotX(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin; m[1][2] = Sin; } + //! Sets a rotation matrix around the Y axis. + void RotY(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin; m[0][2] = -Sin; } + //! Sets a rotation matrix around the Z axis. + void RotZ(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin; m[0][1] = Sin; } + + //! Makes a rotation matrix about an arbitrary axis + Matrix4x4& Rot(float angle, IcePoint& p1, IcePoint& p2); + + //! Transposes the matrix. + void Transpose() + { + IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]); + IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]); + IR(m[3][0]) ^= IR(m[0][3]); IR(m[0][3]) ^= IR(m[3][0]); IR(m[3][0]) ^= IR(m[0][3]); + IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); + IR(m[1][3]) ^= IR(m[3][1]); IR(m[3][1]) ^= IR(m[1][3]); IR(m[1][3]) ^= IR(m[3][1]); + IR(m[2][3]) ^= IR(m[3][2]); IR(m[3][2]) ^= IR(m[2][3]); IR(m[2][3]) ^= IR(m[3][2]); + } + + //! Computes a cofactor. Used for matrix inversion. + float CoFactor(udword row, udword col) const; + //! Computes the determinant of the matrix. + float Determinant() const; + //! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted. + Matrix4x4& Invert(); +// Matrix& ComputeAxisMatrix(Point& axis, float angle); + + // Cast operators + //! Casts a Matrix4x4 to a Matrix3x3. + inline_ operator Matrix3x3() const + { + return Matrix3x3( + m[0][0], m[0][1], m[0][2], + m[1][0], m[1][1], m[1][2], + m[2][0], m[2][1], m[2][2]); + } + //! Casts a Matrix4x4 to a Quat. + operator Quat() const; + //! Casts a Matrix4x4 to a PR. + operator PR() const; + + // Arithmetic operators + //! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4; + inline_ Matrix4x4 operator+(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3], + m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3], + m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3], + m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]); + } + + //! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4; + inline_ Matrix4x4 operator-(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3], + m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3], + m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3], + m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]); + } + + //! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4; + inline_ Matrix4x4 operator*(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0], + m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1], + m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2], + m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3], + + m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0], + m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1], + m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2], + m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3], + + m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0], + m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1], + m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2], + m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3], + + m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0], + m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1], + m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2], + m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]); + } + + //! Operator for HPoint Mul = Matrix4x4 * HPoint; + inline_ HPoint operator*(const HPoint& v) const { return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); } + + //! Operator for Point Mul = Matrix4x4 * Point; + inline_ IcePoint operator*(const IcePoint& v) const + { + return IcePoint( m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3], + m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3], + m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3] ); + } + + //! Operator for Matrix4x4 Scale = Matrix4x4 * float; + inline_ Matrix4x4 operator*(float s) const + { + return Matrix4x4( + m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, + m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); + } + + //! Operator for Matrix4x4 Scale = float * Matrix4x4; + inline_ friend Matrix4x4 operator*(float s, const Matrix4x4& mat) + { + return Matrix4x4( + s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[0][3], + s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[1][3], + s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2], s*mat.m[2][3], + s*mat.m[3][0], s*mat.m[3][1], s*mat.m[3][2], s*mat.m[3][3]); + } + + //! Operator for Matrix4x4 Div = Matrix4x4 / float; + inline_ Matrix4x4 operator/(float s) const + { + if(s) s = 1.0f / s; + + return Matrix4x4( + m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, + m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); + } + + //! Operator for Matrix4x4 Div = float / Matrix4x4; + inline_ friend Matrix4x4 operator/(float s, const Matrix4x4& mat) + { + return Matrix4x4( + s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[0][3], + s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[1][3], + s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2], s/mat.m[2][3], + s/mat.m[3][0], s/mat.m[3][1], s/mat.m[3][2], s/mat.m[3][3]); + } + + //! Operator for Matrix4x4 += Matrix4x4; + inline_ Matrix4x4& operator+=(const Matrix4x4& mat) + { + m[0][0]+=mat.m[0][0]; m[0][1]+=mat.m[0][1]; m[0][2]+=mat.m[0][2]; m[0][3]+=mat.m[0][3]; + m[1][0]+=mat.m[1][0]; m[1][1]+=mat.m[1][1]; m[1][2]+=mat.m[1][2]; m[1][3]+=mat.m[1][3]; + m[2][0]+=mat.m[2][0]; m[2][1]+=mat.m[2][1]; m[2][2]+=mat.m[2][2]; m[2][3]+=mat.m[2][3]; + m[3][0]+=mat.m[3][0]; m[3][1]+=mat.m[3][1]; m[3][2]+=mat.m[3][2]; m[3][3]+=mat.m[3][3]; + return *this; + } + + //! Operator for Matrix4x4 -= Matrix4x4; + inline_ Matrix4x4& operator-=(const Matrix4x4& mat) + { + m[0][0]-=mat.m[0][0]; m[0][1]-=mat.m[0][1]; m[0][2]-=mat.m[0][2]; m[0][3]-=mat.m[0][3]; + m[1][0]-=mat.m[1][0]; m[1][1]-=mat.m[1][1]; m[1][2]-=mat.m[1][2]; m[1][3]-=mat.m[1][3]; + m[2][0]-=mat.m[2][0]; m[2][1]-=mat.m[2][1]; m[2][2]-=mat.m[2][2]; m[2][3]-=mat.m[2][3]; + m[3][0]-=mat.m[3][0]; m[3][1]-=mat.m[3][1]; m[3][2]-=mat.m[3][2]; m[3][3]-=mat.m[3][3]; + return *this; + } + + //! Operator for Matrix4x4 *= Matrix4x4; + Matrix4x4& operator*=(const Matrix4x4& mat) + { + HPoint TempRow; + + GetRow(0, TempRow); + m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(1, TempRow); + m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(2, TempRow); + m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(3, TempRow); + m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + return *this; + } + + //! Operator for Matrix4x4 *= float; + inline_ Matrix4x4& operator*=(float s) + { + m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; + m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; + m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; + m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; + return *this; + } + + //! Operator for Matrix4x4 /= float; + inline_ Matrix4x4& operator/=(float s) + { + if(s) s = 1.0f / s; + m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; + m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; + m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; + m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; + return *this; + } + + inline_ const HPoint& operator[](int row) const { return *(const HPoint*)&m[row][0]; } + inline_ HPoint& operator[](int row) { return *(HPoint*)&m[row][0]; } + + public: + + float m[4][4]; + }; + + //! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix + inline_ void TransformPoint4x3(IcePoint& dest, const IcePoint& source, const Matrix4x4& rot) + { + dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; + dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; + dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; + } + + //! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix + inline_ void TransformPoint3x3(IcePoint& dest, const IcePoint& source, const Matrix4x4& rot) + { + dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; + dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; + dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; + } + + ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src); + +#endif // __ICEMATRIX4X4_H__ + diff --git a/third-party/Opcode/Ice/IceMemoryMacros.h b/third-party/Opcode/Ice/IceMemoryMacros.h new file mode 100644 index 0000000..0987e11 --- /dev/null +++ b/third-party/Opcode/Ice/IceMemoryMacros.h @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains all memory macros. + * \file IceMemoryMacros.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMEMORYMACROS_H__ +#define __ICEMEMORYMACROS_H__ + +#undef ZeroMemory +#undef CopyMemory +#undef MoveMemory +#undef FillMemory + + //! Clears a buffer. + //! \param addr [in] buffer address + //! \param size [in] buffer length + //! \see FillMemory + //! \see StoreDwords + //! \see CopyMemory + //! \see MoveMemory + inline_ void ZeroMemory(void* addr, udword size) { memset(addr, 0, size); } + + //! Fills a buffer with a given byte. + //! \param addr [in] buffer address + //! \param size [in] buffer length + //! \param val [in] the byte value + //! \see StoreDwords + //! \see ZeroMemory + //! \see CopyMemory + //! \see MoveMemory + inline_ void FillMemory(void* dest, udword size, ubyte val) { memset(dest, val, size); } + + //! Fills a buffer with a given dword. + //! \param addr [in] buffer address + //! \param nb [in] number of dwords to write + //! \param value [in] the dword value + //! \see FillMemory + //! \see ZeroMemory + //! \see CopyMemory + //! \see MoveMemory + //! \warning writes nb*4 bytes ! + inline_ void StoreDwords(udword* dest, udword nb, udword value) + { + while (nb--) *dest++ = value; + } + + //! Copies a buffer. + //! \param addr [in] destination buffer address + //! \param addr [in] source buffer address + //! \param size [in] buffer length + //! \see ZeroMemory + //! \see FillMemory + //! \see StoreDwords + //! \see MoveMemory + inline_ void CopyMemory(void* dest, const void* src, udword size) { memcpy(dest, src, size); } + + //! Moves a buffer. + //! \param addr [in] destination buffer address + //! \param addr [in] source buffer address + //! \param size [in] buffer length + //! \see ZeroMemory + //! \see FillMemory + //! \see StoreDwords + //! \see CopyMemory + inline_ void MoveMemory(void* dest, const void* src, udword size) { memmove(dest, src, size); } + + #define SIZEOFOBJECT sizeof(*this) //!< Gives the size of current object. Avoid some mistakes (e.g. "sizeof(this)"). + //#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); } //!< Clears current object. Laziness is my business. HANDLE WITH CARE. + #define DELETESINGLE(x) if (x) { delete x; x = null; } //!< Deletes an instance of a class. + #define DELETEARRAY(x) if (x) { delete []x; x = null; } //!< Deletes an array. + #define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; } //!< Safe D3D-style release + #define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release + +#ifdef __ICEERROR_H__ + #define CHECKALLOC(x) if(!x) return SetIceError;; // ("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE. +#else + #define CHECKALLOC(x) if(!x) return false; +#endif + + //! Standard allocation cycle + #define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr); + +#endif // __ICEMEMORYMACROS_H__ diff --git a/third-party/Opcode/Ice/IceOBB.cpp b/third-party/Opcode/Ice/IceOBB.cpp new file mode 100644 index 0000000..ac9dbf7 --- /dev/null +++ b/third-party/Opcode/Ice/IceOBB.cpp @@ -0,0 +1,323 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains OBB-related code. + * \file IceOBB.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * An Oriented Bounding Box (OBB). + * \class OBB + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Tests if a point is contained within the OBB. + * \param p [in] the world point to test + * \return true if inside the OBB + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ContainsPoint(const IcePoint& p) const +{ + // IcePoint in OBB test using lazy evaluation and early exits + + // Translate to box space + IcePoint RelPoint = p - mCenter; + + // IcePoint * mRot maps from box space to world space + // mRot * IcePoint maps from world space to box space (what we need here) + + float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z; + if(f >= mExtents.x || f <= -mExtents.x) return false; + + f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z; + if(f >= mExtents.y || f <= -mExtents.y) return false; + + f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z; + if(f >= mExtents.z || f <= -mExtents.z) return false; + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds an OBB from an AABB and a world transform. + * \param aabb [in] the aabb + * \param mat [in] the world transform + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::Create(const AABB& aabb, const Matrix4x4& mat) +{ + // Note: must be coherent with Rotate() + + aabb.GetCenter(mCenter); + aabb.GetExtents(mExtents); + // Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity). + + // So following what's done in Rotate: + // - x-form the center + mCenter *= mat; + // - combine rotation with identity, i.e. just use given matrix + mRot = mat; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the obb planes. + * \param planes [out] 6 box planes + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputePlanes(IcePlane* planes) const +{ + // Checkings + if(!planes) return false; + + IcePoint Axis0 = mRot[0]; + IcePoint Axis1 = mRot[1]; + IcePoint Axis2 = mRot[2]; + + // Writes normals + planes[0].n = Axis0; + planes[1].n = -Axis0; + planes[2].n = Axis1; + planes[3].n = -Axis1; + planes[4].n = Axis2; + planes[5].n = -Axis2; + + // Compute a point on each plane + IcePoint p0 = mCenter + Axis0 * mExtents.x; + IcePoint p1 = mCenter - Axis0 * mExtents.x; + IcePoint p2 = mCenter + Axis1 * mExtents.y; + IcePoint p3 = mCenter - Axis1 * mExtents.y; + IcePoint p4 = mCenter + Axis2 * mExtents.z; + IcePoint p5 = mCenter - Axis2 * mExtents.z; + + // Compute d + planes[0].d = -(planes[0].n|p0); + planes[1].d = -(planes[1].n|p1); + planes[2].d = -(planes[2].n|p2); + planes[3].d = -(planes[3].n|p3); + planes[4].d = -(planes[4].n|p4); + planes[5].d = -(planes[5].n|p5); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the obb points. + * \param pts [out] 8 box points + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputePoints(IcePoint* pts) const +{ + // Checkings + if(!pts) return false; + + IcePoint Axis0 = mRot[0]; + IcePoint Axis1 = mRot[1]; + IcePoint Axis2 = mRot[2]; + + Axis0 *= mExtents.x; + Axis1 *= mExtents.y; + Axis2 *= mExtents.z; + + // 7+------+6 0 = --- + // /| /| 1 = +-- + // / | / | 2 = ++- + // / 4+---/--+5 3 = -+- + // 3+------+2 / y z 4 = --+ + // | / | / | / 5 = +-+ + // |/ |/ |/ 6 = +++ + // 0+------+1 *---x 7 = -++ + + pts[0] = mCenter - Axis0 - Axis1 - Axis2; + pts[1] = mCenter + Axis0 - Axis1 - Axis2; + pts[2] = mCenter + Axis0 + Axis1 - Axis2; + pts[3] = mCenter - Axis0 + Axis1 - Axis2; + pts[4] = mCenter - Axis0 - Axis1 + Axis2; + pts[5] = mCenter + Axis0 - Axis1 + Axis2; + pts[6] = mCenter + Axis0 + Axis1 + Axis2; + pts[7] = mCenter - Axis0 + Axis1 + Axis2; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes vertex normals. + * \param pts [out] 8 box points + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputeVertexNormals(IcePoint* pts) const +{ + static float VertexNormals[] = + { + -INVSQRT3, -INVSQRT3, -INVSQRT3, + INVSQRT3, -INVSQRT3, -INVSQRT3, + INVSQRT3, INVSQRT3, -INVSQRT3, + -INVSQRT3, INVSQRT3, -INVSQRT3, + -INVSQRT3, -INVSQRT3, INVSQRT3, + INVSQRT3, -INVSQRT3, INVSQRT3, + INVSQRT3, INVSQRT3, INVSQRT3, + -INVSQRT3, INVSQRT3, INVSQRT3 + }; + + if(!pts) return false; + + const IcePoint* VN = (const IcePoint*)VertexNormals; + for(udword i=0;i<8;i++) + { + pts[i] = VN[i] * mRot; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns edges. + * \return 24 indices (12 edges) indexing the list returned by ComputePoints() + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const udword* OBB::GetEdges() const +{ + static udword Indices[] = { + 0, 1, 1, 2, 2, 3, 3, 0, + 7, 6, 6, 5, 5, 4, 4, 7, + 1, 5, 6, 2, + 3, 7, 4, 0 + }; + return Indices; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns local edge normals. + * \return edge normals in local space + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const IcePoint* OBB::GetLocalEdgeNormals() const +{ + static float EdgeNormals[] = + { + 0, -INVSQRT2, -INVSQRT2, // 0-1 + INVSQRT2, 0, -INVSQRT2, // 1-2 + 0, INVSQRT2, -INVSQRT2, // 2-3 + -INVSQRT2, 0, -INVSQRT2, // 3-0 + + 0, INVSQRT2, INVSQRT2, // 7-6 + INVSQRT2, 0, INVSQRT2, // 6-5 + 0, -INVSQRT2, INVSQRT2, // 5-4 + -INVSQRT2, 0, INVSQRT2, // 4-7 + + INVSQRT2, -INVSQRT2, 0, // 1-5 + INVSQRT2, INVSQRT2, 0, // 6-2 + -INVSQRT2, INVSQRT2, 0, // 3-7 + -INVSQRT2, -INVSQRT2, 0 // 4-0 + }; + return (const IcePoint*)EdgeNormals; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns world edge normal + * \param edge_index [in] 0 <= edge index < 12 + * \param world_normal [out] edge normal in world space + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::ComputeWorldEdgeNormal(udword edge_index, IcePoint& world_normal) const +{ + ASSERT(edge_index<12); + world_normal = GetLocalEdgeNormals()[edge_index] * mRot; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes an LSS surrounding the OBB. + * \param lss [out] the LSS + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::ComputeLSS(LSS& lss) const +{ + IcePoint Axis0 = mRot[0]; + IcePoint Axis1 = mRot[1]; + IcePoint Axis2 = mRot[2]; + + switch(mExtents.LargestAxis()) + { + case 0: + lss.mRadius = (mExtents.y + mExtents.z)*0.5f; + lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius); + lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius); + break; + case 1: + lss.mRadius = (mExtents.x + mExtents.z)*0.5f; + lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius); + lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius); + break; + case 2: + lss.mRadius = (mExtents.x + mExtents.y)*0.5f; + lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius); + lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius); + break; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the OBB is inside another OBB. + * \param box [in] the other OBB + * \return TRUE if we're inside the other box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL OBB::IsInside(const OBB& box) const +{ + // Make a 4x4 from the box & inverse it + Matrix4x4 M0Inv; + { + Matrix4x4 M0 = box.mRot; + M0.SetTrans(box.mCenter); + InvertPRMatrix(M0Inv, M0); + } + + // With our inversed 4x4, create box1 in space of box0 + OBB _1in0; + Rotate(M0Inv, _1in0); + + // This should cancel out box0's rotation, i.e. it's now an AABB. + // => Center(0,0,0), Rot(identity) + + // The two boxes are in the same space so now we can compare them. + + // Create the AABB of (box1 in space of box0) + const Matrix3x3& mtx = _1in0.mRot; + + float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x; + if(f > _1in0.mCenter.x) return FALSE; + if(-f < _1in0.mCenter.x) return FALSE; + + f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y; + if(f > _1in0.mCenter.y) return FALSE; + if(-f < _1in0.mCenter.y) return FALSE; + + f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z; + if(f > _1in0.mCenter.z) return FALSE; + if(-f < _1in0.mCenter.z) return FALSE; + + return TRUE; +} diff --git a/third-party/Opcode/Ice/IceOBB.h b/third-party/Opcode/Ice/IceOBB.h new file mode 100644 index 0000000..c55c2d5 --- /dev/null +++ b/third-party/Opcode/Ice/IceOBB.h @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains OBB-related code. (oriented bounding box) + * \file IceOBB.h + * \author Pierre Terdiman + * \date January, 13, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEOBB_H__ +#define __ICEOBB_H__ + + // Forward declarations + class LSS; + + class ICEMATHS_API OBB + { + public: + //! Constructor + inline_ OBB() {} + //! Constructor + inline_ OBB(const IcePoint& center, const IcePoint& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot) {} + //! Destructor + inline_ ~OBB() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty OBB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() + { + mCenter.Zero(); + mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); + mRot.Identity(); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a IcePoint is contained within the OBB. + * \param p [in] the world IcePoint to test + * \return true if inside the OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ContainsPoint(const IcePoint& p) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds an OBB from an AABB and a world transform. + * \param aabb [in] the aabb + * \param mat [in] the world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Create(const AABB& aabb, const Matrix4x4& mat); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the OBB after an arbitrary transform by a 4x4 matrix. + * \param mtx [in] the transform matrix + * \param obb [out] the transformed OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, OBB& obb) const + { + // The extents remain constant + obb.mExtents = mExtents; + // The center gets x-formed + obb.mCenter = mCenter * mtx; + // Combine rotations + obb.mRot = mRot * Matrix3x3(mtx); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the OBB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Center, Extents) boxes: Extents >= 0.0f + if(mExtents.x < 0.0f) return FALSE; + if(mExtents.y < 0.0f) return FALSE; + if(mExtents.z < 0.0f) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the obb planes. + * \param planes [out] 6 box planes + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputePlanes(IcePlane* planes) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the obb points. + * \param pts [out] 8 box points + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputePoints(IcePoint* pts) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes vertex normals. + * \param pts [out] 8 box points + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputeVertexNormals(IcePoint* pts) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns edges. + * \return 24 indices (12 edges) indexing the list returned by ComputePoints() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const udword* GetEdges() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns local edge normals. + * \return edge normals in local space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const IcePoint* GetLocalEdgeNormals() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns world edge normal + * \param edge_index [in] 0 <= edge index < 12 + * \param world_normal [out] edge normal in world space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeWorldEdgeNormal(udword edge_index, IcePoint& world_normal) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes an LSS surrounding the OBB. + * \param lss [out] the LSS + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeLSS(LSS& lss) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the OBB is inside another OBB. + * \param box [in] the other OBB + * \return TRUE if we're inside the other box + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + BOOL IsInside(const OBB& box) const; + + inline_ const IcePoint& GetCenter() const { return mCenter; } + inline_ const IcePoint& GetExtents() const { return mExtents; } + inline_ const Matrix3x3& GetRot() const { return mRot; } + + inline_ void GetRotatedExtents(Matrix3x3& extents) const + { + extents = mRot; + extents.Scale(mExtents); + } + + IcePoint mCenter; //!< B for Box + IcePoint mExtents; //!< B for Bounding + Matrix3x3 mRot; //!< O for Oriented + + // Orientation is stored in row-major format, + // i.e. rows = eigen vectors of the covariance matrix + }; + +#endif // __ICEOBB_H__ diff --git a/third-party/Opcode/Ice/IcePairs.h b/third-party/Opcode/Ice/IcePairs.h new file mode 100644 index 0000000..2c09b92 --- /dev/null +++ b/third-party/Opcode/Ice/IcePairs.h @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a simple pair class. + * \file IcePairs.h + * \author Pierre Terdiman + * \date January, 13, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPAIRS_H__ +#define __ICEPAIRS_H__ + + //! A generic couple structure + struct ICECORE_API Pair + { + inline_ Pair() {} + inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {} + + udword id0; //!< First index of the pair + udword id1; //!< Second index of the pair + }; + + class ICECORE_API Pairs : private Container + { + public: + // Constructor / Destructor + Pairs() {} + ~Pairs() {} + + inline_ udword GetNbPairs() const { return GetNbEntries()>>1; } + inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); } + inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; } + + inline_ BOOL HasPairs() const { return IsNotEmpty(); } + + inline_ void ResetPairs() { Reset(); } + inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); } + + inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); } + inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); } + }; + +#endif // __ICEPAIRS_H__ diff --git a/third-party/Opcode/Ice/IcePlane.cpp b/third-party/Opcode/Ice/IcePlane.cpp new file mode 100644 index 0000000..f198843 --- /dev/null +++ b/third-party/Opcode/Ice/IcePlane.cpp @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for planes. + * \file IcePlane.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * IcePlane class. + * \class IcePlane + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the plane equation from 3 points. + * \param p0 [in] first IcePoint + * \param p1 [in] second IcePoint + * \param p2 [in] third IcePoint + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +IcePlane& IcePlane::Set(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) +{ + IcePoint Edge0 = p1 - p0; + IcePoint Edge1 = p2 - p0; + + n = Edge0 ^ Edge1; + n.Normalize(); + + d = -(p0 | n); + + return *this; +} diff --git a/third-party/Opcode/Ice/IcePlane.h b/third-party/Opcode/Ice/IcePlane.h new file mode 100644 index 0000000..5c93b90 --- /dev/null +++ b/third-party/Opcode/Ice/IcePlane.h @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for planes. + * \file IcePlane.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPLANE_H__ +#define __ICEPLANE_H__ + + #define PLANE_EPSILON (1.0e-7f) + + class ICEMATHS_API IcePlane + { + public: + //! Constructor + inline_ IcePlane() { } + //! Constructor from a normal and a distance + inline_ IcePlane(float nx, float ny, float nz, float d) { Set(nx, ny, nz, d); } + //! Constructor from a point on the plane and a normal + inline_ IcePlane(const IcePoint& p, const IcePoint& n) { Set(p, n); } + //! Constructor from three points + inline_ IcePlane(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) { Set(p0, p1, p2); } + //! Constructor from a normal and a distance + inline_ IcePlane(const IcePoint& _n, float _d) { n = _n; d = _d; } + //! Copy constructor + inline_ IcePlane(const IcePlane& plane) : n(plane.n), d(plane.d) { } + //! Destructor + inline_ ~IcePlane() { } + + inline_ IcePlane& Zero() { n.Zero(); d = 0.0f; return *this; } + inline_ IcePlane& Set(float nx, float ny, float nz, float _d) { n.Set(nx, ny, nz); d = _d; return *this; } + inline_ IcePlane& Set(const IcePoint& p, const IcePoint& _n) { n = _n; d = - p | _n; return *this; } + IcePlane& Set(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2); + + inline_ float Distance(const IcePoint& p) const { return (p | n) + d; } + inline_ bool Belongs(const IcePoint& p) const { return fabsf(Distance(p)) < PLANE_EPSILON; } + + inline_ void Normalize() + { + float Denom = 1.0f / n.Magnitude(); + n.x *= Denom; + n.y *= Denom; + n.z *= Denom; + d *= Denom; + } + public: + // Members + IcePoint n; //!< The normal to the plane + float d; //!< The distance from the origin + + // Cast operators + inline_ operator IcePoint() const { return n; } + inline_ operator HPoint() const { return HPoint(n, d); } + + // Arithmetic operators + inline_ IcePlane operator*(const Matrix4x4& m) const + { + // Old code from Irion. Kept for reference. + IcePlane Ret(*this); + return Ret *= m; + } + + inline_ IcePlane& operator*=(const Matrix4x4& m) + { + // Old code from Irion. Kept for reference. + IcePoint n2 = HPoint(n, 0.0f) * m; + d = -((IcePoint) (HPoint( -d*n, 1.0f ) * m) | n2); + n = n2; + return *this; + } + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a plane by a 4x4 matrix. Same as IcePlane * Matrix4x4 operator, but faster. + * \param transformed [out] transformed plane + * \param plane [in] source plane + * \param transform [in] transform matrix + * \warning the plane normal must be unit-length + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void TransformPlane(IcePlane& transformed, const IcePlane& plane, const Matrix4x4& transform) + { + // Rotate the normal using the rotation part of the 4x4 matrix + transformed.n = plane.n * Matrix3x3(transform); + + // Compute new d + transformed.d = plane.d - (IcePoint(transform.GetTrans())|transformed.n); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a plane by a 4x4 matrix. Same as IcePlane * Matrix4x4 operator, but faster. + * \param plane [in/out] source plane (transformed on return) + * \param transform [in] transform matrix + * \warning the plane normal must be unit-length + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void TransformPlane(IcePlane& plane, const Matrix4x4& transform) + { + // Rotate the normal using the rotation part of the 4x4 matrix + plane.n *= Matrix3x3(transform); + + // Compute new d + plane.d -= IcePoint(transform.GetTrans())|plane.n; + } + +#endif // __ICEPLANE_H__ diff --git a/third-party/Opcode/Ice/IcePoint.cpp b/third-party/Opcode/Ice/IcePoint.cpp new file mode 100644 index 0000000..616b08c --- /dev/null +++ b/third-party/Opcode/Ice/IcePoint.cpp @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3D vectors. + * \file IcePoint.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 3D point. + * + * The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3". + * So the choice was between "Point" and "Vector3", the first one looked better (IMHO). + * + * Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3; + * This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out: + * + * \code + * Point P0,P1 = some 3D points; + * Point Delta = P1 - P0; + * \endcode + * + * This compiles fine, although you should have written: + * + * \code + * Point P0,P1 = some 3D points; + * Vector3 Delta = P1 - P0; + * \endcode + * + * Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake + * from the author or something you don't get. + * + * One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors. + * But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work. + * + * Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store + * your model's vertices and in most cases, you really want to use Points to save ram. + * + * \class Point + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates a positive unit random vector. + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +IcePoint& IcePoint::PositiveUnitRandomVector() +{ + x = UnitRandomFloat(); + y = UnitRandomFloat(); + z = UnitRandomFloat(); + Normalize(); + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates a unit random vector. + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +IcePoint& IcePoint::UnitRandomVector() +{ + x = UnitRandomFloat() - 0.5f; + y = UnitRandomFloat() - 0.5f; + z = UnitRandomFloat() - 0.5f; + Normalize(); + return *this; +} + +// Cast operator +// WARNING: not inlined +IcePoint::operator HPoint() const { return HPoint(x, y, z, 0.0f); } + +IcePoint& IcePoint::Refract(const IcePoint& eye, const IcePoint& n, float refractindex, IcePoint& refracted) +{ + // IcePoint EyePt = eye position + // IcePoint p = current vertex + // IcePoint n = vertex normal + // IcePoint rv = refracted vector + // Eye vector - doesn't need to be normalized + IcePoint Env; + Env.x = eye.x - x; + Env.y = eye.y - y; + Env.z = eye.z - z; + + float NDotE = n|Env; + float NDotN = n|n; + NDotE /= refractindex; + + // Refracted vector + refracted = n*NDotE - Env*NDotN; + + return *this; +} + +IcePoint& IcePoint::ProjectToPlane(const IcePlane& p) +{ + *this-= (p.d + (*this|p.n))*p.n; + return *this; +} + +void IcePoint::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const +{ + projected = HPoint(x, y, z, 1.0f) * mat; + projected.w = 1.0f / projected.w; + + projected.x*=projected.w; + projected.y*=projected.w; + projected.z*=projected.w; + + projected.x *= halfrenderwidth; projected.x += halfrenderwidth; + projected.y *= -halfrenderheight; projected.y += halfrenderheight; +} + +void IcePoint::SetNotUsed() +{ + // We use a particular integer pattern : 0xffffffff everywhere. This is a NAN. + IR(x) = 0xffffffff; + IR(y) = 0xffffffff; + IR(z) = 0xffffffff; +} + +BOOL IcePoint::IsNotUsed() const +{ + if(IR(x)!=0xffffffff) return FALSE; + if(IR(y)!=0xffffffff) return FALSE; + if(IR(z)!=0xffffffff) return FALSE; + return TRUE; +} + +IcePoint& IcePoint::Mult(const Matrix3x3& mat, const IcePoint& a) +{ + x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; + y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; + z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; + return *this; +} + +IcePoint& IcePoint::Mult2(const Matrix3x3& mat1, const IcePoint& a1, const Matrix3x3& mat2, const IcePoint& a2) +{ + x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2]; + y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2]; + z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2]; + return *this; +} + +IcePoint& IcePoint::Mac(const Matrix3x3& mat, const IcePoint& a) +{ + x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; + y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; + z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; + return *this; +} + +IcePoint& IcePoint::TransMult(const Matrix3x3& mat, const IcePoint& a) +{ + x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0]; + y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1]; + z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2]; + return *this; +} + +IcePoint& IcePoint::Transform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos) +{ + x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x; + y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y; + z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z; + return *this; +} + +IcePoint& IcePoint::InvTransform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos) +{ + float sx = r.x - linpos.x; + float sy = r.y - linpos.y; + float sz = r.z - linpos.z; + x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0]; + y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1]; + z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2]; + return *this; +} diff --git a/third-party/Opcode/Ice/IcePoint.h b/third-party/Opcode/Ice/IcePoint.h new file mode 100644 index 0000000..2ca1801 --- /dev/null +++ b/third-party/Opcode/Ice/IcePoint.h @@ -0,0 +1,528 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3D vectors. + * \file IcePoint.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPOINT_H__ +#define __ICEPOINT_H__ + + // Forward declarations + class HPoint; + class IcePlane; + class Matrix3x3; + class Matrix4x4; + + #define CROSS2D(a, b) (a.x*b.y - b.x*a.y) + + const float EPSILON2 = 1.0e-20f; + + class ICEMATHS_API IcePoint + { + public: + + //! Empty constructor + inline_ IcePoint() {} + //! Constructor from a single float +// inline_ Point(float val) : x(val), y(val), z(val) {} +// Removed since it introduced the nasty "Point T = *Matrix4x4.GetTrans();" bug....... + //! Constructor from floats + inline_ IcePoint(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} + //! Constructor from array + inline_ IcePoint(const float f[3]) : x(f[_X]), y(f[_Y]), z(f[_Z]) {} + //! Copy constructor + inline_ IcePoint(const IcePoint& p) : x(p.x), y(p.y), z(p.z) {} + //! Destructor + inline_ ~IcePoint() {} + + //! Clears the vector + inline_ IcePoint& Zero() { x = y = z = 0.0f; return *this; } + + //! + infinity + inline_ IcePoint& SetPlusInfinity() { x = y = z = MAX_FLOAT; return *this; } + //! - infinity + inline_ IcePoint& SetMinusInfinity() { x = y = z = MIN_FLOAT; return *this; } + + //! Sets positive unit random vector + IcePoint& PositiveUnitRandomVector(); + //! Sets unit random vector + IcePoint& UnitRandomVector(); + + //! Assignment from values + inline_ IcePoint& Set(float _x, float _y, float _z) { x = _x; y = _y; z = _z; return *this; } + //! Assignment from array + inline_ IcePoint& Set(const float f[3]) { x = f[_X]; y = f[_Y]; z = f[_Z]; return *this; } + //! Assignment from another point + inline_ IcePoint& Set(const IcePoint& src) { x = src.x; y = src.y; z = src.z; return *this; } + + //! Adds a vector + inline_ IcePoint& Add(const IcePoint& p) { x += p.x; y += p.y; z += p.z; return *this; } + //! Adds a vector + inline_ IcePoint& Add(float _x, float _y, float _z) { x += _x; y += _y; z += _z; return *this; } + //! Adds a vector + inline_ IcePoint& Add(const float f[3]) { x += f[_X]; y += f[_Y]; z += f[_Z]; return *this; } + //! Adds vectors + inline_ IcePoint& Add(const IcePoint& p, const IcePoint& q) { x = p.x+q.x; y = p.y+q.y; z = p.z+q.z; return *this; } + + //! Subtracts a vector + inline_ IcePoint& Sub(const IcePoint& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } + //! Subtracts a vector + inline_ IcePoint& Sub(float _x, float _y, float _z) { x -= _x; y -= _y; z -= _z; return *this; } + //! Subtracts a vector + inline_ IcePoint& Sub(const float f[3]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; return *this; } + //! Subtracts vectors + inline_ IcePoint& Sub(const IcePoint& p, const IcePoint& q) { x = p.x-q.x; y = p.y-q.y; z = p.z-q.z; return *this; } + + //! this = -this + inline_ IcePoint& Neg() { x = -x; y = -y; z = -z; return *this; } + //! this = -a + inline_ IcePoint& Neg(const IcePoint& a) { x = -a.x; y = -a.y; z = -a.z; return *this; } + + //! Multiplies by a scalar + inline_ IcePoint& Mult(float s) { x *= s; y *= s; z *= s; return *this; } + + //! this = a * scalar + inline_ IcePoint& Mult(const IcePoint& a, float scalar) + { + x = a.x * scalar; + y = a.y * scalar; + z = a.z * scalar; + return *this; + } + + //! this = a + b * scalar + inline_ IcePoint& Mac(const IcePoint& a, const IcePoint& b, float scalar) + { + x = a.x + b.x * scalar; + y = a.y + b.y * scalar; + z = a.z + b.z * scalar; + return *this; + } + + //! this = this + a * scalar + inline_ IcePoint& Mac(const IcePoint& a, float scalar) + { + x += a.x * scalar; + y += a.y * scalar; + z += a.z * scalar; + return *this; + } + + //! this = a - b * scalar + inline_ IcePoint& Msc(const IcePoint& a, const IcePoint& b, float scalar) + { + x = a.x - b.x * scalar; + y = a.y - b.y * scalar; + z = a.z - b.z * scalar; + return *this; + } + + //! this = this - a * scalar + inline_ IcePoint& Msc(const IcePoint& a, float scalar) + { + x -= a.x * scalar; + y -= a.y * scalar; + z -= a.z * scalar; + return *this; + } + + //! this = a + b * scalarb + c * scalarc + inline_ IcePoint& Mac2(const IcePoint& a, const IcePoint& b, float scalarb, const IcePoint& c, float scalarc) + { + x = a.x + b.x * scalarb + c.x * scalarc; + y = a.y + b.y * scalarb + c.y * scalarc; + z = a.z + b.z * scalarb + c.z * scalarc; + return *this; + } + + //! this = a - b * scalarb - c * scalarc + inline_ IcePoint& Msc2(const IcePoint& a, const IcePoint& b, float scalarb, const IcePoint& c, float scalarc) + { + x = a.x - b.x * scalarb - c.x * scalarc; + y = a.y - b.y * scalarb - c.y * scalarc; + z = a.z - b.z * scalarb - c.z * scalarc; + return *this; + } + + //! this = mat * a + inline_ IcePoint& Mult(const Matrix3x3& mat, const IcePoint& a); + + //! this = mat1 * a1 + mat2 * a2 + inline_ IcePoint& Mult2(const Matrix3x3& mat1, const IcePoint& a1, const Matrix3x3& mat2, const IcePoint& a2); + + //! this = this + mat * a + inline_ IcePoint& Mac(const Matrix3x3& mat, const IcePoint& a); + + //! this = transpose(mat) * a + inline_ IcePoint& TransMult(const Matrix3x3& mat, const IcePoint& a); + + //! Linear interpolate between two vectors: this = a + t * (b - a) + inline_ IcePoint& Lerp(const IcePoint& a, const IcePoint& b, float t) + { + x = a.x + t * (b.x - a.x); + y = a.y + t * (b.y - a.y); + z = a.z + t * (b.z - a.z); + return *this; + } + + //! Hermite interpolate between p1 and p2. p0 and p3 are used for finding gradient at p1 and p2. + //! this = p0 * (2t^2 - t^3 - t)/2 + //! + p1 * (3t^3 - 5t^2 + 2)/2 + //! + p2 * (4t^2 - 3t^3 + t)/2 + //! + p3 * (t^3 - t^2)/2 + inline_ IcePoint& Herp(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2, const IcePoint& p3, float t) + { + float t2 = t * t; + float t3 = t2 * t; + float kp0 = (2.0f * t2 - t3 - t) * 0.5f; + float kp1 = (3.0f * t3 - 5.0f * t2 + 2.0f) * 0.5f; + float kp2 = (4.0f * t2 - 3.0f * t3 + t) * 0.5f; + float kp3 = (t3 - t2) * 0.5f; + x = p0.x * kp0 + p1.x * kp1 + p2.x * kp2 + p3.x * kp3; + y = p0.y * kp0 + p1.y * kp1 + p2.y * kp2 + p3.y * kp3; + z = p0.z * kp0 + p1.z * kp1 + p2.z * kp2 + p3.z * kp3; + return *this; + } + + //! this = rotpos * r + linpos + inline_ IcePoint& Transform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos); + + //! this = trans(rotpos) * (r - linpos) + inline_ IcePoint& InvTransform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos); + + //! Returns MIN(x, y, z); + inline_ float Min() const { return MIN(x, MIN(y, z)); } + //! Returns MAX(x, y, z); + inline_ float Max() const { return MAX(x, MAX(y, z)); } + //! Sets each element to be componentwise minimum + inline_ IcePoint& Min(const IcePoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); return *this; } + //! Sets each element to be componentwise maximum + inline_ IcePoint& Max(const IcePoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); return *this; } + + //! Clamps each element + inline_ IcePoint& Clamp(float min, float max) + { + if(xmax) x=max; + if(ymax) y=max; + if(zmax) z=max; + return *this; + } + + //! Computes square magnitude + inline_ float SquareMagnitude() const { return x*x + y*y + z*z; } + //! Computes magnitude + inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z); } + //! Computes volume + inline_ float Volume() const { return x * y * z; } + + //! Checks the IcePoint is near zero + inline_ bool ApproxZero() const { return SquareMagnitude() < EPSILON2; } + + //! Tests for exact zero vector + inline_ BOOL IsZero() const + { + if(IR(x) || IR(y) || IR(z)) return FALSE; + return TRUE; + } + + //! Checks IcePoint validity + inline_ BOOL IsValid() const + { + if(!IsValidFloat(x)) return FALSE; + if(!IsValidFloat(y)) return FALSE; + if(!IsValidFloat(z)) return FALSE; + return TRUE; + } + + //! Slighty moves the IcePoint + void Tweak(udword coord_mask, udword tweak_mask) + { + if(coord_mask&1) { udword Dummy = IR(x); Dummy^=tweak_mask; x = FR(Dummy); } + if(coord_mask&2) { udword Dummy = IR(y); Dummy^=tweak_mask; y = FR(Dummy); } + if(coord_mask&4) { udword Dummy = IR(z); Dummy^=tweak_mask; z = FR(Dummy); } + } + + #define TWEAKMASK 0x3fffff + #define TWEAKNOTMASK ~TWEAKMASK + //! Slighty moves the IcePoint out + inline_ void TweakBigger() + { + udword Dummy = (IR(x)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); + Dummy = (IR(y)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); + Dummy = (IR(z)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); + } + + //! Slighty moves the IcePoint in + inline_ void TweakSmaller() + { + udword Dummy = (IR(x)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); + Dummy = (IR(y)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); + Dummy = (IR(z)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); + } + + //! Normalizes the vector + inline_ IcePoint& Normalize() + { + float M = x*x + y*y + z*z; + if(M) + { + M = 1.0f / sqrtf(M); + x *= M; + y *= M; + z *= M; + } + return *this; + } + + //! Sets vector length + inline_ IcePoint& SetLength(float length) + { + float NewLength = length / Magnitude(); + x *= NewLength; + y *= NewLength; + z *= NewLength; + return *this; + } + + //! Clamps vector length + inline_ IcePoint& ClampLength(float limit_length) + { + if(limit_length>=0.0f) // Magnitude must be positive + { + float CurrentSquareLength = SquareMagnitude(); + + if(CurrentSquareLength > limit_length * limit_length) + { + float Coeff = limit_length / sqrtf(CurrentSquareLength); + x *= Coeff; + y *= Coeff; + z *= Coeff; + } + } + return *this; + } + + //! Computes distance to another IcePoint + inline_ float Distance(const IcePoint& b) const + { + return sqrtf((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); + } + + //! Computes square distance to another IcePoint + inline_ float SquareDistance(const IcePoint& b) const + { + return ((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); + } + + //! Dot product dp = this|a + inline_ float Dot(const IcePoint& p) const { return p.x * x + p.y * y + p.z * z; } + + //! Cross product this = a x b + inline_ IcePoint& Cross(const IcePoint& a, const IcePoint& b) + { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + return *this; + } + + //! Vector code ( bitmask = sign(z) | sign(y) | sign(x) ) + inline_ udword VectorCode() const + { + return (IR(x)>>31) | ((IR(y)&SIGN_BITMASK)>>30) | ((IR(z)&SIGN_BITMASK)>>29); + } + + //! Returns largest axis + inline_ PointComponent LargestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(Vals[_Y] > Vals[m]) m = _Y; + if(Vals[_Z] > Vals[m]) m = _Z; + return m; + } + + //! Returns closest axis + inline_ PointComponent ClosestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(AIR(Vals[_Y]) > AIR(Vals[m])) m = _Y; + if(AIR(Vals[_Z]) > AIR(Vals[m])) m = _Z; + return m; + } + + //! Returns smallest axis + inline_ PointComponent SmallestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(Vals[_Y] < Vals[m]) m = _Y; + if(Vals[_Z] < Vals[m]) m = _Z; + return m; + } + + //! Refracts the IcePoint + IcePoint& Refract(const IcePoint& eye, const IcePoint& n, float refractindex, IcePoint& refracted); + + //! Projects the IcePoint onto a plane + IcePoint& ProjectToPlane(const IcePlane& p); + + //! Projects the IcePoint onto the screen + void ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const; + + //! Unfolds the IcePoint onto a plane according to edge(a,b) + IcePoint& Unfold(IcePlane& p, IcePoint& a, IcePoint& b); + + //! Hash function from Ville Miettinen + inline_ udword GetHashValue() const + { + const udword* h = (const udword*)(this); + udword f = (h[0]+h[1]*11-(h[2]*17)) & 0x7fffffff; // avoid problems with +-0 + return (f>>22)^(f>>12)^(f); + } + + //! Stuff magic values in the IcePoint, marking it as explicitely not used. + void SetNotUsed(); + //! Checks the IcePoint is marked as not used + BOOL IsNotUsed() const; + + // Arithmetic operators + + //! Unary operator for IcePoint Negate = - IcePoint + inline_ IcePoint operator-() const { return IcePoint(-x, -y, -z); } + + //! Operator for IcePoint Plus = IcePoint + IcePoint. + inline_ IcePoint operator+(const IcePoint& p) const { return IcePoint(x + p.x, y + p.y, z + p.z); } + //! Operator for IcePoint Minus = IcePoint - IcePoint. + inline_ IcePoint operator-(const IcePoint& p) const { return IcePoint(x - p.x, y - p.y, z - p.z); } + + //! Operator for IcePoint Mul = IcePoint * IcePoint. + inline_ IcePoint operator*(const IcePoint& p) const { return IcePoint(x * p.x, y * p.y, z * p.z); } + //! Operator for IcePoint Scale = IcePoint * float. + inline_ IcePoint operator*(float s) const { return IcePoint(x * s, y * s, z * s ); } + //! Operator for IcePoint Scale = float * IcePoint. + inline_ friend IcePoint operator*(float s, const IcePoint& p) { return IcePoint(s * p.x, s * p.y, s * p.z); } + + //! Operator for IcePoint Div = IcePoint / IcePoint. + inline_ IcePoint operator/(const IcePoint& p) const { return IcePoint(x / p.x, y / p.y, z / p.z); } + //! Operator for IcePoint Scale = IcePoint / float. + inline_ IcePoint operator/(float s) const { s = 1.0f / s; return IcePoint(x * s, y * s, z * s); } + //! Operator for IcePoint Scale = float / IcePoint. + inline_ friend IcePoint operator/(float s, const IcePoint& p) { return IcePoint(s / p.x, s / p.y, s / p.z); } + + //! Operator for float DotProd = IcePoint | IcePoint. + inline_ float operator|(const IcePoint& p) const { return x*p.x + y*p.y + z*p.z; } + //! Operator for IcePoint VecProd = IcePoint ^ IcePoint. + inline_ IcePoint operator^(const IcePoint& p) const + { + return IcePoint( + y * p.z - z * p.y, + z * p.x - x * p.z, + x * p.y - y * p.x ); + } + + //! Operator for IcePoint += IcePoint. + inline_ IcePoint& operator+=(const IcePoint& p) { x += p.x; y += p.y; z += p.z; return *this; } + //! Operator for IcePoint += float. + inline_ IcePoint& operator+=(float s) { x += s; y += s; z += s; return *this; } + + //! Operator for IcePoint -= IcePoint. + inline_ IcePoint& operator-=(const IcePoint& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } + //! Operator for IcePoint -= float. + inline_ IcePoint& operator-=(float s) { x -= s; y -= s; z -= s; return *this; } + + //! Operator for IcePoint *= IcePoint. + inline_ IcePoint& operator*=(const IcePoint& p) { x *= p.x; y *= p.y; z *= p.z; return *this; } + //! Operator for IcePoint *= float. + inline_ IcePoint& operator*=(float s) { x *= s; y *= s; z *= s; return *this; } + + //! Operator for IcePoint /= IcePoint. + inline_ IcePoint& operator/=(const IcePoint& p) { x /= p.x; y /= p.y; z /= p.z; return *this; } + //! Operator for IcePoint /= float. + inline_ IcePoint& operator/=(float s) { s = 1.0f/s; x *= s; y *= s; z *= s; return *this; } + + // Logical operators + + //! Operator for "if(IcePoint==IcePoint)" + inline_ bool operator==(const IcePoint& p) const { return ( (IR(x)==IR(p.x))&&(IR(y)==IR(p.y))&&(IR(z)==IR(p.z))); } + //! Operator for "if(IcePoint!=IcePoint)" + inline_ bool operator!=(const IcePoint& p) const { return ( (IR(x)!=IR(p.x))||(IR(y)!=IR(p.y))||(IR(z)!=IR(p.z))); } + + // Arithmetic operators + + //! Operator for IcePoint Mul = IcePoint * Matrix3x3. + inline_ IcePoint operator*(const Matrix3x3& mat) const + { + class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining + const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; + + return IcePoint( + x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0], + x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1], + x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] ); + } + + //! Operator for IcePoint Mul = IcePoint * Matrix4x4. + inline_ IcePoint operator*(const Matrix4x4& mat) const + { + class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining + const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; + + return IcePoint( + x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0], + x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1], + x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]); + } + + //! Operator for IcePoint *= Matrix3x3. + inline_ IcePoint& operator*=(const Matrix3x3& mat) + { + class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining + const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; + + float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0]; + float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1]; + float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2]; + + x = xp; y = yp; z = zp; + + return *this; + } + + //! Operator for IcePoint *= Matrix4x4. + inline_ IcePoint& operator*=(const Matrix4x4& mat) + { + class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining + const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; + + float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0]; + float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1]; + float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]; + + x = xp; y = yp; z = zp; + + return *this; + } + + // Cast operators + + //! Cast a IcePoint to a HPoint. w is set to zero. + operator HPoint() const; + + inline_ operator const float*() const { return &x; } + inline_ operator float*() { return &x; } + + public: + float x, y, z; + }; + + FUNCTION ICEMATHS_API void Normalize1(IcePoint& a); + FUNCTION ICEMATHS_API void Normalize2(IcePoint& a); + +#endif //__ICEPOINT_H__ diff --git a/third-party/Opcode/Ice/IcePreprocessor.h b/third-party/Opcode/Ice/IcePreprocessor.h new file mode 100644 index 0000000..d4ca850 --- /dev/null +++ b/third-party/Opcode/Ice/IcePreprocessor.h @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains preprocessor stuff. This should be the first included header. + * \file IcePreprocessor.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPREPROCESSOR_H__ +#define __ICEPREPROCESSOR_H__ + + // Check platform + #if defined( _WIN32 ) || defined( WIN32 ) + #pragma message("Compiling on Windows...") + #define PLATFORM_WINDOWS + #else + #pragma message("Compiling on unknown platform...") + #endif + + // Check compiler + #if defined(_MSC_VER) + #pragma message("Compiling with VC++...") + #define COMPILER_VISUAL_CPP + #else + #pragma message("Compiling with unknown compiler...") + #endif + + // Check compiler options. If this file is included in user-apps, this + // shouldn't be needed, so that they can use what they like best. + #ifndef ICE_DONT_CHECK_COMPILER_OPTIONS + #ifdef COMPILER_VISUAL_CPP + #if defined(_CHAR_UNSIGNED) + #endif + + #if defined(_CPPRTTI) + #error Please disable RTTI... + #endif + + #if defined(_CPPUNWIND) + #error Please disable exceptions... + #endif + + #if defined(_MT) + // Multithreading + #endif + #endif + #endif + + // Check debug mode + #ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it. + #ifndef _DEBUG + #define _DEBUG + #endif + #endif + + #ifdef _DEBUG + // Here you may define items for debug builds + #endif + + #ifndef THIS_FILE + #define THIS_FILE __FILE__ + #endif + + #ifdef WIN32 + #ifndef ICE_NO_DLL + #ifdef ICECORE_EXPORTS + #define ICECORE_API __declspec(dllexport) + #else + #define ICECORE_API __declspec(dllimport) + #endif + #else + #define ICECORE_API + #endif + #else + #define ICECORE_API + #endif + + // Don't override new/delete +// #define DEFAULT_NEWDELETE + #define DONT_TRACK_MEMORY_LEAKS + + #define FUNCTION extern "C" + + // Cosmetic stuff [mainly useful with multiple inheritance] + #define override(base_class) virtual + + // Our own inline keyword, so that: + // - we can switch to __forceinline to check it's really better or not + // - we can remove __forceinline if the compiler doesn't support it +// #define inline_ __forceinline +// #define inline_ inline + + // Contributed by Bruce Mitchener + #if defined(COMPILER_VISUAL_CPP) + #define inline_ __forceinline +// #define inline_ inline + #elif defined(__GNUC__) && __GNUC__ < 3 + #define inline_ inline + #elif defined(__GNUC__) + #define inline_ inline __attribute__ ((always_inline)) + #else + #define inline_ inline + #endif + + // Down the hatch + #pragma inline_depth( 255 ) + + #ifdef COMPILER_VISUAL_CPP + #pragma intrinsic(memcmp) + #pragma intrinsic(memcpy) + #pragma intrinsic(memset) + #pragma intrinsic(strcat) + #pragma intrinsic(strcmp) + #pragma intrinsic(strcpy) + #pragma intrinsic(strlen) + #pragma intrinsic(abs) + #pragma intrinsic(labs) + #endif + + // ANSI compliance + #ifdef _DEBUG + // Remove painful warning in debug + inline_ bool __False__(){ return false; } + #define for if(__False__()){} else for + #else + #define for if(0){} else for + #endif + +#endif // __ICEPREPROCESSOR_H__ diff --git a/third-party/Opcode/Ice/IceRandom.cpp b/third-party/Opcode/Ice/IceRandom.cpp new file mode 100644 index 0000000..305721d --- /dev/null +++ b/third-party/Opcode/Ice/IceRandom.cpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for random generators. + * \file IceRandom.cpp + * \author Pierre Terdiman + * \date August, 9, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceCore; + +void IceCore:: SRand(udword seed) +{ + srand(seed); +} + +udword IceCore::Rand() +{ + return rand(); +} + + +static BasicRandom gRandomGenerator(42); + +udword IceCore::GetRandomIndex(udword max_index) +{ + // We don't use rand() since it's limited to RAND_MAX + udword Index = gRandomGenerator.Randomize(); + return Index % max_index; +} + diff --git a/third-party/Opcode/Ice/IceRandom.h b/third-party/Opcode/Ice/IceRandom.h new file mode 100644 index 0000000..3170b33 --- /dev/null +++ b/third-party/Opcode/Ice/IceRandom.h @@ -0,0 +1,42 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for random generators. + * \file IceRandom.h + * \author Pierre Terdiman + * \date August, 9, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICERANDOM_H__ +#define __ICERANDOM_H__ + + FUNCTION ICECORE_API void SRand(udword seed); + FUNCTION ICECORE_API udword Rand(); + + //! Returns a unit random floating-point value + inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; } + + //! Returns a random index so that 0<= index < max_index + ICECORE_API udword GetRandomIndex(udword max_index); + + class ICECORE_API BasicRandom + { + public: + + //! Constructor + inline_ BasicRandom(udword seed=0) : mRnd(seed) {} + //! Destructor + inline_ ~BasicRandom() {} + + inline_ void SetSeed(udword seed) { mRnd = seed; } + inline_ udword GetCurrentValue() const { return mRnd; } + inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; } + + private: + udword mRnd; + }; + +#endif // __ICERANDOM_H__ + diff --git a/third-party/Opcode/Ice/IceRay.cpp b/third-party/Opcode/Ice/IceRay.cpp new file mode 100644 index 0000000..d7c617a --- /dev/null +++ b/third-party/Opcode/Ice/IceRay.cpp @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for rays. + * \file IceRay.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Ray class. + * A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity + * \class Ray + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + O = Origin = impact IcePoint + i = normalized vector along the x axis + j = normalized vector along the y axis = actually the normal vector in O + D = Direction vector, norm |D| = 1 + N = Projection of D on y axis, norm |N| = normal reaction + T = Projection of D on x axis, norm |T| = tangential reaction + R = Reflexion vector + + ^y + | + | + | + _ _ _| _ _ _ + * * *| + \ | / + \ |N / | + R\ | /D + \ | / | + \ | / + _________\|/______*_______>x + O T + + Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized. + + j|D = |j|*|D|*cos(theta) => |N| = j|D + + Then we simply have: + + D = N + T + + To compute tangential reaction : + + T = D - N + + To compute reflexion vector : + + R = N - T = N - (D-N) = 2*N - D +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +float Ray::SquareDistance(const IcePoint& Point, float* t) const +{ + IcePoint Diff = Point - mOrig; + float fT = Diff | mDir; + + if(fT<=0.0f) + { + fT = 0.0f; + } + else + { + fT /= mDir.SquareMagnitude(); + Diff -= fT*mDir; + } + + if(t) *t = fT; + + return Diff.SquareMagnitude(); +} diff --git a/third-party/Opcode/Ice/IceRay.h b/third-party/Opcode/Ice/IceRay.h new file mode 100644 index 0000000..4c0d6d9 --- /dev/null +++ b/third-party/Opcode/Ice/IceRay.h @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for rays. + * \file IceRay.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICERAY_H__ +#define __ICERAY_H__ + + class ICEMATHS_API Ray + { + public: + //! Constructor + inline_ Ray() {} + //! Constructor + inline_ Ray(const IcePoint& orig, const IcePoint& dir) : mOrig(orig), mDir(dir) {} + //! Copy constructor + inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {} + //! Destructor + inline_ ~Ray() {} + + float SquareDistance(const IcePoint& point, float* t=null) const; + inline_ float Distance(const IcePoint& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } + + IcePoint mOrig; //!< Ray origin + IcePoint mDir; //!< Normalized direction + }; + + inline_ void ComputeReflexionVector(IcePoint& reflected, const IcePoint& incoming_dir, const IcePoint& outward_normal) + { + reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal); + } + + inline_ void ComputeReflexionVector(IcePoint& reflected, const IcePoint& source, const IcePoint& impact, const IcePoint& normal) + { + IcePoint V = impact - source; + reflected = V - normal * 2.0f * (V|normal); + } + + inline_ void DecomposeVector(IcePoint& normal_compo, IcePoint& tangent_compo, const IcePoint& outward_dir, const IcePoint& outward_normal) + { + normal_compo = outward_normal * (outward_dir|outward_normal); + tangent_compo = outward_dir - normal_compo; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a direction vector from world space to local space + * \param local_dir [out] direction vector in local space + * \param world_dir [in] direction vector in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalDirection(IcePoint& local_dir, const IcePoint& world_dir, const Matrix4x4& world) + { + // Get world direction back in local space +// Matrix3x3 InvWorld = world; +// local_dir = InvWorld * world_dir; + local_dir = Matrix3x3(world) * world_dir; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a position vector from world space to local space + * \param local_pt [out] position vector in local space + * \param world_pt [in] position vector in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalPoint(IcePoint& local_pt, const IcePoint& world_pt, const Matrix4x4& world) + { + // Get world vertex back in local space + Matrix4x4 InvWorld = world; + InvWorld.Invert(); + local_pt = world_pt * InvWorld; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a ray from world space to local space + * \param local_ray [out] ray in local space + * \param world_ray [in] ray in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world) + { + // Get world ray back in local space + ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world); + ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world); + } + +#endif // __ICERAY_H__ diff --git a/third-party/Opcode/Ice/IceRevisitedRadix.cpp b/third-party/Opcode/Ice/IceRevisitedRadix.cpp new file mode 100644 index 0000000..b654995 --- /dev/null +++ b/third-party/Opcode/Ice/IceRevisitedRadix.cpp @@ -0,0 +1,520 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains source code from the article "Radix Sort Revisited". + * \file IceRevisitedRadix.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Revisited Radix Sort. + * This is my new radix routine: + * - it uses indices and doesn't recopy the values anymore, hence wasting less ram + * - it creates all the histograms in one run instead of four + * - it sorts words faster than dwords and bytes faster than words + * - it correctly sorts negative floating-point values by patching the offsets + * - it automatically takes advantage of temporal coherence + * - multiple keys support is a side effect of temporal coherence + * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway] + * + * History: + * - 08.15.98: very first version + * - 04.04.00: recoded for the radix article + * - 12.xx.00: code lifting + * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here) + * - 10.11.01: added local ram support + * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting...... + * - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all. + * - ranks are not "reset" anymore, but implicit on first calls + * - 07.05.02: - offsets rewritten with one less indirection. + * - 11.03.02: - "bool" replaced with RadixHint enum + * + * \class RadixSort + * \author Pierre Terdiman + * \version 1.4 + * \date August, 15, 1998 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +To do: + - add an offset parameter between two input values (avoid some data recopy sometimes) + - unroll ? asm ? + - 11 bits trick & 3 passes as Michael did + - prefetch stuff the day I have a P3 + - make a version with 16-bits indices ? +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceCore; + +#define INVALIDATE_RANKS mCurrentSize|=0x80000000 +#define VALIDATE_RANKS mCurrentSize&=0x7fffffff +#define CURRENT_SIZE (mCurrentSize&0x7fffffff) +#define INVALID_RANKS (mCurrentSize&0x80000000) + +#define CHECK_RESIZE(n) \ + if(n!=mPreviousSize) \ + { \ + if(n>mCurrentSize) Resize(n); \ + else ResetRanks(); \ + mPreviousSize = n; \ + } + +#define CREATE_HISTOGRAMS(type, buffer) \ + /* Clear counters/histograms */ \ + ZeroMemory(mHistogram, 256*4*sizeof(udword)); \ + \ + /* Prepare to count */ \ + ubyte* p = (ubyte*)input; \ + ubyte* pe = &p[nb*4]; \ + udword* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \ + udword* h1= &mHistogram[256]; /* Histogram for second pass */ \ + udword* h2= &mHistogram[512]; /* Histogram for third pass */ \ + udword* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \ + \ + bool AlreadySorted = true; /* Optimism... */ \ + \ + if(INVALID_RANKS) \ + { \ + /* Prepare for temporal coherence */ \ + type* Running = (type*)buffer; \ + type PrevVal = *Running; \ + \ + while(p!=pe) \ + { \ + /* Read input buffer in previous sorted order */ \ + type Val = *Running++; \ + /* Check whether already sorted or not */ \ + if(ValCurSize) Resize(nb); + mCurrentSize = nb; + INVALIDATE_RANKS; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main sort routine. + * This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data. + * \param input [in] a list of integer values to sort + * \param nb [in] number of values to sort, must be < 2^31 + * \param hint [in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint) +{ + // Checkings + if(!input || !nb || nb&0x80000000) return *this; + + // Stats + mTotalCalls++; + + // Resize lists if needed + CheckResize(nb); + +#ifdef RADIX_LOCAL_RAM + // Allocate histograms & offsets on the stack + udword mHistogram[256*4]; +// udword mOffset[256]; + udword* mLink[256]; +#endif + + // Create histograms (counters). Counters for all passes are created in one run. + // Pros: read input buffer once instead of four times + // Cons: mHistogram is 4Kb instead of 1Kb + // We must take care of signed/unsigned values for temporal coherence.... I just + // have 2 code paths even if just a single opcode changes. Self-modifying code, someone? + if(hint==RADIX_UNSIGNED) { CREATE_HISTOGRAMS(udword, input); } + else { CREATE_HISTOGRAMS(sdword, input); } + + // Compute #negative values involved if needed + udword NbNegativeValues = 0; + if(hint==RADIX_SIGNED) + { + // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128 + // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte, + // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers. + udword* h3= &mHistogram[768]; + for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part + } + + // Radix sort, j is the pass number (0=LSB, 3=MSB) + for(udword j=0;j<4;j++) + { + CHECK_PASS_VALIDITY(j); + + // Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is + // not a problem, numbers are correctly sorted anyway. + if(PerformPass) + { + // Should we care about negative values? + if(j!=3 || hint==RADIX_UNSIGNED) + { + // Here we deal with positive values only + + // Create offsets +// mOffset[0] = 0; +// for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + mLink[0] = mRanks2; + for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + } + else + { + // This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place. + + // Create biased offsets, in order for negative numbers to be sorted as well +// mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones + mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones +// for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + + // Fixing the wrong place for negative values +// mOffset[128] = 0; + mLink[128] = mRanks2; +// for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + } + + // Perform Radix Sort + ubyte* InputBytes = (ubyte*)input; + InputBytes += j; + if(INVALID_RANKS) + { +// for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). + // ### cmp to be killed. Not good. Later. +// if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above +// else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order + if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above + else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order + } + VALIDATE_RANKS; + } + else + { + for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). + // ### cmp to be killed. Not good. Later. +// if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above +// else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order + if(Radix<128) *mLink[Radix]++ = mRanks[i]; // Number is positive, same as above + else *(--mLink[Radix]) = mRanks[i]; // Number is negative, flip the sorting order + } + } + // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. + udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; + } + else + { + // The pass is useless, yet we still have to reverse the order of current list if all values are negative. + if(UniqueVal>=128) + { + if(INVALID_RANKS) + { + // ###Possible? + for(udword i=0;i=SqrLen) + { + fT = 1.0f; + Diff -= Dir; + } + else + { + fT /= SqrLen; + Diff -= fT*Dir; + } + } + + if(t) *t = fT; + + return Diff.SquareMagnitude(); +} diff --git a/third-party/Opcode/Ice/IceSegment.h b/third-party/Opcode/Ice/IceSegment.h new file mode 100644 index 0000000..72ddceb --- /dev/null +++ b/third-party/Opcode/Ice/IceSegment.h @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for segments. + * \file IceSegment.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICESEGMENT_H__ +#define __ICESEGMENT_H__ + + class ICEMATHS_API IceSegment + { + public: + //! Constructor + inline_ IceSegment() {} + //! Constructor + inline_ IceSegment(const IcePoint& p0, const IcePoint& p1) : mP0(p0), mP1(p1) {} + //! Copy constructor + inline_ IceSegment(const IceSegment& seg) : mP0(seg.mP0), mP1(seg.mP1) {} + //! Destructor + inline_ ~IceSegment() {} + + inline_ const IcePoint& GetOrigin() const { return mP0; } + inline_ IcePoint ComputeDirection() const { return mP1 - mP0; } + inline_ void ComputeDirection(IcePoint& dir) const { dir = mP1 - mP0; } + inline_ float ComputeLength() const { return mP1.Distance(mP0); } + inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); } + + inline_ void SetOriginDirection(const IcePoint& origin, const IcePoint& direction) + { + mP0 = mP1 = origin; + mP1 += direction; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes a IcePoint on the segment + * \param pt [out] IcePoint on segment + * \param t [in] IcePoint's parameter [t=0 => pt = mP0, t=1 => pt = mP1] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputePoint(IcePoint& pt, float t) const { pt = mP0 + t * (mP1 - mP0); } + + float SquareDistance(const IcePoint& IcePoint, float* t=null) const; + inline_ float Distance(const IcePoint& IcePoint, float* t=null) const { return sqrtf(SquareDistance(IcePoint, t)); } + + IcePoint mP0; //!< Start of segment + IcePoint mP1; //!< End of segment + }; + +#endif // __ICESEGMENT_H__ diff --git a/third-party/Opcode/Ice/IceTriangle.cpp b/third-party/Opcode/Ice/IceTriangle.cpp new file mode 100644 index 0000000..e55f73e --- /dev/null +++ b/third-party/Opcode/Ice/IceTriangle.cpp @@ -0,0 +1,286 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy triangle class. + * \file IceTriangle.cpp + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a triangle class. + * + * \class Tri + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static sdword VPlaneSideEps(const IcePoint& v, const IcePlane& plane, float epsilon) +{ + // Compute distance from current vertex to the plane + float Dist = plane.Distance(v); + // Compute side: + // 1 = the vertex is on the positive side of the plane + // -1 = the vertex is on the negative side of the plane + // 0 = the vertex is on the plane (within epsilon) + return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Flips the winding order. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Flip() +{ + IcePoint Tmp = mVerts[1]; + mVerts[1] = mVerts[2]; + mVerts[2] = Tmp; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle area. + * \return the area + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Area() const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle perimeter. + * \return the perimeter + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Perimeter() const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + return p0.Distance(p1) + + p0.Distance(p2) + + p1.Distance(p2); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle compacity. + * \return the compacity + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Compacity() const +{ + float P = Perimeter(); + if(P==0.0f) return 0.0f; + return (4.0f*PI*Area()/(P*P)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle normal. + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Normal(IcePoint& normal) const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + normal = ((p0 - p1)^(p0 - p2)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle denormalized normal. + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::DenormalizedNormal(IcePoint& normal) const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + normal = ((p0 - p1)^(p0 - p2)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle center. + * \param center [out] the computed center + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Center(IcePoint& center) const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + center = (p0 + p1 + p2)*INV3; +} + +PartVal Triangle::TestAgainstPlane(const IcePlane& plane, float epsilon) const +{ + bool Pos = false, Neg = false; + + // Loop through all vertices + for(udword i=0;i<3;i++) + { + // Compute side: + sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon); + + if (Side < 0) Neg = true; + else if (Side > 0) Pos = true; + } + + if (!Pos && !Neg) return TRI_ON_PLANE; + else if (Pos && Neg) return TRI_INTERSECT; + else if (Pos && !Neg) return TRI_PLUS_SPACE; + else if (!Pos && Neg) return TRI_MINUS_SPACE; + + // What?! + return TRI_FORCEDWORD; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle moment. + * \param m [out] the moment + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* +void Triangle::ComputeMoment(Moment& m) +{ + // Compute the area of the triangle + m.mArea = Area(); + + // Compute the centroid + Center(m.mCentroid); + + // Second-order components. Handle zero-area faces. + IcePoint& p = mVerts[0]; + IcePoint& q = mVerts[1]; + IcePoint& r = mVerts[2]; + if(m.mArea==0.0f) + { + // This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the + // sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices. + m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x); + m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y); + m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z); + m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y); + m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z); + m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z); + m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; + m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; + m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; + } + else + { + const float OneOverTwelve = 1.0f / 12.0f; + m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve; + m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve; + m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve; + m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve; + m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve; + m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve; + m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; + m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; + m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; + } +} +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's smallest edge length. + * \return the smallest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::MinEdgeLength() const +{ + float Min = MAX_FLOAT; + float Length01 = mVerts[0].Distance(mVerts[1]); + float Length02 = mVerts[0].Distance(mVerts[2]); + float Length12 = mVerts[1].Distance(mVerts[2]); + if(Length01 < Min) Min = Length01; + if(Length02 < Min) Min = Length02; + if(Length12 < Min) Min = Length12; + return Min; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's largest edge length. + * \return the largest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::MaxEdgeLength() const +{ + float Max = MIN_FLOAT; + float Length01 = mVerts[0].Distance(mVerts[1]); + float Length02 = mVerts[0].Distance(mVerts[2]); + float Length12 = mVerts[1].Distance(mVerts[2]); + if(Length01 > Max) Max = Length01; + if(Length02 > Max) Max = Length02; + if(Length12 > Max) Max = Length12; + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a IcePoint on the triangle according to the stabbing information. + * \param u,v [in] IcePoint's barycentric coordinates + * \param pt [out] IcePoint on triangle + * \param nearvtx [out] index of nearest vertex + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::ComputePoint(float u, float v, IcePoint& pt, udword* nearvtx) const +{ + // Compute IcePoint coordinates + pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2]; + + // Compute nearest vertex if needed + if(nearvtx) + { + // Compute distance vector + IcePoint d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to IcePoint on the face + mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to IcePoint on the face + mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to IcePoint on the face + + // Get smallest distance + *nearvtx = d.SmallestAxis(); + } +} + +void Triangle::Inflate(float fat_coeff, bool constant_border) +{ + // Compute triangle center + IcePoint TriangleCenter; + Center(TriangleCenter); + + // Don't normalize? + // Normalize => add a constant border, regardless of triangle size + // Don't => add more to big triangles + for(udword i=0;i<3;i++) + { + IcePoint v = mVerts[i] - TriangleCenter; + + if(constant_border) v.Normalize(); + + mVerts[i] += v * fat_coeff; + } +} diff --git a/third-party/Opcode/Ice/IceTriangle.h b/third-party/Opcode/Ice/IceTriangle.h new file mode 100644 index 0000000..e5c8426 --- /dev/null +++ b/third-party/Opcode/Ice/IceTriangle.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy triangle class. + * \file IceTriangle.h + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICETRIANGLE_H__ +#define __ICETRIANGLE_H__ + + // Forward declarations + class Moment; + + // Partitioning values + enum PartVal + { + TRI_MINUS_SPACE = 0, //!< Triangle is in the negative space + TRI_PLUS_SPACE = 1, //!< Triangle is in the positive space + TRI_INTERSECT = 2, //!< Triangle intersects plane + TRI_ON_PLANE = 3, //!< Triangle and plane are coplanar + + TRI_FORCEDWORD = 0x7fffffff + }; + + // A triangle class. + class ICEMATHS_API Triangle + { + public: + //! Constructor + inline_ Triangle() {} + //! Constructor + inline_ Triangle(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) { mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; } + //! Copy constructor + inline_ Triangle(const Triangle& triangle) + { + mVerts[0] = triangle.mVerts[0]; + mVerts[1] = triangle.mVerts[1]; + mVerts[2] = triangle.mVerts[2]; + } + //! Destructor + inline_ ~Triangle() {} + //! Vertices + IcePoint mVerts[3]; + + // Methods + void Flip(); + float Area() const; + float Perimeter() const; + float Compacity() const; + void Normal(IcePoint& normal) const; + void DenormalizedNormal(IcePoint& normal) const; + void Center(IcePoint& center) const; + inline_ IcePlane PlaneEquation() const { return IcePlane(mVerts[0], mVerts[1], mVerts[2]); } + + PartVal TestAgainstPlane(const IcePlane& plane, float epsilon) const; +// float Distance(Point& cp, Point& cq, Tri& tri); + void ComputeMoment(Moment& m); + float MinEdgeLength() const; + float MaxEdgeLength() const; + void ComputePoint(float u, float v, IcePoint& pt, udword* nearvtx=null) const; + void Inflate(float fat_coeff, bool constant_border); + }; + +#endif // __ICETRIANGLE_H__ diff --git a/third-party/Opcode/Ice/IceTrilist.h b/third-party/Opcode/Ice/IceTrilist.h new file mode 100644 index 0000000..057f8df --- /dev/null +++ b/third-party/Opcode/Ice/IceTrilist.h @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a triangle container. + * \file IceTrilist.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICETRILIST_H__ +#define __ICETRILIST_H__ + + class ICEMATHS_API TriList : public Container + { + public: + // Constructor / Destructor + TriList() {} + ~TriList() {} + + inline_ udword GetNbTriangles() const { return GetNbEntries()/9; } + inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); } + + void AddTri(const Triangle& tri) + { + Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z); + Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z); + Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z); + } + + void AddTri(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) + { + Add(p0.x).Add(p0.y).Add(p0.z); + Add(p1.x).Add(p1.y).Add(p1.z); + Add(p2.x).Add(p2.y).Add(p2.z); + } + }; + + class ICEMATHS_API TriangleList : public Container + { + public: + // Constructor / Destructor + TriangleList() {} + ~TriangleList() {} + + inline_ udword GetNbTriangles() const { return GetNbEntries()/3; } + inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();} + + void AddTriangle(const IndexedTriangle& tri) + { + Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]); + } + + void AddTriangle(udword vref0, udword vref1, udword vref2) + { + Add(vref0).Add(vref1).Add(vref2); + } + }; + +#endif //__ICETRILIST_H__ diff --git a/third-party/Opcode/Ice/IceTypes.h b/third-party/Opcode/Ice/IceTypes.h new file mode 100644 index 0000000..75104fa --- /dev/null +++ b/third-party/Opcode/Ice/IceTypes.h @@ -0,0 +1,164 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains custom types. + * \file IceTypes.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICETYPES_H__ +#define __ICETYPES_H__ + +#include + + #define USE_HANDLE_MANAGER + + // Constants + #define PI 3.1415926535897932384626433832795028841971693993751f //!< PI + #define HALFPI 1.57079632679489661923f //!< 0.5 * PI + #define TWOPI 6.28318530717958647692f //!< 2.0 * PI + #define INVPI 0.31830988618379067154f //!< 1.0 / PI + + #define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees + #define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians + + #define EXP 2.71828182845904523536f //!< e + #define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2) + #define LN2 0.693147180559945f //!< ln(2) + #define INVLN2 1.44269504089f //!< 1.0f / ln(2) + + #define INV3 0.33333333333333333333f //!< 1/3 + #define INV6 0.16666666666666666666f //!< 1/6 + #define INV7 0.14285714285714285714f //!< 1/7 + #define INV9 0.11111111111111111111f //!< 1/9 + #define INV255 0.00392156862745098039f //!< 1/255 + + #define SQRT2 1.41421356237f //!< sqrt(2) + #define INVSQRT2 0.707106781188f //!< 1 / sqrt(2) + + #define SQRT3 1.73205080757f //!< sqrt(3) + #define INVSQRT3 0.577350269189f //!< 1 / sqrt(3) + + #define null 0 //!< our own NULL pointer + + // Custom types used in ICE + typedef std::int8_t sbyte; + typedef std::uint8_t ubyte; + typedef std::int16_t sword; + typedef std::uint16_t uword; + typedef std::int32_t sdword; + typedef std::uint32_t udword; + typedef std::int64_t sqword; + typedef std::uint64_t uqword; + typedef float float32; + typedef double float64; + + ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 ! + ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1); + ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1); + ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2); + ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2); + ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4); + ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4); + ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8); + ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8); + ICE_COMPILE_TIME_ASSERT(sizeof(float32)==4); + ICE_COMPILE_TIME_ASSERT(sizeof(float64)==8); + + //! TO BE DOCUMENTED + #define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name + + typedef udword DynID; //!< Dynamic identifier +#ifdef USE_HANDLE_MANAGER + typedef udword KID; //!< Kernel ID +// DECLARE_ICE_HANDLE(KID); +#else + typedef uword KID; //!< Kernel ID +#endif + typedef udword RTYPE; //!< Relationship-type (!) between owners and references + #define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers) +#ifdef USE_HANDLE_MANAGER + #define INVALID_KID 0xffffffff //!< Invalid Kernel ID +#else + #define INVALID_KID 0xffff //!< Invalid Kernel ID +#endif + #define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value + + // Define BOOL if needed + #ifndef BOOL + typedef int BOOL; //!< Another boolean type. + #endif + + //! Union of a float and a sdword + typedef union { + float f; //!< The float + sdword d; //!< The integer + }scell; + + //! Union of a float and a udword + typedef union { + float f; //!< The float + udword d; //!< The integer + }ucell; + + // Type ranges + #define MAX_SBYTE 0x7f //!< max possible sbyte value + #define MIN_SBYTE 0x80 //!< min possible sbyte value + #define MAX_UBYTE 0xff //!< max possible ubyte value + #define MIN_UBYTE 0x00 //!< min possible ubyte value + #define MAX_SWORD 0x7fff //!< max possible sword value + #define MIN_SWORD 0x8000 //!< min possible sword value + #define MAX_UWORD 0xffff //!< max possible uword value + #define MIN_UWORD 0x0000 //!< min possible uword value + #define MAX_SDWORD 0x7fffffff //!< max possible sdword value + #define MIN_SDWORD 0x80000000 //!< min possible sdword value + #define MAX_UDWORD 0xffffffff //!< max possible udword value + #define MIN_UDWORD 0x00000000 //!< min possible udword value + #define MAX_FLOAT FLT_MAX //!< max possible float value + #define MIN_FLOAT (-FLT_MAX) //!< min possible loat value + #define IEEE_1_0 0x3f800000 //!< integer representation of 1.0 + #define IEEE_255_0 0x437f0000 //!< integer representation of 255.0 + #define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT + #define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT + #define IEEE_UNDERFLOW_LIMIT 0x1a000000 + + #define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand() + #ifndef WIN32 + #define __stdcall + #endif + + typedef int (__stdcall* PROC)(); //!< A standard procedure call. + typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call + typedef void** VTABLE; //!< A V-Table. + + #undef MIN + #undef MAX + #define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b + #define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b + #define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c + + template inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; } + template inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; } + template inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; } + template inline_ void TSetMax (T& a, const T& b) { if(a> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa); + n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc); + n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0); + n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); + n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); + // Etc for larger intergers (64 bits in Java) + // NOTE: the >> operation must be unsigned! (>>> in java) + } + + //! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection) + inline_ udword CountBits(udword n) + { + // This relies of the fact that the count of n bits can NOT overflow + // an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts + // 2 bit interger, 3 bit count requires only a 2 bit interger. + // So we add all bit pairs, then each nible, then each byte etc... + n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1); + n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2); + n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4); + n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8); + n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16); + // Etc for larger intergers (64 bits in Java) + // NOTE: the >> operation must be unsigned! (>>> in java) + return n; + } + + //! Even faster? + inline_ udword CountBits2(udword bits) + { + bits = bits - ((bits >> 1) & 0x55555555); + bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333); + bits = ((bits >> 4) + bits) & 0x0F0F0F0F; + return (bits * 0x01010101) >> 24; + } + + //! Spread out bits. EG 00001111 -> 0101010101 + //! 00001010 -> 0100010000 + //! This is used to interleve to intergers to produce a `Morten Key' + //! used in Space Filling Curves (See DrDobbs Journal, July 1999) + //! Order is important. + inline_ void SpreadBits(udword& n) + { + n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16); + n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8); + n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4); + n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2); + n = ( n & 0x11111111) | (( n & 0x22222222) << 1); + } + + // Next Largest Power of 2 + // Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm + // that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with + // the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next + // largest power of 2. For a 32-bit value: + inline_ udword nlpo2(udword x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x+1; + } + + //! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection) + inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); } + + //! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection) + inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); } + + //! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection) + inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<> 31; return (x^y)-y; } + + //!< Alternative min function + inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); } + + // Determine if one of the bytes in a 4 byte word is zero + inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); } + + // To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0 + inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); } +// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); } + + // Most Significant 1 Bit + // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set) + // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits. + // This process yields a bit vector with the same most significant 1 as x, but all 1's below it. + // Bitwise AND of the original value with the complement of the "folded" value shifted down by one + // yields the most significant bit. For a 32-bit value: + inline_ udword msb32(udword x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return (x & ~(x >> 1)); + } + + /* + "Just call it repeatedly with various input values and always with the same variable as "memory". + The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1 + does no filtering at all. + + I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed + to the more typical FIR (Finite Impulse Response). + + Also, I'd say that you can make more intelligent and interesting filters than this, for example filters + that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter + to be applied before this one, of course." + + (JCAB on Flipcode) + */ + inline_ float FeedbackFilter(float val, float& memory, float sharpness) + { + ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter"); + if(sharpness<0.0f) sharpness = 0.0f; + else if(sharpness>1.0f) sharpness = 1.0f; + return memory = val * sharpness + memory * (1.0f - sharpness); + } + + //! If you can guarantee that your input domain (i.e. value of x) is slightly + //! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the + //! following code to clamp the resulting value into [-32768,+32767] range: + inline_ int ClampToInt16(int x) + { +// ASSERT(abs(x) < (int)((1<<31u)-32767)); + + int delta = 32767 - x; + x += (delta>>31) & delta; + delta = x + 32768; + x -= (delta>>31) & delta; + return x; + } + + // Generic functions + template inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; } + template inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((xhi) ? hi : x); } + + template inline_ void TSort(Type& a, Type& b) + { + if(a>b) TSwap(a, b); + } + + template inline_ void TSort(Type& a, Type& b, Type& c) + { + if(a>b) TSwap(a, b); + if(b>c) TSwap(b, c); + if(a>b) TSwap(a, b); + if(b>c) TSwap(b, c); + } + + // Prevent nasty user-manipulations (strategy borrowed from Charles Bloom) +// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); } + // ... actually this is better ! + #define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object); + + //! TO BE DOCUMENTED + #define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member) + //! TO BE DOCUMENTED + #define ICEARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns the alignment of the input address. + * \fn Alignment() + * \param address [in] address to check + * \return the best alignment (e.g. 1 for odd addresses, etc) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + FUNCTION ICECORE_API udword Alignment(udword address); + + #define IS_ALIGNED_2(x) ((x&1)==0) + #define IS_ALIGNED_4(x) ((x&3)==0) + #define IS_ALIGNED_8(x) ((x&7)==0) + + inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; } + + // Compute implicit coords from an index: + // The idea is to get back 2D coords from a 1D index. + // For example: + // + // 0 1 2 ... nbu-1 + // nbu nbu+1 i ... + // + // We have i, we're looking for the equivalent (u=2, v=1) location. + // i = u + v*nbu + // <=> i/nbu = u/nbu + v + // Since 0 <= u < nbu, u/nbu = 0 (integer) + // Hence: v = i/nbu + // Then we simply put it back in the original equation to compute u = i - v*nbu + inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu) + { + v = i / nbu; + u = i - (v * nbu); + } + + // In 3D: i = u + v*nbu + w*nbu*nbv + // <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w + // u/(nbu*nbv) is null since u/nbu was null already. + // v/nbv is null as well for the same reason. + // Hence w = i/(nbu*nbv) + // Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu + inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv) + { + w = i / (nbu_nbv); + Compute2DCoords(u, v, i - (w * nbu_nbv), nbu); + } + +#endif // __ICEUTILS_H__ diff --git a/third-party/Opcode/OPC_AABBCollider.cpp b/third-party/Opcode/OPC_AABBCollider.cpp new file mode 100644 index 0000000..a3cfa62 --- /dev/null +++ b/third-party/Opcode/OPC_AABBCollider.cpp @@ -0,0 +1,696 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an AABB collider. + * \file OPC_AABBCollider.cpp + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an AABB-vs-tree collider. + * + * \class AABBCollider + * \author Pierre Terdiman + * \version 1.3 + * \date January, 1st, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#include "OPC_BoxBoxOverlap.h" +#include "OPC_TriBoxOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! AABB-triangle test +#define AABB_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index);\ + mLeafVerts[0] = *VP.Vertex[0]; \ + mLeafVerts[1] = *VP.Vertex[1]; \ + mLeafVerts[2] = *VP.Vertex[2]; \ + /* Perform triangle-box overlap test */ \ + if(TriBoxOverlap()) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollider::AABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollider::~AABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param model [in] Opcode model to collide with + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const Model& model) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - check temporal coherence + * + * \param cache [in/out] a box cache + * \param box [in] AABB in world space + * \return TRUE if we can return immediately + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL AABBCollider::InitQuery(AABBCache& cache, const CollisionAABB& box) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Keep track of the query box + mBox = box; + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the box (and set contact status if needed) + AABB_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the box (and set contact status if needed) + AABB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): + if(IsCacheValid(cache) && mBox.IsInside(cache.FatBox)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat box so that coherence will work for subsequent frames + mBox.mExtents *= cache.FatCoeff; + + // Update cache with query data (signature for cached faces) + cache.FatBox = mBox; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + // 5) Precompute min & max bounds if needed + mMin = box.mCenter - box.mExtents; + mMax = box.mCenter + box.mExtents; + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the AABB completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the AABB contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBCollider::AABBContainsBox(const IcePoint& bc, const IcePoint& be) +{ + if(mMin.x > bc.x - be.x) return FALSE; + if(mMin.y > bc.y - be.y) return FALSE; + if(mMin.z > bc.z - be.z) return FALSE; + + if(mMax.x < bc.x + be.x) return FALSE; + if(mMax.y < bc.y + be.y) return FALSE; + if(mMax.z < bc.z + be.z) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_AABB(center, extents) \ + if(AABBContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->IsLeaf()) + { + AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBTreeNode* node) +{ + // Perform AABB-AABB overlap test + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!AABBAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || AABBContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridAABBCollider::HybridAABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridAABBCollider::~HybridAABBCollider() +{ +} + +bool HybridAABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + AABB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + AABB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/third-party/Opcode/OPC_AABBCollider.h b/third-party/Opcode/OPC_AABBCollider.h new file mode 100644 index 0000000..c792b44 --- /dev/null +++ b/third-party/Opcode/OPC_AABBCollider.h @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an AABB collider. + * \file OPC_AABBCollider.h + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_AABBCOLLIDER_H__ +#define __OPC_AABBCOLLIDER_H__ + + struct OPCODE_API AABBCache : VolumeCache + { + AABBCache() : FatCoeff(1.1f) + { + FatBox.mCenter.Zero(); + FatBox.mExtents.Zero(); + } + + // Cached faces signature + CollisionAABB FatBox; //!< Box used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere + }; + + class OPCODE_API AABBCollider : public VolumeCollider + { + public: + // Constructor / Destructor + AABBCollider(); + virtual ~AABBCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param model [in] Opcode model to collide with + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(AABBCache& cache, const CollisionAABB& box, const Model& model); + // + bool Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree); + protected: + CollisionAABB mBox; //!< Query box in (center, extents) form + IcePoint mMin; //!< Query box min IcePoint + IcePoint mMax; //!< Query box max IcePoint + // Leaf description + IcePoint mLeafVerts[3]; //!< Triangle vertices + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL AABBContainsBox(const IcePoint& bc, const IcePoint& be); + inline_ BOOL AABBAABBOverlap(const IcePoint& b, const IcePoint& Pb); + inline_ BOOL TriBoxOverlap(); + // Init methods + BOOL InitQuery(AABBCache& cache, const CollisionAABB& box); + }; + + class OPCODE_API HybridAABBCollider : public AABBCollider + { + public: + // Constructor / Destructor + HybridAABBCollider(); + virtual ~HybridAABBCollider(); + + bool Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_AABBCOLLIDER_H__ diff --git a/third-party/Opcode/OPC_AABBTree.cpp b/third-party/Opcode/OPC_AABBTree.cpp new file mode 100644 index 0000000..bc1a4e0 --- /dev/null +++ b/third-party/Opcode/OPC_AABBTree.cpp @@ -0,0 +1,573 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a versatile AABB tree. + * \file OPC_AABBTree.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a generic AABB tree node. + * + * \class AABBTreeNode + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a generic AABB tree. + * This is a vanilla AABB tree, without any particular optimization. It contains anonymous references to + * user-provided primitives, which can theoretically be anything - triangles, boxes, etc. Each primitive + * is surrounded by an AABB, regardless of the primitive's nature. When the primitive is a triangle, the + * resulting tree can be converted into an optimized tree. If the primitive is a box, the resulting tree + * can be used for culling - VFC or occlusion -, assuming you cull on a mesh-by-mesh basis (modern way). + * + * \class AABBTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTreeNode::AABBTreeNode() : + mPos (null), +#ifndef OPC_NO_NEG_VANILLA_TREE + mNeg (null), +#endif + mNbPrimitives (0), + mNodePrimitives (null) +{ +#ifdef OPC_USE_TREE_COHERENCE + mBitmask = 0; +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTreeNode::~AABBTreeNode() +{ + // Opcode 1.3: + const AABBTreeNode* Pos = GetPos(); + const AABBTreeNode* Neg = GetNeg(); +#ifndef OPC_NO_NEG_VANILLA_TREE + if(!(mPos&1)) DELETESINGLE(Pos); + if(!(mNeg&1)) DELETESINGLE(Neg); +#else + if(!(mPos&1)) DELETEARRAY(Pos); +#endif + mNodePrimitives = null; // This was just a shortcut to the global list => no release + mNbPrimitives = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Splits the node along a given axis. + * The list of indices is reorganized according to the split values. + * \param axis [in] splitting axis index + * \param builder [in] the tree builder + * \return the number of primitives assigned to the first child + * \warning this method reorganizes the internal list of primitives + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTreeNode::Split(udword axis, AABBTreeBuilder* builder) +{ + // Get node split value + float SplitValue = builder->GetSplittingValue(mNodePrimitives, mNbPrimitives, mBV, axis); + + udword NbPos = 0; + // Loop through all node-related primitives. Their indices range from mNodePrimitives[0] to mNodePrimitives[mNbPrimitives-1]. + // Those indices map the global list in the tree builder. + for(udword i=0;iGetSplittingValue(Index, axis); + + // Reorganize the list of indices in this order: positive - negative. + if(PrimitiveValue > SplitValue) + { + // Swap entries + udword Tmp = mNodePrimitives[i]; + mNodePrimitives[i] = mNodePrimitives[NbPos]; + mNodePrimitives[NbPos] = Tmp; + // Count primitives assigned to positive space + NbPos++; + } + } + return NbPos; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Subdivides the node. + * + * N + * / \ + * / \ + * N/2 N/2 + * / \ / \ + * N/4 N/4 N/4 N/4 + * (etc) + * + * A well-balanced tree should have a O(log n) depth. + * A degenerate tree would have a O(n) depth. + * Note a perfectly-balanced tree is not well-suited to collision detection anyway. + * + * \param builder [in] the tree builder + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeNode::Subdivide(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder) return false; + + // Stop subdividing if we reach a leaf node. This is always performed here, + // else we could end in trouble if user overrides this. + if(mNbPrimitives==1) return true; + + // Let the user validate the subdivision + if(!builder->ValidateSubdivision(mNodePrimitives, mNbPrimitives, mBV)) return true; + + bool ValidSplit = true; // Optimism... + udword NbPos; + if(builder->mSettings.mRules & SPLIT_LARGEST_AXIS) + { + // Find the largest axis to split along + IcePoint Extents; mBV.GetExtents(Extents); // Box extents + udword Axis = Extents.LargestAxis(); // Index of largest axis + + // Split along the axis + NbPos = Split(Axis, builder); + + // Check split validity + if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; + } + else if(builder->mSettings.mRules & SPLIT_SPLATTER_POINTS) + { + // Compute the means + IcePoint Means(0.0f, 0.0f, 0.0f); + for(udword i=0;iGetSplittingValue(Index, 0); + Means.y+=builder->GetSplittingValue(Index, 1); + Means.z+=builder->GetSplittingValue(Index, 2); + } + Means/=float(mNbPrimitives); + + // Compute variances + IcePoint Vars(0.0f, 0.0f, 0.0f); + for(udword i=0;iGetSplittingValue(Index, 0); + float Cy = builder->GetSplittingValue(Index, 1); + float Cz = builder->GetSplittingValue(Index, 2); + Vars.x += (Cx - Means.x)*(Cx - Means.x); + Vars.y += (Cy - Means.y)*(Cy - Means.y); + Vars.z += (Cz - Means.z)*(Cz - Means.z); + } + Vars/=float(mNbPrimitives-1); + + // Choose axis with greatest variance + udword Axis = Vars.LargestAxis(); + + // Split along the axis + NbPos = Split(Axis, builder); + + // Check split validity + if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; + } + else if(builder->mSettings.mRules & SPLIT_BALANCED) + { + // Test 3 axis, take the best + float Results[3]; + NbPos = Split(0, builder); Results[0] = float(NbPos)/float(mNbPrimitives); + NbPos = Split(1, builder); Results[1] = float(NbPos)/float(mNbPrimitives); + NbPos = Split(2, builder); Results[2] = float(NbPos)/float(mNbPrimitives); + Results[0]-=0.5f; Results[0]*=Results[0]; + Results[1]-=0.5f; Results[1]*=Results[1]; + Results[2]-=0.5f; Results[2]*=Results[2]; + udword Min=0; + if(Results[1]mSettings.mRules & SPLIT_BEST_AXIS) + { + // Test largest, then middle, then smallest axis... + + // Sort axis + IcePoint Extents; mBV.GetExtents(Extents); // Box extents + udword SortedAxis[] = { 0, 1, 2 }; + float* Keys = (float*)&Extents.x; + for(udword j=0;j<3;j++) + { + for(udword i=0;i<2;i++) + { + if(Keys[SortedAxis[i]]mSettings.mRules & SPLIT_FIFTY) + { + // Don't even bother splitting (mainly a performance test) + NbPos = mNbPrimitives>>1; + } + else return false; // Unknown splitting rules + + // Check the subdivision has been successful + if(!ValidSplit) + { + // Here, all boxes lie in the same sub-space. Two strategies: + // - if the tree *must* be complete, make an arbitrary 50-50 split + // - else stop subdividing +// if(builder->mSettings.mRules&SPLIT_COMPLETE) + if(builder->mSettings.mLimit==1) + { + builder->IncreaseNbInvalidSplits(); + NbPos = mNbPrimitives>>1; + } + else return true; + } + + // Now create children and assign their pointers. + if(builder->mNodeBase) + { + // We use a pre-allocated linear pool for complete trees [Opcode 1.3] + AABBTreeNode* Pool = (AABBTreeNode*)builder->mNodeBase; + udword Count = builder->GetCount() - 1; // Count begins to 1... + // Set last bit to tell it shouldn't be freed ### pretty ugly, find a better way. Maybe one bit in mNbPrimitives + ASSERT(!(udword(&Pool[Count+0])&1)); + ASSERT(!(udword(&Pool[Count+1])&1)); + mPos = udword(&Pool[Count+0])|1; +#ifndef OPC_NO_NEG_VANILLA_TREE + mNeg = udword(&Pool[Count+1])|1; +#endif + } + else + { + // Non-complete trees and/or Opcode 1.2 allocate nodes on-the-fly +#ifndef OPC_NO_NEG_VANILLA_TREE + mPos = (udword)new AABBTreeNode; CHECKALLOC(mPos); + mNeg = (udword)new AABBTreeNode; CHECKALLOC(mNeg); +#else + AABBTreeNode* PosNeg = new AABBTreeNode[2]; + CHECKALLOC(PosNeg); + mPos = (udword)PosNeg; +#endif + } + + // Update stats + builder->IncreaseCount(2); + + // Assign children + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + Pos->mNodePrimitives = &mNodePrimitives[0]; + Pos->mNbPrimitives = NbPos; + Neg->mNodePrimitives = &mNodePrimitives[NbPos]; + Neg->mNbPrimitives = mNbPrimitives - NbPos; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive hierarchy building in a top-down fashion. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeNode::_BuildHierarchy(AABBTreeBuilder* builder) +{ + // 1) Compute the global box for current node. The box is stored in mBV. + builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); + + // 2) Subdivide current node + Subdivide(builder); + + // 3) Recurse + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + if(Pos) Pos->_BuildHierarchy(builder); + if(Neg) Neg->_BuildHierarchy(builder); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree (top-down). + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeNode::_Refit(AABBTreeBuilder* builder) +{ + // 1) Recompute the new global box for current node + builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); + + // 2) Recurse + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + if(Pos) Pos->_Refit(builder); + if(Neg) Neg->_Refit(builder); +} + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTree::AABBTree() : mIndices(null), mTotalNbNodes(0), mPool(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTree::~AABBTree() +{ + Release(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases the tree. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTree::Release() +{ + DELETEARRAY(mPool); + DELETEARRAY(mIndices); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a generic AABB tree from a tree builder. + * \param builder [in] the tree builder + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Build(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder || !builder->mNbPrimitives) return false; + + // Release previous tree + Release(); + + // Init stats + builder->SetCount(1); + builder->SetNbInvalidSplits(0); + + // Initialize indices. This list will be modified during build. + mIndices = new udword[builder->mNbPrimitives]; + CHECKALLOC(mIndices); + // Identity permutation + for(udword i=0;imNbPrimitives;i++) mIndices[i] = i; + + // Setup initial node. Here we have a complete permutation of the app's primitives. + mNodePrimitives = mIndices; + mNbPrimitives = builder->mNbPrimitives; + + // Use a linear array for complete trees (since we can predict the final number of nodes) [Opcode 1.3] +// if(builder->mRules&SPLIT_COMPLETE) + if(builder->mSettings.mLimit==1) + { + // Allocate a pool of nodes + mPool = new AABBTreeNode[builder->mNbPrimitives*2 - 1]; + + builder->mNodeBase = mPool; // ### ugly ! + } + + // Build the hierarchy + _BuildHierarchy(builder); + + // Get back total number of nodes + mTotalNbNodes = builder->GetCount(); + + // For complete trees, check the correct number of nodes has been created [Opcode 1.3] + if(mPool) ASSERT(mTotalNbNodes==builder->mNbPrimitives*2 - 1); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the depth of the tree. + * A well-balanced tree should have a log(n) depth. A degenerate tree O(n) depth. + * \return depth of the tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::ComputeDepth() const +{ + return Walk(null, null); // Use the walking code without callback +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree, calling the user back for each node. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::Walk(WalkingCallback callback, void* user_data) const +{ + // Call it without callback to compute max depth + udword MaxDepth = 0; + udword CurrentDepth = 0; + + struct Local + { + static void _Walk(const AABBTreeNode* current_node, udword& max_depth, udword& current_depth, WalkingCallback callback, void* user_data) + { + // Checkings + if(!current_node) return; + // Entering a new node => increase depth + current_depth++; + // Keep track of max depth + if(current_depth>max_depth) max_depth = current_depth; + + // Callback + if(callback && !(callback)(current_node, current_depth, user_data)) return; + + // Recurse + if(current_node->GetPos()) { _Walk(current_node->GetPos(), max_depth, current_depth, callback, user_data); current_depth--; } + if(current_node->GetNeg()) { _Walk(current_node->GetNeg(), max_depth, current_depth, callback, user_data); current_depth--; } + } + }; + Local::_Walk(this, MaxDepth, CurrentDepth, callback, user_data); + return MaxDepth; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree in a top-down way. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Refit(AABBTreeBuilder* builder) +{ + if(!builder) return false; + _Refit(builder); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree in a bottom-up way. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Refit2(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder) return false; + + ASSERT(mPool); + + // Bottom-up update + IcePoint Min,Max; + IcePoint Min_,Max_; + udword Index = mTotalNbNodes; + while(Index--) + { + AABBTreeNode& Current = mPool[Index]; + + if(Current.IsLeaf()) + { + builder->ComputeGlobalBox(Current.GetPrimitives(), Current.GetNbPrimitives(), *(AABB*)Current.GetAABB()); + } + else + { + Current.GetPos()->GetAABB()->GetMin(Min); + Current.GetPos()->GetAABB()->GetMax(Max); + + Current.GetNeg()->GetAABB()->GetMin(Min_); + Current.GetNeg()->GetAABB()->GetMax(Max_); + + Min.Min(Min_); + Max.Max(Max_); + + ((AABB*)Current.GetAABB())->SetMinMax(Min, Max); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the number of bytes used by the tree. + * \return number of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::GetUsedBytes() const +{ + udword TotalSize = mTotalNbNodes*GetNodeSize(); + if(mIndices) TotalSize+=mNbPrimitives*sizeof(udword); + return TotalSize; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the tree is a complete tree or not. + * A complete tree is made of 2*N-1 nodes, where N is the number of primitives in the tree. + * \return true for complete trees + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::IsComplete() const +{ + return (GetNbNodes()==GetNbPrimitives()*2-1); +} diff --git a/third-party/Opcode/OPC_AABBTree.h b/third-party/Opcode/OPC_AABBTree.h new file mode 100644 index 0000000..298f482 --- /dev/null +++ b/third-party/Opcode/OPC_AABBTree.h @@ -0,0 +1,137 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a versatile AABB tree. + * \file OPC_AABBTree.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_AABBTREE_H__ +#define __OPC_AABBTREE_H__ + +#ifdef OPC_NO_NEG_VANILLA_TREE + //! TO BE DOCUMENTED + #define IMPLEMENT_TREE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + ~base_class(); \ + /* Data access */ \ + inline_ const volume* Get##volume() const { return &mBV; } \ + /* Clear the last bit */ \ + inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \ + inline_ const base_class* GetNeg() const { const base_class* P = GetPos(); return P ? P+1 : null;} \ + \ + /* We don't need to test both nodes since we can't have one without the other */ \ + inline_ bool IsLeaf() const { return !GetPos(); } \ + \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + protected: \ + /* Tree-independent data */ \ + /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \ + /* Whatever happens we need the two children and the enclosing volume.*/ \ + volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \ + udword mPos; /* "Positive" & "Negative" children */ +#else + //! TO BE DOCUMENTED + #define IMPLEMENT_TREE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + ~base_class(); \ + /* Data access */ \ + inline_ const volume* Get##volume() const { return &mBV; } \ + /* Clear the last bit */ \ + inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \ + inline_ const base_class* GetNeg() const { return (const base_class*)(mNeg&~1); } \ + \ +/* inline_ bool IsLeaf() const { return (!GetPos() && !GetNeg()); } */ \ + /* We don't need to test both nodes since we can't have one without the other */ \ + inline_ bool IsLeaf() const { return !GetPos(); } \ + \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + protected: \ + /* Tree-independent data */ \ + /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \ + /* Whatever happens we need the two children and the enclosing volume.*/ \ + volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \ + udword mPos; /* "Positive" child */ \ + udword mNeg; /* "Negative" child */ +#endif + + typedef void (*CullingCallback) (udword nb_primitives, udword* node_primitives, BOOL need_clipping, void* user_data); + + class OPCODE_API AABBTreeNode + { + IMPLEMENT_TREE(AABBTreeNode, AABB) + public: + // Data access + inline_ const udword* GetPrimitives() const { return mNodePrimitives; } + inline_ udword GetNbPrimitives() const { return mNbPrimitives; } + + protected: + // Tree-dependent data + udword* mNodePrimitives; //!< Node-related primitives (shortcut to a position in mIndices below) + udword mNbPrimitives; //!< Number of primitives for this node + // Internal methods + udword Split(udword axis, AABBTreeBuilder* builder); + bool Subdivide(AABBTreeBuilder* builder); + void _BuildHierarchy(AABBTreeBuilder* builder); + void _Refit(AABBTreeBuilder* builder); + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called for each node by the walking code. + * \param current [in] current node + * \param depth [in] current node's depth + * \param user_data [in] user-defined data + * \return true to recurse through children, else false to bypass them + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef bool (*WalkingCallback) (const AABBTreeNode* current, udword depth, void* user_data); + + class OPCODE_API AABBTree : public AABBTreeNode + { + public: + // Constructor / Destructor + AABBTree(); + ~AABBTree(); + // Build + bool Build(AABBTreeBuilder* builder); + void Release(); + + // Data access + inline_ const udword* GetIndices() const { return mIndices; } //!< Catch the indices + inline_ udword GetNbNodes() const { return mTotalNbNodes; } //!< Catch the number of nodes + + // Infos + bool IsComplete() const; + // Stats + udword ComputeDepth() const; + udword GetUsedBytes() const; + udword Walk(WalkingCallback callback, void* user_data) const; + + bool Refit(AABBTreeBuilder* builder); + bool Refit2(AABBTreeBuilder* builder); + private: + udword* mIndices; //!< Indices in the app list. Indices are reorganized during build (permutation). + AABBTreeNode* mPool; //!< Linear pool of nodes for complete trees. Null otherwise. [Opcode 1.3] + // Stats + udword mTotalNbNodes; //!< Number of nodes in the tree. + }; + +#endif // __OPC_AABBTREE_H__ diff --git a/third-party/Opcode/OPC_BaseModel.cpp b/third-party/Opcode/OPC_BaseModel.cpp new file mode 100644 index 0000000..88b6a69 --- /dev/null +++ b/third-party/Opcode/OPC_BaseModel.cpp @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base model interface. + * \file OPC_BaseModel.cpp + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * The base class for collision models. + * + * \class BaseModel + * \author Pierre Terdiman + * \version 1.3 + * \date May, 18, 2003 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OPCODECREATE::OPCODECREATE() +{ + mIMesh = null; + mSettings.mRules = SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER; + mSettings.mLimit = 1; // Mandatory for complete trees + mNoLeaf = true; + mQuantized = true; +#ifdef __MESHMERIZER_H__ + mCollisionHull = false; +#endif // __MESHMERIZER_H__ + mKeepOriginal = false; + mCanRemap = false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BaseModel::BaseModel() : mIMesh(null), mModelCode(0), mSource(null), mTree(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BaseModel::~BaseModel() +{ + ReleaseBase(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases everything. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void BaseModel::ReleaseBase() +{ + DELETESINGLE(mSource); + DELETESINGLE(mTree); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates an optimized tree according to user-settings, and setups mModelCode. + * \param no_leaf [in] true for "no leaf" tree + * \param quantized [in] true for quantized tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BaseModel::CreateTree(bool no_leaf, bool quantized) +{ + DELETESINGLE(mTree); + + // Setup model code + if(no_leaf) mModelCode |= OPC_NO_LEAF; + else mModelCode &= ~OPC_NO_LEAF; + + if(quantized) mModelCode |= OPC_QUANTIZED; + else mModelCode &= ~OPC_QUANTIZED; + + // Create the correct class + if(mModelCode & OPC_NO_LEAF) + { + if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedNoLeafTree; + else mTree = new AABBNoLeafTree; + } + else + { + if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedTree; + else mTree = new AABBCollisionTree; + } + CHECKALLOC(mTree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BaseModel::Refit() +{ + // Refit the optimized tree + return mTree->Refit(mIMesh); + +// Old code kept for reference : refit the source tree then rebuild ! +// if(!mSource) return false; +// // Ouch... +// mSource->Refit(&mTB); +// // Ouch... +// return mTree->Build(mSource); +} diff --git a/third-party/Opcode/OPC_BaseModel.h b/third-party/Opcode/OPC_BaseModel.h new file mode 100644 index 0000000..3c2e58c --- /dev/null +++ b/third-party/Opcode/OPC_BaseModel.h @@ -0,0 +1,175 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base model interface. + * \file OPC_BaseModel.h + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_BASEMODEL_H__ +#define __OPC_BASEMODEL_H__ + + //! Model creation structure + struct OPCODE_API OPCODECREATE + { + //! Constructor + OPCODECREATE(); + + MeshInterface* mIMesh; //!< Mesh interface (access to triangles & vertices) (*) + BuildSettings mSettings; //!< Builder's settings + bool mNoLeaf; //!< true => discard leaf nodes (else use a normal tree) + bool mQuantized; //!< true => quantize the tree (else use a normal tree) +#ifdef __MESHMERIZER_H__ + bool mCollisionHull; //!< true => use convex hull + GJK +#endif // __MESHMERIZER_H__ + bool mKeepOriginal; //!< true => keep a copy of the original tree (debug purpose) + bool mCanRemap; //!< true => allows OPCODE to reorganize client arrays + + // (*) This pointer is saved internally and used by OPCODE until collision structures are released, + // so beware of the object's lifetime. + }; + + enum ModelFlag + { + OPC_QUANTIZED = (1<<0), //!< Compressed/uncompressed tree + OPC_NO_LEAF = (1<<1), //!< Leaf/NoLeaf tree + OPC_SINGLE_NODE = (1<<2) //!< Special case for 1-node models + }; + + class OPCODE_API BaseModel + { + public: + // Constructor/Destructor + BaseModel(); + virtual ~BaseModel(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Build(const OPCODECREATE& create) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual udword GetUsedBytes() const = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Refit(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the source tree. + * \return generic tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const AABBTree* GetSourceTree() const { return mSource; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the tree. + * \return the collision tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const AABBOptimizedTree* GetTree() const { return mTree; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the tree. + * \return the collision tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ AABBOptimizedTree* GetTree() { return mTree; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of nodes in the tree. + * Should be 2*N-1 for normal trees and N-1 for optimized ones. + * \return number of nodes + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbNodes() const { return mTree->GetNbNodes(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the tree has leaf nodes or not. + * \return true if the tree has leaf nodes (normal tree), else false (optimized tree) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL HasLeafNodes() const { return !(mModelCode & OPC_NO_LEAF); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the tree is quantized or not. + * \return true if the tree is quantized + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsQuantized() const { return mModelCode & OPC_QUANTIZED; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the model has a single node or not. This special case must be handled separately. + * \return true if the model has only 1 node + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL HasSingleNode() const { return mModelCode & OPC_SINGLE_NODE; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the model's code. + * \return model's code + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetModelCode() const { return mModelCode; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the mesh interface. + * \return mesh interface + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const MeshInterface* GetMeshInterface() const { return mIMesh; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Sets the mesh interface. + * \param imesh [in] mesh interface + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMeshInterface(const MeshInterface* imesh) { mIMesh = imesh; } + + protected: + const MeshInterface* mIMesh; //!< User-defined mesh interface + udword mModelCode; //!< Model code = combination of ModelFlag(s) + AABBTree* mSource; //!< Original source tree + AABBOptimizedTree* mTree; //!< Optimized tree owned by the model + // Internal methods + void ReleaseBase(); + bool CreateTree(bool no_leaf, bool quantized); + }; + +#endif //__OPC_BASEMODEL_H__ \ No newline at end of file diff --git a/third-party/Opcode/OPC_BoxBoxOverlap.h b/third-party/Opcode/OPC_BoxBoxOverlap.h new file mode 100644 index 0000000..78a7675 --- /dev/null +++ b/third-party/Opcode/OPC_BoxBoxOverlap.h @@ -0,0 +1,122 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * OBB-OBB overlap test using the separating axis theorem. + * - original code by Gomez / Gamasutra (similar to Gottschalk's one in RAPID) + * - optimized for AABB trees by computing the rotation matrix once (SOLID-fashion) + * - the fabs matrix is precomputed as well and epsilon-tweaked (RAPID-style, we found this almost mandatory) + * - Class III axes can be disabled... (SOLID & Intel fashion) + * - ...or enabled to perform some profiling + * - CPU comparisons used when appropriate + * - lazy evaluation sometimes saves some work in case of early exits (unlike SOLID) + * + * \param ea [in] extents from box A + * \param ca [in] center from box A + * \param eb [in] extents from box B + * \param cb [in] center from box B + * \return true if boxes overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::BoxBoxOverlap(const IcePoint& ea, const IcePoint& ca, const IcePoint& eb, const IcePoint& cb) +{ + // Stats + mNbBVBVTests++; + + float t,t2; + + // Class I : A's basis vectors + float Tx = (mR1to0.m[0][0]*cb.x + mR1to0.m[1][0]*cb.y + mR1to0.m[2][0]*cb.z) + mT1to0.x - ca.x; + t = ea.x + eb.x*mAR.m[0][0] + eb.y*mAR.m[1][0] + eb.z*mAR.m[2][0]; + if(GREATER(Tx, t)) return FALSE; + + float Ty = (mR1to0.m[0][1]*cb.x + mR1to0.m[1][1]*cb.y + mR1to0.m[2][1]*cb.z) + mT1to0.y - ca.y; + t = ea.y + eb.x*mAR.m[0][1] + eb.y*mAR.m[1][1] + eb.z*mAR.m[2][1]; + if(GREATER(Ty, t)) return FALSE; + + float Tz = (mR1to0.m[0][2]*cb.x + mR1to0.m[1][2]*cb.y + mR1to0.m[2][2]*cb.z) + mT1to0.z - ca.z; + t = ea.z + eb.x*mAR.m[0][2] + eb.y*mAR.m[1][2] + eb.z*mAR.m[2][2]; + if(GREATER(Tz, t)) return FALSE; + + // Class II : B's basis vectors + t = Tx*mR1to0.m[0][0] + Ty*mR1to0.m[0][1] + Tz*mR1to0.m[0][2]; t2 = ea.x*mAR.m[0][0] + ea.y*mAR.m[0][1] + ea.z*mAR.m[0][2] + eb.x; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mR1to0.m[1][0] + Ty*mR1to0.m[1][1] + Tz*mR1to0.m[1][2]; t2 = ea.x*mAR.m[1][0] + ea.y*mAR.m[1][1] + ea.z*mAR.m[1][2] + eb.y; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mR1to0.m[2][0] + Ty*mR1to0.m[2][1] + Tz*mR1to0.m[2][2]; t2 = ea.x*mAR.m[2][0] + ea.y*mAR.m[2][1] + ea.z*mAR.m[2][2] + eb.z; + if(GREATER(t, t2)) return FALSE; + + // Class III : 9 cross products + // Cool trick: always perform the full test for first level, regardless of settings. + // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! + if(mFullBoxBoxTest || mNbBVBVTests==1) + { + t = Tz*mR1to0.m[0][1] - Ty*mR1to0.m[0][2]; t2 = ea.y*mAR.m[0][2] + ea.z*mAR.m[0][1] + eb.y*mAR.m[2][0] + eb.z*mAR.m[1][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 + t = Tz*mR1to0.m[1][1] - Ty*mR1to0.m[1][2]; t2 = ea.y*mAR.m[1][2] + ea.z*mAR.m[1][1] + eb.x*mAR.m[2][0] + eb.z*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 + t = Tz*mR1to0.m[2][1] - Ty*mR1to0.m[2][2]; t2 = ea.y*mAR.m[2][2] + ea.z*mAR.m[2][1] + eb.x*mAR.m[1][0] + eb.y*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 + t = Tx*mR1to0.m[0][2] - Tz*mR1to0.m[0][0]; t2 = ea.x*mAR.m[0][2] + ea.z*mAR.m[0][0] + eb.y*mAR.m[2][1] + eb.z*mAR.m[1][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 + t = Tx*mR1to0.m[1][2] - Tz*mR1to0.m[1][0]; t2 = ea.x*mAR.m[1][2] + ea.z*mAR.m[1][0] + eb.x*mAR.m[2][1] + eb.z*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 + t = Tx*mR1to0.m[2][2] - Tz*mR1to0.m[2][0]; t2 = ea.x*mAR.m[2][2] + ea.z*mAR.m[2][0] + eb.x*mAR.m[1][1] + eb.y*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 + t = Ty*mR1to0.m[0][0] - Tx*mR1to0.m[0][1]; t2 = ea.x*mAR.m[0][1] + ea.y*mAR.m[0][0] + eb.y*mAR.m[2][2] + eb.z*mAR.m[1][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 + t = Ty*mR1to0.m[1][0] - Tx*mR1to0.m[1][1]; t2 = ea.x*mAR.m[1][1] + ea.y*mAR.m[1][0] + eb.x*mAR.m[2][2] + eb.z*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 + t = Ty*mR1to0.m[2][0] - Tx*mR1to0.m[2][1]; t2 = ea.x*mAR.m[2][1] + ea.y*mAR.m[2][0] + eb.x*mAR.m[1][2] + eb.y*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 + } + return TRUE; +} + +//! A dedicated version when one box is constant +inline_ BOOL OBBCollider::BoxBoxOverlap(const IcePoint& extents, const IcePoint& center) +{ + // Stats + mNbVolumeBVTests++; + + float t,t2; + + // Class I : A's basis vectors + float Tx = mTBoxToModel.x - center.x; t = extents.x + mBBx1; if(GREATER(Tx, t)) return FALSE; + float Ty = mTBoxToModel.y - center.y; t = extents.y + mBBy1; if(GREATER(Ty, t)) return FALSE; + float Tz = mTBoxToModel.z - center.z; t = extents.z + mBBz1; if(GREATER(Tz, t)) return FALSE; + + // Class II : B's basis vectors + t = Tx*mRBoxToModel.m[0][0] + Ty*mRBoxToModel.m[0][1] + Tz*mRBoxToModel.m[0][2]; + t2 = extents.x*mAR.m[0][0] + extents.y*mAR.m[0][1] + extents.z*mAR.m[0][2] + mBoxExtents.x; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mRBoxToModel.m[1][0] + Ty*mRBoxToModel.m[1][1] + Tz*mRBoxToModel.m[1][2]; + t2 = extents.x*mAR.m[1][0] + extents.y*mAR.m[1][1] + extents.z*mAR.m[1][2] + mBoxExtents.y; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mRBoxToModel.m[2][0] + Ty*mRBoxToModel.m[2][1] + Tz*mRBoxToModel.m[2][2]; + t2 = extents.x*mAR.m[2][0] + extents.y*mAR.m[2][1] + extents.z*mAR.m[2][2] + mBoxExtents.z; + if(GREATER(t, t2)) return FALSE; + + // Class III : 9 cross products + // Cool trick: always perform the full test for first level, regardless of settings. + // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! + if(mFullBoxBoxTest || mNbVolumeBVTests==1) + { + t = Tz*mRBoxToModel.m[0][1] - Ty*mRBoxToModel.m[0][2]; t2 = extents.y*mAR.m[0][2] + extents.z*mAR.m[0][1] + mBB_1; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 + t = Tz*mRBoxToModel.m[1][1] - Ty*mRBoxToModel.m[1][2]; t2 = extents.y*mAR.m[1][2] + extents.z*mAR.m[1][1] + mBB_2; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 + t = Tz*mRBoxToModel.m[2][1] - Ty*mRBoxToModel.m[2][2]; t2 = extents.y*mAR.m[2][2] + extents.z*mAR.m[2][1] + mBB_3; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 + t = Tx*mRBoxToModel.m[0][2] - Tz*mRBoxToModel.m[0][0]; t2 = extents.x*mAR.m[0][2] + extents.z*mAR.m[0][0] + mBB_4; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 + t = Tx*mRBoxToModel.m[1][2] - Tz*mRBoxToModel.m[1][0]; t2 = extents.x*mAR.m[1][2] + extents.z*mAR.m[1][0] + mBB_5; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 + t = Tx*mRBoxToModel.m[2][2] - Tz*mRBoxToModel.m[2][0]; t2 = extents.x*mAR.m[2][2] + extents.z*mAR.m[2][0] + mBB_6; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 + t = Ty*mRBoxToModel.m[0][0] - Tx*mRBoxToModel.m[0][1]; t2 = extents.x*mAR.m[0][1] + extents.y*mAR.m[0][0] + mBB_7; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 + t = Ty*mRBoxToModel.m[1][0] - Tx*mRBoxToModel.m[1][1]; t2 = extents.x*mAR.m[1][1] + extents.y*mAR.m[1][0] + mBB_8; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 + t = Ty*mRBoxToModel.m[2][0] - Tx*mRBoxToModel.m[2][1]; t2 = extents.x*mAR.m[2][1] + extents.y*mAR.m[2][0] + mBB_9; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 + } + return TRUE; +} + +//! A special version for 2 axis-aligned boxes +inline_ BOOL AABBCollider::AABBAABBOverlap(const IcePoint& extents, const IcePoint& center) +{ + // Stats + mNbVolumeBVTests++; + + float tx = mBox.mCenter.x - center.x; float ex = extents.x + mBox.mExtents.x; if(GREATER(tx, ex)) return FALSE; + float ty = mBox.mCenter.y - center.y; float ey = extents.y + mBox.mExtents.y; if(GREATER(ty, ey)) return FALSE; + float tz = mBox.mCenter.z - center.z; float ez = extents.z + mBox.mExtents.z; if(GREATER(tz, ez)) return FALSE; + + return TRUE; +} diff --git a/third-party/Opcode/OPC_BoxPruning.cpp b/third-party/Opcode/OPC_BoxPruning.cpp new file mode 100644 index 0000000..3735a39 --- /dev/null +++ b/third-party/Opcode/OPC_BoxPruning.cpp @@ -0,0 +1,367 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for box pruning. + * \file IceBoxPruning.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + You could use a complex sweep-and-prune as implemented in I-Collide. + You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems. + You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2. + + Or you could use this. + Faster ? I don't know. Probably not. It would be a shame. But who knows ? + Easier ? Definitely. Enjoy the sheer simplicity. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + + inline_ void FindRunningIndex(udword& index, float* array, udword* sorted, int last, float max) + { + int First=index; + while(First<=last) + { + index = (First+last)>>1; + + if(max>array[sorted[index]]) First = index+1; + else last = index-1; + } + } +// ### could be log(n) ! +// and maybe use cmp integers + +// InsertionSort has better coherence, RadixSort is better for one-shot queries. +#define PRUNING_SORTER RadixSort +//#define PRUNING_SORTER InsertionSort + +// Static for coherence +static PRUNING_SORTER* gCompletePruningSorter = null; +static PRUNING_SORTER* gBipartitePruningSorter0 = null; +static PRUNING_SORTER* gBipartitePruningSorter1 = null; +inline_ PRUNING_SORTER* GetCompletePruningSorter() +{ + if(!gCompletePruningSorter) gCompletePruningSorter = new PRUNING_SORTER; + return gCompletePruningSorter; +} +inline_ PRUNING_SORTER* GetBipartitePruningSorter0() +{ + if(!gBipartitePruningSorter0) gBipartitePruningSorter0 = new PRUNING_SORTER; + return gBipartitePruningSorter0; +} +inline_ PRUNING_SORTER* GetBipartitePruningSorter1() +{ + if(!gBipartitePruningSorter1) gBipartitePruningSorter1 = new PRUNING_SORTER; + return gBipartitePruningSorter1; +} +void ReleasePruningSorters() +{ + DELETESINGLE(gBipartitePruningSorter1); + DELETESINGLE(gBipartitePruningSorter0); + DELETESINGLE(gCompletePruningSorter); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. + * \param nb0 [in] number of boxes in the first set + * \param array0 [in] array of boxes for the first set + * \param nb1 [in] number of boxes in the second set + * \param array1 [in] array of boxes for the second set + * \param pairs [out] array of overlapping pairs + * \param axes [in] projection order (0,2,1 is often best) + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes) +{ + // Checkings + if(!nb0 || !array0 || !nb1 || !array1) return false; + + // Catch axes + udword Axis0 = axes.mAxis0; + udword Axis1 = axes.mAxis1; + udword Axis2 = axes.mAxis2; + + // Allocate some temporary data + float* MinPosList0 = new float[nb0]; + float* MinPosList1 = new float[nb1]; + + // 1) Build main lists using the primary axis + for(udword i=0;iGetMin(Axis0); + for(udword i=0;iGetMin(Axis0); + + // 2) Sort the lists + PRUNING_SORTER* RS0 = GetBipartitePruningSorter0(); + PRUNING_SORTER* RS1 = GetBipartitePruningSorter1(); + const udword* Sorted0 = RS0->Sort(MinPosList0, nb0).GetRanks(); + const udword* Sorted1 = RS1->Sort(MinPosList1, nb1).GetRanks(); + + // 3) Prune the lists + udword Index0, Index1; + + const udword* const LastSorted0 = &Sorted0[nb0]; + const udword* const LastSorted1 = &Sorted1[nb1]; + const udword* RunningAddress0 = Sorted0; + const udword* RunningAddress1 = Sorted1; + + while(RunningAddress1GetMax(Axis0)) + { + if(array0[Index0]->Intersect(*array1[Index1], Axis1)) + { + if(array0[Index0]->Intersect(*array1[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } + } + } + + //// + + while(RunningAddress0GetMax(Axis0)) + { + if(array0[Index1]->Intersect(*array1[Index0], Axis1)) + { + if(array0[Index1]->Intersect(*array1[Index0], Axis2)) + { + pairs.AddPair(Index1, Index0); + } + } + + } + } + + DELETEARRAY(MinPosList1); + DELETEARRAY(MinPosList0); + + return true; +} + +#define ORIGINAL_VERSION +//#define JOAKIM + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. + * \param nb [in] number of boxes + * \param array [in] array of boxes + * \param pairs [out] array of overlapping pairs + * \param axes [in] projection order (0,2,1 is often best) + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes) +{ + // Checkings + if(!nb || !array) return false; + + // Catch axes + udword Axis0 = axes.mAxis0; + udword Axis1 = axes.mAxis1; + udword Axis2 = axes.mAxis2; + +#ifdef ORIGINAL_VERSION + // Allocate some temporary data +// float* PosList = new float[nb]; + float* PosList = new float[nb+1]; + + // 1) Build main list using the primary axis + for(udword i=0;iGetMin(Axis0); +PosList[nb++] = MAX_FLOAT; + + // 2) Sort the list + PRUNING_SORTER* RS = GetCompletePruningSorter(); + const udword* Sorted = RS->Sort(PosList, nb).GetRanks(); + + // 3) Prune the list + const udword* const LastSorted = &Sorted[nb]; + const udword* RunningAddress = Sorted; + udword Index0, Index1; + while(RunningAddressGetMax(Axis0)) + while(PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0)) + { +// if(Index0!=Index1) +// { + if(array[Index0]->Intersect(*array[Index1], Axis1)) + { + if(array[Index0]->Intersect(*array[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } +// } + } + } + } + + DELETEARRAY(PosList); +#endif + +#ifdef JOAKIM + // Allocate some temporary data +// float* PosList = new float[nb]; + float* MinList = new float[nb+1]; + + // 1) Build main list using the primary axis + for(udword i=0;iGetMin(Axis0); + MinList[nb] = MAX_FLOAT; + + // 2) Sort the list + PRUNING_SORTER* RS = GetCompletePruningSorter(); + udword* Sorted = RS->Sort(MinList, nb+1).GetRanks(); + + // 3) Prune the list +// const udword* const LastSorted = &Sorted[nb]; +// const udword* const LastSorted = &Sorted[nb-1]; + const udword* RunningAddress = Sorted; + udword Index0, Index1; + +// while(RunningAddressGetMax(Axis0)) + +// float CurrentMin = array[Index0]->GetMin(Axis0); + float CurrentMax = array[Index0]->GetMax(Axis0); + + while(MinList[Index1 = *RunningAddress2] <= CurrentMax) +// while(PosList[Index1 = *RunningAddress] <= CurrentMax) + { +// if(Index0!=Index1) +// { + if(array[Index0]->Intersect(*array[Index1], Axis1)) + { + if(array[Index0]->Intersect(*array[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } +// } + + RunningAddress2++; +// RunningAddress++; + } + } + } + + DELETEARRAY(MinList); +#endif + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Brute-force versions are kept: +// - to check the optimized versions return the correct list of intersections +// - to check the speed of the optimized code against the brute-force one +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Brute-force bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. + * \param nb0 [in] number of boxes in the first set + * \param array0 [in] array of boxes for the first set + * \param nb1 [in] number of boxes in the second set + * \param array1 [in] array of boxes for the second set + * \param pairs [out] array of overlapping pairs + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs) +{ + // Checkings + if(!nb0 || !array0 || !nb1 || !array1) return false; + + // Brute-force nb0*nb1 overlap tests + for(udword i=0;iIntersect(*array1[j])) pairs.AddPair(i, j); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. + * \param nb [in] number of boxes + * \param array [in] array of boxes + * \param pairs [out] array of overlapping pairs + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs) +{ + // Checkings + if(!nb || !array) return false; + + // Brute-force n(n-1)/2 overlap tests + for(udword i=0;iIntersect(*array[j])) pairs.AddPair(i, j); + } + } + return true; +} diff --git a/third-party/Opcode/OPC_BoxPruning.h b/third-party/Opcode/OPC_BoxPruning.h new file mode 100644 index 0000000..b431946 --- /dev/null +++ b/third-party/Opcode/OPC_BoxPruning.h @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for box pruning. + * \file IceBoxPruning.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_BOXPRUNING_H__ +#define __OPC_BOXPRUNING_H__ + + // Optimized versions + FUNCTION OPCODE_API bool CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes); + FUNCTION OPCODE_API bool BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes); + + // Brute-force versions + FUNCTION OPCODE_API bool BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs); + FUNCTION OPCODE_API bool BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs); + +#endif //__OPC_BOXPRUNING_H__ \ No newline at end of file diff --git a/third-party/Opcode/OPC_Collider.cpp b/third-party/Opcode/OPC_Collider.cpp new file mode 100644 index 0000000..c352618 --- /dev/null +++ b/third-party/Opcode/OPC_Collider.cpp @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base collider class. + * \file OPC_Collider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains the abstract class for colliders. + * + * \class Collider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Collider::Collider() : + mFlags (0), + mCurrentModel (null), + mIMesh (null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Collider::~Collider() +{ +} diff --git a/third-party/Opcode/OPC_Collider.h b/third-party/Opcode/OPC_Collider.h new file mode 100644 index 0000000..d718e02 --- /dev/null +++ b/third-party/Opcode/OPC_Collider.h @@ -0,0 +1,176 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base collider class. + * \file OPC_Collider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_COLLIDER_H__ +#define __OPC_COLLIDER_H__ + + enum CollisionFlag + { + OPC_FIRST_CONTACT = (1<<0), //!< Report all contacts (false) or only first one (true) + OPC_TEMPORAL_COHERENCE = (1<<1), //!< Use temporal coherence or not + OPC_CONTACT = (1<<2), //!< Final contact status after a collision query + OPC_TEMPORAL_HIT = (1<<3), //!< There has been an early exit due to temporal coherence + OPC_NO_PRIMITIVE_TESTS = (1<<4), //!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries) + + OPC_CONTACT_FOUND = OPC_FIRST_CONTACT | OPC_CONTACT, + OPC_TEMPORAL_CONTACT = OPC_TEMPORAL_HIT | OPC_CONTACT, + + OPC_FORCE_DWORD = 0x7fffffff + }; + + class OPCODE_API Collider + { + public: + // Constructor / Destructor + Collider(); + virtual ~Collider(); + + // Collision report + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the last collision status after a collision query. + * \return true if a collision occured + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL GetContactStatus() const { return mFlags & OPC_CONTACT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the "first contact" mode. + * \return true if "first contact" mode is on + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL FirstContactEnabled() const { return mFlags & OPC_FIRST_CONTACT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the temporal coherence mode. + * \return true if temporal coherence is on + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL TemporalCoherenceEnabled() const { return mFlags & OPC_TEMPORAL_COHERENCE; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks a first contact has already been found. + * \return true if a first contact has been found and we can stop a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL ContactFound() const { return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks there's been an early exit due to temporal coherence; + * \return true if a temporal hit has occured + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL TemporalHit() const { return mFlags & OPC_TEMPORAL_HIT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks primitive tests are enabled; + * \return true if primitive tests must be skipped + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL SkipPrimitiveTests() const { return mFlags & OPC_NO_PRIMITIVE_TESTS; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Reports all contacts (false) or first contact only (true) + * \param flag [in] true for first contact, false for all contacts + * \see SetTemporalCoherence(bool flag) + * \see ValidateSettings() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFirstContact(bool flag) + { + if(flag) mFlags |= OPC_FIRST_CONTACT; + else mFlags &= ~OPC_FIRST_CONTACT; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Enable/disable temporal coherence. + * \param flag [in] true to enable temporal coherence, false to discard it + * \see SetFirstContact(bool flag) + * \see ValidateSettings() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetTemporalCoherence(bool flag) + { + if(flag) mFlags |= OPC_TEMPORAL_COHERENCE; + else mFlags &= ~OPC_TEMPORAL_COHERENCE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Enable/disable primitive tests. + * \param flag [in] true to enable primitive tests, false to discard them + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetPrimitiveTests(bool flag) + { + if(!flag) mFlags |= OPC_NO_PRIMITIVE_TESTS; + else mFlags &= ~OPC_NO_PRIMITIVE_TESTS; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual const char* ValidateSettings() = 0; + + protected: + udword mFlags; //!< Bit flags + const BaseModel* mCurrentModel; //!< Current model for collision query (owner of touched faces) + // User mesh interface + const MeshInterface* mIMesh; //!< User-defined mesh interface + + // Internal methods + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups current collision model + * \param model [in] current collision model + * \return TRUE if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Setup(const BaseModel* model) + { + // Keep track of current model + mCurrentModel = model; + if(!mCurrentModel) return FALSE; + + mIMesh = model->GetMeshInterface(); + return mIMesh!=null; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Initializes a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual inline_ void InitQuery() { mFlags &= ~OPC_TEMPORAL_CONTACT; } + }; + +#endif // __OPC_COLLIDER_H__ diff --git a/third-party/Opcode/OPC_Common.cpp b/third-party/Opcode/OPC_Common.cpp new file mode 100644 index 0000000..6bd9722 --- /dev/null +++ b/third-party/Opcode/OPC_Common.cpp @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains common classes & defs used in OPCODE. + * \file OPC_Common.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * An AABB dedicated to collision detection. + * We don't use the generic AABB class included in ICE, since it can be a Min/Max or a Center/Extents one (depends + * on compilation flags). Since the Center/Extents model is more efficient in collision detection, it was worth + * using an extra special class. + * + * \class CollisionAABB + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized AABB. + * Center/Extent model, using 16-bits integers. + * + * \class QuantizedAABB + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; diff --git a/third-party/Opcode/OPC_Common.h b/third-party/Opcode/OPC_Common.h new file mode 100644 index 0000000..84ccf8d --- /dev/null +++ b/third-party/Opcode/OPC_Common.h @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains common classes & defs used in OPCODE. + * \file OPC_Common.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_COMMON_H__ +#define __OPC_COMMON_H__ + +// [GOTTFRIED]: Just a small change for readability. +#ifdef OPC_CPU_COMPARE + #define GREATER(x, y) AIR(x) > IR(y) +#else + #define GREATER(x, y) fabsf(x) > (y) +#endif + + class OPCODE_API CollisionAABB + { + public: + //! Constructor + inline_ CollisionAABB() {} + //! Constructor + inline_ CollisionAABB(const AABB& b) { b.GetCenter(mCenter); b.GetExtents(mExtents); } + //! Destructor + inline_ ~CollisionAABB() {} + + //! Get min IcePoint of the box + inline_ void GetMin(IcePoint& min) const { min = mCenter - mExtents; } + //! Get max IcePoint of the box + inline_ void GetMax(IcePoint& max) const { max = mCenter + mExtents; } + + //! Get component of the box's min IcePoint along a given axis + inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } + //! Get component of the box's max IcePoint along a given axis + inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min IcePoint + * \param max [in] the max IcePoint + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMinMax(const IcePoint& min, const IcePoint& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks a box is inside another box. + * \param box [in] the other box + * \return true if current box is inside input box + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsInside(const CollisionAABB& box) const + { + if(box.GetMin(0)>GetMin(0)) return FALSE; + if(box.GetMin(1)>GetMin(1)) return FALSE; + if(box.GetMin(2)>GetMin(2)) return FALSE; + if(box.GetMax(0)IsValid()) return false; + + // Look for degenerate faces. + udword NbDegenerate = create.mIMesh->CheckTopology(); + if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); + // We continue nonetheless.... + + Release(); // Make sure previous tree has been discarded + + // 1-1) Setup mesh interface automatically + SetMeshInterface(create.mIMesh); + + bool Status = false; + AABBTree* LeafTree = null; + Internal Data; + + // 2) Build a generic AABB Tree. + mSource = new AABBTree; + CHECKALLOC(mSource); + + // 2-1) Setup a builder. Our primitives here are triangles from input mesh, + // so we use an AABBTreeOfTrianglesBuilder..... + { + AABBTreeOfTrianglesBuilder TB; + TB.mIMesh = create.mIMesh; + TB.mNbPrimitives = create.mIMesh->GetNbTriangles(); + TB.mSettings = create.mSettings; + TB.mSettings.mLimit = 16; // ### Hardcoded, but maybe we could let the user choose 8 / 16 / 32 ... + if(!mSource->Build(&TB)) goto FreeAndExit; + } + + // 2-2) Here's the trick : create *another* AABB tree using the leaves of the first one (which are boxes, this time) + struct Local + { + // A callback to count leaf nodes + static bool CountLeaves(const AABBTreeNode* current, udword depth, void* user_data) + { + if(current->IsLeaf()) + { + Internal* Data = (Internal*)user_data; + Data->mNbLeaves++; + } + return true; + } + + // A callback to setup leaf nodes in our internal structures + static bool SetupLeafData(const AABBTreeNode* current, udword depth, void* user_data) + { + if(current->IsLeaf()) + { + Internal* Data = (Internal*)user_data; + + // Get current leaf's box + Data->mLeaves[Data->mNbLeaves] = *current->GetAABB(); + + // Setup leaf data + udword Index = (udword(current->GetPrimitives()) - udword(Data->mBase))/sizeof(udword); + Data->mTriangles[Data->mNbLeaves].SetData(current->GetNbPrimitives(), Index); + + Data->mNbLeaves++; + } + return true; + } + }; + + // Walk the tree & count number of leaves + Data.mNbLeaves = 0; + mSource->Walk(Local::CountLeaves, &Data); + mNbLeaves = Data.mNbLeaves; // Keep track of it + + // Special case for 1-leaf meshes + if(mNbLeaves==1) + { + mModelCode |= OPC_SINGLE_NODE; + Status = true; + goto FreeAndExit; + } + + // Allocate our structures + Data.mLeaves = new AABB[Data.mNbLeaves]; CHECKALLOC(Data.mLeaves); + mTriangles = new LeafTriangles[Data.mNbLeaves]; CHECKALLOC(mTriangles); + + // Walk the tree again & setup leaf data + Data.mTriangles = mTriangles; + Data.mBase = mSource->GetIndices(); + Data.mNbLeaves = 0; // Reset for incoming walk + mSource->Walk(Local::SetupLeafData, &Data); + + // Handle source indices + { + bool MustKeepIndices = true; + if(create.mCanRemap) + { + // We try to get rid of source indices (saving more ram!) by reorganizing triangle arrays... + // Remap can fail when we use callbacks => keep track of indices in that case (it still + // works, only using more memory) + if(create.mIMesh->RemapClient(mSource->GetNbPrimitives(), mSource->GetIndices())) + { + MustKeepIndices = false; + } + } + + if(MustKeepIndices) + { + // Keep track of source indices (from vanilla tree) + mNbPrimitives = mSource->GetNbPrimitives(); + mIndices = new udword[mNbPrimitives]; + CopyMemory(mIndices, mSource->GetIndices(), mNbPrimitives*sizeof(udword)); + } + } + + // Now, create our optimized tree using previous leaf nodes + LeafTree = new AABBTree; + CHECKALLOC(LeafTree); + { + AABBTreeOfAABBsBuilder TB; // Now using boxes ! + TB.mSettings = create.mSettings; + TB.mSettings.mLimit = 1; // We now want a complete tree so that we can "optimize" it + TB.mNbPrimitives = Data.mNbLeaves; + TB.mAABBArray = Data.mLeaves; + if(!LeafTree->Build(&TB)) goto FreeAndExit; + } + + // 3) Create an optimized tree according to user-settings + if(!CreateTree(create.mNoLeaf, create.mQuantized)) goto FreeAndExit; + + // 3-2) Create optimized tree + if(!mTree->Build(LeafTree)) goto FreeAndExit; + + // Finally ok... + Status = true; + +FreeAndExit: // Allow me this one... + DELETESINGLE(LeafTree); + + // 3-3) Delete generic tree if needed + if(!create.mKeepOriginal) DELETESINGLE(mSource); + + return Status; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword HybridModel::GetUsedBytes() const +{ + udword UsedBytes = 0; + if(mTree) UsedBytes += mTree->GetUsedBytes(); + if(mIndices) UsedBytes += mNbPrimitives * sizeof(udword); // mIndices + if(mTriangles) UsedBytes += mNbLeaves * sizeof(LeafTriangles); // mTriangles + return UsedBytes; +} + +inline_ void ComputeMinMax(IcePoint& min, IcePoint& max, const VertexPointers& vp) +{ + // Compute triangle's AABB = a leaf box +#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much + min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + + min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + + min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); + max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); +#else + min = *vp.Vertex[0]; + max = *vp.Vertex[0]; + min.Min(*vp.Vertex[1]); + max.Max(*vp.Vertex[1]); + min.Min(*vp.Vertex[2]); + max.Max(*vp.Vertex[2]); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool HybridModel::Refit() +{ + if(!mIMesh) return false; + if(!mTree) return false; + + if(IsQuantized()) return false; + if(HasLeafNodes()) return false; + + const LeafTriangles* LT = GetLeafTriangles(); + const udword* Indices = GetIndices(); + + // Bottom-up update + VertexPointers VP; + IcePoint Min,Max; + IcePoint Min_,Max_; + udword Index = mTree->GetNbNodes(); + AABBNoLeafNode* Nodes = (AABBNoLeafNode*)((AABBNoLeafTree*)mTree)->GetNodes(); + while(Index--) + { + AABBNoLeafNode& Current = Nodes[Index]; + + if(Current.HasPosLeaf()) + { + const LeafTriangles& CurrentLeaf = LT[Current.GetPosPrimitive()]; + + Min.SetPlusInfinity(); + Max.SetMinusInfinity(); + + IcePoint TmpMin, TmpMax; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, *T++); + ComputeMinMax(TmpMin, TmpMax, VP); + Min.Min(TmpMin); + Max.Max(TmpMax); + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, BaseIndex++); + ComputeMinMax(TmpMin, TmpMax, VP); + Min.Min(TmpMin); + Max.Max(TmpMax); + } + } + } + else + { + const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; + CurrentBox.GetMin(Min); + CurrentBox.GetMax(Max); + } + + if(Current.HasNegLeaf()) + { + const LeafTriangles& CurrentLeaf = LT[Current.GetNegPrimitive()]; + + Min_.SetPlusInfinity(); + Max_.SetMinusInfinity(); + + IcePoint TmpMin, TmpMax; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, *T++); + ComputeMinMax(TmpMin, TmpMax, VP); + Min_.Min(TmpMin); + Max_.Max(TmpMax); + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, BaseIndex++); + ComputeMinMax(TmpMin, TmpMax, VP); + Min_.Min(TmpMin); + Max_.Max(TmpMax); + } + } + } + else + { + const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; + CurrentBox.GetMin(Min_); + CurrentBox.GetMax(Max_); + } +#ifdef OPC_USE_FCOMI + Min.x = FCMin2(Min.x, Min_.x); + Max.x = FCMax2(Max.x, Max_.x); + Min.y = FCMin2(Min.y, Min_.y); + Max.y = FCMax2(Max.y, Max_.y); + Min.z = FCMin2(Min.z, Min_.z); + Max.z = FCMax2(Max.z, Max_.z); +#else + Min.Min(Min_); + Max.Max(Max_); +#endif + Current.mAABB.SetMinMax(Min, Max); + } + return true; +} diff --git a/third-party/Opcode/OPC_HybridModel.h b/third-party/Opcode/OPC_HybridModel.h new file mode 100644 index 0000000..c7eb59d --- /dev/null +++ b/third-party/Opcode/OPC_HybridModel.h @@ -0,0 +1,106 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for hybrid models. + * \file OPC_HybridModel.h + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_HYBRIDMODEL_H__ +#define __OPC_HYBRIDMODEL_H__ + + //! Leaf descriptor + struct LeafTriangles + { + udword Data; //!< Packed data + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets number of triangles in the leaf. + * \return number of triangles N, with 0 < N <= 16 + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbTriangles() const { return (Data & 15)+1; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets triangle index for this leaf. Indexed model's array of indices retrieved with HybridModel::GetIndices() + * \return triangle index + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetTriangleIndex() const { return Data>>4; } + inline_ void SetData(udword nb, udword index) { ASSERT(nb>0 && nb<=16); nb--; Data = (index<<4)|(nb&15); } + }; + + class OPCODE_API HybridModel : public BaseModel + { + public: + // Constructor/Destructor + HybridModel(); + virtual ~HybridModel(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Build(const OPCODECREATE& create); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) udword GetUsedBytes() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Refit(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets array of triangles. + * \return array of triangles + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const LeafTriangles* GetLeafTriangles() const { return mTriangles; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets array of indices. + * \return array of indices + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const udword* GetIndices() const { return mIndices; } + + private: + udword mNbLeaves; //!< Number of leaf nodes in the model + LeafTriangles* mTriangles; //!< Array of mNbLeaves leaf descriptors + udword mNbPrimitives; //!< Number of primitives in the model + udword* mIndices; //!< Array of primitive indices + + // Internal methods + void Release(); + }; + +#endif // __OPC_HYBRIDMODEL_H__ diff --git a/third-party/Opcode/OPC_IceHook.h b/third-party/Opcode/OPC_IceHook.h new file mode 100644 index 0000000..d33120b --- /dev/null +++ b/third-party/Opcode/OPC_IceHook.h @@ -0,0 +1,70 @@ + +// Should be included by Opcode.h if needed + + #define ICE_DONT_CHECK_COMPILER_OPTIONS + + // From Windows... + typedef int BOOL; + #ifndef FALSE + #define FALSE 0 + #endif + + #ifndef TRUE + #define TRUE 1 + #endif + + #include + #include + #include + #include + #include + #include + + #ifndef ASSERT + #define ASSERT(exp) {} + #endif + #define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ] + + #define Log {} + #define SetIceError false + #define EC_OUTOFMEMORY "Out of memory" + + #include "Ice/IcePreprocessor.h" + + #undef ICECORE_API + #define ICECORE_API OPCODE_API + + #include "Ice/IceTypes.h" + #include "Ice/IceFPU.h" + #include "Ice/IceMemoryMacros.h" + + namespace IceCore + { + #include "Ice/IceUtils.h" + #include "Ice/IceContainer.h" + #include "Ice/IcePairs.h" + #include "Ice/IceRevisitedRadix.h" + #include "Ice/IceRandom.h" + } + using namespace IceCore; + + #define ICEMATHS_API OPCODE_API + namespace IceMaths + { + #include "Ice/IceAxes.h" + #include "Ice/IcePoint.h" + #include "Ice/IceHPoint.h" + #include "Ice/IceMatrix3x3.h" + #include "Ice/IceMatrix4x4.h" + #include "Ice/IcePlane.h" + #include "Ice/IceRay.h" + #include "Ice/IceIndexedTriangle.h" + #include "Ice/IceTriangle.h" + #include "Ice/IceTrilist.h" + #include "Ice/IceAABB.h" + #include "Ice/IceOBB.h" + #include "Ice/IceBoundingSphere.h" + #include "Ice/IceSegment.h" + #include "Ice/IceLSS.h" + } + using namespace IceMaths; diff --git a/third-party/Opcode/OPC_LSSAABBOverlap.h b/third-party/Opcode/OPC_LSSAABBOverlap.h new file mode 100644 index 0000000..5afb190 --- /dev/null +++ b/third-party/Opcode/OPC_LSSAABBOverlap.h @@ -0,0 +1,523 @@ + +// Following code from Magic-Software (http://www.magic-software.com/) +// A bit modified for Opcode + +inline_ float OPC_PointAABBSqrDist(const IcePoint& Point, const IcePoint& center, const IcePoint& extents) +{ + // Compute coordinates of IcePoint in box coordinate system + IcePoint Closest = Point - center; + + float SqrDistance = 0.0f; + + if(Closest.x < -extents.x) + { + float Delta = Closest.x + extents.x; + SqrDistance += Delta*Delta; + } + else if(Closest.x > extents.x) + { + float Delta = Closest.x - extents.x; + SqrDistance += Delta*Delta; + } + + if(Closest.y < -extents.y) + { + float Delta = Closest.y + extents.y; + SqrDistance += Delta*Delta; + } + else if(Closest.y > extents.y) + { + float Delta = Closest.y - extents.y; + SqrDistance += Delta*Delta; + } + + if(Closest.z < -extents.z) + { + float Delta = Closest.z + extents.z; + SqrDistance += Delta*Delta; + } + else if(Closest.z > extents.z) + { + float Delta = Closest.z - extents.z; + SqrDistance += Delta*Delta; + } + return SqrDistance; +} + +static void Face(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, const IcePoint& rkPmE, float* pfLParam, float& rfSqrDistance) +{ + IcePoint kPpE; + float fLSqr, fInv, fTmp, fParam, fT, fDelta; + + kPpE[i1] = rkPnt[i1] + extents[i1]; + kPpE[i2] = rkPnt[i2] + extents[i2]; + if(rkDir[i0]*kPpE[i1] >= rkDir[i1]*rkPmE[i0]) + { + if(rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0]) + { + // v[i1] >= -e[i1], v[i2] >= -e[i2] (distance = 0) + if(pfLParam) + { + rkPnt[i0] = extents[i0]; + fInv = 1.0f/rkDir[i0]; + rkPnt[i1] -= rkDir[i1]*rkPmE[i0]*fInv; + rkPnt[i2] -= rkDir[i2]*rkPmE[i0]*fInv; + *pfLParam = -rkPmE[i0]*fInv; + } + } + else + { + // v[i1] >= -e[i1], v[i2] < -e[i2] + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i2]*rkDir[i2]; + fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); + if(fTmp <= 2.0f*fLSqr*extents[i1]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i1]*rkDir[i1]; + fTmp = kPpE[i1] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = fT - extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + else + { + fLSqr += rkDir[i1]*rkDir[i1]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + } + } + else + { + if ( rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0] ) + { + // v[i1] < -e[i1], v[i2] >= -e[i2] + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; + fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); + if(fTmp <= 2.0f*fLSqr*extents[i2]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i2]*rkDir[i2]; + fTmp = kPpE[i2] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = fT - extents[i2]; + } + } + else + { + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = extents[i2]; + } + } + } + else + { + // v[i1] < -e[i1], v[i2] < -e[i2] + fLSqr = rkDir[i0]*rkDir[i0]+rkDir[i2]*rkDir[i2]; + fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); + if(fTmp >= 0.0f) + { + // v[i1]-edge is closest + if ( fTmp <= 2.0f*fLSqr*extents[i1] ) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i1]*rkDir[i1]; + fTmp = kPpE[i1] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = fT - extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + else + { + fLSqr += rkDir[i1]*rkDir[i1]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + return; + } + + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; + fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); + if(fTmp >= 0.0f) + { + // v[i2]-edge is closest + if(fTmp <= 2.0f*fLSqr*extents[i2]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i2]*rkDir[i2]; + fTmp = kPpE[i2] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = fT - extents[i2]; + } + } + else + { + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = extents[i2]; + } + } + return; + } + + // (v[i1],v[i2])-corner is closest + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + } +} + +static void CaseNoZeros(IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) +{ + IcePoint kPmE(rkPnt.x - extents.x, rkPnt.y - extents.y, rkPnt.z - extents.z); + + float fProdDxPy, fProdDyPx, fProdDzPx, fProdDxPz, fProdDzPy, fProdDyPz; + + fProdDxPy = rkDir.x*kPmE.y; + fProdDyPx = rkDir.y*kPmE.x; + if(fProdDyPx >= fProdDxPy) + { + fProdDzPx = rkDir.z*kPmE.x; + fProdDxPz = rkDir.x*kPmE.z; + if(fProdDzPx >= fProdDxPz) + { + // line intersects x = e0 + Face(0, 1, 2, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + else + { + // line intersects z = e2 + Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + } + else + { + fProdDzPy = rkDir.z*kPmE.y; + fProdDyPz = rkDir.y*kPmE.z; + if(fProdDzPy >= fProdDyPz) + { + // line intersects y = e1 + Face(1, 2, 0, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + else + { + // line intersects z = e2 + Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + } +} + +static void Case0(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) +{ + float fPmE0 = rkPnt[i0] - extents[i0]; + float fPmE1 = rkPnt[i1] - extents[i1]; + float fProd0 = rkDir[i1]*fPmE0; + float fProd1 = rkDir[i0]*fPmE1; + float fDelta, fInvLSqr, fInv; + + if(fProd0 >= fProd1) + { + // line intersects P[i0] = e[i0] + rkPnt[i0] = extents[i0]; + + float fPpE1 = rkPnt[i1] + extents[i1]; + fDelta = fProd0 - rkDir[i0]*fPpE1; + if(fDelta >= 0.0f) + { + fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); + rfSqrDistance += fDelta*fDelta*fInvLSqr; + if(pfLParam) + { + rkPnt[i1] = -extents[i1]; + *pfLParam = -(rkDir[i0]*fPmE0+rkDir[i1]*fPpE1)*fInvLSqr; + } + } + else + { + if(pfLParam) + { + fInv = 1.0f/rkDir[i0]; + rkPnt[i1] -= fProd0*fInv; + *pfLParam = -fPmE0*fInv; + } + } + } + else + { + // line intersects P[i1] = e[i1] + rkPnt[i1] = extents[i1]; + + float fPpE0 = rkPnt[i0] + extents[i0]; + fDelta = fProd1 - rkDir[i1]*fPpE0; + if(fDelta >= 0.0f) + { + fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); + rfSqrDistance += fDelta*fDelta*fInvLSqr; + if(pfLParam) + { + rkPnt[i0] = -extents[i0]; + *pfLParam = -(rkDir[i0]*fPpE0+rkDir[i1]*fPmE1)*fInvLSqr; + } + } + else + { + if(pfLParam) + { + fInv = 1.0f/rkDir[i1]; + rkPnt[i0] -= fProd1*fInv; + *pfLParam = -fPmE1*fInv; + } + } + } + + if(rkPnt[i2] < -extents[i2]) + { + fDelta = rkPnt[i2] + extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = -extents[i2]; + } + else if ( rkPnt[i2] > extents[i2] ) + { + fDelta = rkPnt[i2] - extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = extents[i2]; + } +} + +static void Case00(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) +{ + float fDelta; + + if(pfLParam) + *pfLParam = (extents[i0] - rkPnt[i0])/rkDir[i0]; + + rkPnt[i0] = extents[i0]; + + if(rkPnt[i1] < -extents[i1]) + { + fDelta = rkPnt[i1] + extents[i1]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = -extents[i1]; + } + else if(rkPnt[i1] > extents[i1]) + { + fDelta = rkPnt[i1] - extents[i1]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = extents[i1]; + } + + if(rkPnt[i2] < -extents[i2]) + { + fDelta = rkPnt[i2] + extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = -extents[i2]; + } + else if(rkPnt[i2] > extents[i2]) + { + fDelta = rkPnt[i2] - extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = extents[i2]; + } +} + +static void Case000(IcePoint& rkPnt, const IcePoint& extents, float& rfSqrDistance) +{ + float fDelta; + + if(rkPnt.x < -extents.x) + { + fDelta = rkPnt.x + extents.x; + rfSqrDistance += fDelta*fDelta; + rkPnt.x = -extents.x; + } + else if(rkPnt.x > extents.x) + { + fDelta = rkPnt.x - extents.x; + rfSqrDistance += fDelta*fDelta; + rkPnt.x = extents.x; + } + + if(rkPnt.y < -extents.y) + { + fDelta = rkPnt.y + extents.y; + rfSqrDistance += fDelta*fDelta; + rkPnt.y = -extents.y; + } + else if(rkPnt.y > extents.y) + { + fDelta = rkPnt.y - extents.y; + rfSqrDistance += fDelta*fDelta; + rkPnt.y = extents.y; + } + + if(rkPnt.z < -extents.z) + { + fDelta = rkPnt.z + extents.z; + rfSqrDistance += fDelta*fDelta; + rkPnt.z = -extents.z; + } + else if(rkPnt.z > extents.z) + { + fDelta = rkPnt.z - extents.z; + rfSqrDistance += fDelta*fDelta; + rkPnt.z = extents.z; + } +} + +static float SqrDistance(const Ray& rkLine, const IcePoint& center, const IcePoint& extents, float* pfLParam) +{ + // compute coordinates of line in box coordinate system + IcePoint kDiff = rkLine.mOrig - center; + IcePoint kPnt = kDiff; + IcePoint kDir = rkLine.mDir; + + // Apply reflections so that direction vector has nonnegative components. + bool bReflect[3]; + for(int i=0;i<3;i++) + { + if(kDir[i]<0.0f) + { + kPnt[i] = -kPnt[i]; + kDir[i] = -kDir[i]; + bReflect[i] = true; + } + else + { + bReflect[i] = false; + } + } + + float fSqrDistance = 0.0f; + + if(kDir.x>0.0f) + { + if(kDir.y>0.0f) + { + if(kDir.z>0.0f) CaseNoZeros(kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,+) + else Case0(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,0) + } + else + { + if(kDir.z>0.0f) Case0(0, 2, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,+) + else Case00(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,0) + } + } + else + { + if(kDir.y>0.0f) + { + if(kDir.z>0.0f) Case0(1, 2, 0, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,+) + else Case00(1, 0, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,0) + } + else + { + if(kDir.z>0.0f) Case00(2, 0, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,0,+) + else + { + Case000(kPnt, extents, fSqrDistance); // (0,0,0) + if(pfLParam) *pfLParam = 0.0f; + } + } + } + return fSqrDistance; +} + +inline_ float OPC_SegmentOBBSqrDist(const IceSegment& segment, const IcePoint& c0, const IcePoint& e0) +{ + float fLP; + float fSqrDistance = SqrDistance(Ray(segment.GetOrigin(), segment.ComputeDirection()), c0, e0, &fLP); + if(fLP>=0.0f) + { + if(fLP<=1.0f) return fSqrDistance; + else return OPC_PointAABBSqrDist(segment.mP1, c0, e0); + } + else return OPC_PointAABBSqrDist(segment.mP0, c0, e0); +} + +inline_ BOOL LSSCollider::LSSAABBOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbVolumeBVTests++; + + float s2 = OPC_SegmentOBBSqrDist(mSeg, center, extents); + if(s2Add(prim_index); + +//! LSS-triangle overlap test +#define LSS_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform LSS-tri overlap test */ \ + if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +LSSCollider::LSSCollider() +{ +// mCenter.Zero(); +// mRadius2 = 0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +LSSCollider::~LSSCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in local space + * \param model [in] Opcode model to collide with + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, lss, worldl, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] an lss cache + * \param lss [in] lss in local space + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL LSSCollider::InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute LSS in model space: + // - Precompute R^2 + mRadius2 = lss.mRadius * lss.mRadius; + // - Compute segment + mSeg.mP0 = lss.mP0; + mSeg.mP1 = lss.mP1; + // -> to world space + if(worldl) + { + mSeg.mP0 *= *worldl; + mSeg.mP1 *= *worldl; + } + // -> to model space + if(worldm) + { + // Invert model matrix + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + mSeg.mP0 *= InvWorldM; + mSeg.mP1 *= InvWorldM; + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the LSS (and set contact status if needed) + LSS_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the LSS (and set contact status if needed) + LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious): + + // ### rewrite this + + LSS Test(mSeg, lss.mRadius); // in model space + LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius)); + +// if(cache.Previous.Contains(Test)) + if(IsCacheValid(cache) && Previous.Contains(Test)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat sphere so that coherence will work for subsequent frames + mRadius2 *= cache.FatCoeff; +// mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff); + + + // Update cache with query data (signature for cached faces) + cache.Previous.mP0 = mSeg.mP0; + cache.Previous.mP1 = mSeg.mP1; + cache.Previous.mRadius = mRadius2; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, lss)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the LSS completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the LSS contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL LSSCollider::LSSContainsBox(const IcePoint& bc, const IcePoint& be) +{ + // Not implemented + return FALSE; +} + +#define TEST_BOX_IN_LSS(center, extents) \ + if(LSSContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->IsLeaf()) + { + LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBTreeNode* node) +{ + // Perform LSS-AABB overlap test + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!LSSAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || LSSContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridLSSCollider::HybridLSSCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridLSSCollider::~HybridLSSCollider() +{ +} + +bool HybridLSSCollider::Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, lss, worldl, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + LSS_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + LSS_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/third-party/Opcode/OPC_LSSCollider.h b/third-party/Opcode/OPC_LSSCollider.h new file mode 100644 index 0000000..426564c --- /dev/null +++ b/third-party/Opcode/OPC_LSSCollider.h @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an LSS collider. + * \file OPC_LSSCollider.h + * \author Pierre Terdiman + * \date December, 28, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_LSSCOLLIDER_H__ +#define __OPC_LSSCOLLIDER_H__ + + struct OPCODE_API LSSCache : VolumeCache + { + LSSCache() + { + Previous.mP0 = IcePoint(0.0f, 0.0f, 0.0f); + Previous.mP1 = IcePoint(0.0f, 0.0f, 0.0f); + Previous.mRadius = 0.0f; + FatCoeff = 1.1f; + } + + // Cached faces signature + LSS Previous; //!< LSS used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat LSS + }; + + class OPCODE_API LSSCollider : public VolumeCollider + { + public: + // Constructor / Destructor + LSSCollider(); + virtual ~LSSCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in local space + * \param model [in] Opcode model to collide with + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + // + bool Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree); + protected: + // LSS in model space + IceSegment mSeg; //!< IceSegment + float mRadius2; //!< LSS radius squared + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL LSSContainsBox(const IcePoint& bc, const IcePoint& be); + inline_ BOOL LSSAABBOverlap(const IcePoint& center, const IcePoint& extents); + inline_ BOOL LSSTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); + // Init methods + BOOL InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridLSSCollider : public LSSCollider + { + public: + // Constructor / Destructor + HybridLSSCollider(); + virtual ~HybridLSSCollider(); + + bool Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_LSSCOLLIDER_H__ diff --git a/third-party/Opcode/OPC_LSSTriOverlap.h b/third-party/Opcode/OPC_LSSTriOverlap.h new file mode 100644 index 0000000..9957534 --- /dev/null +++ b/third-party/Opcode/OPC_LSSTriOverlap.h @@ -0,0 +1,679 @@ +// Following code from Magic-Software (http://www.magic-software.com/) +// A bit modified for Opcode + +static const float gs_fTolerance = 1e-05f; + +static float OPC_PointTriangleSqrDist(const IcePoint& Point, const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) +{ + // Hook + IcePoint TriEdge0 = p1 - p0; + IcePoint TriEdge1 = p2 - p0; + + IcePoint kDiff = p0 - Point; + float fA00 = TriEdge0.SquareMagnitude(); + float fA01 = TriEdge0 | TriEdge1; + float fA11 = TriEdge1.SquareMagnitude(); + float fB0 = kDiff | TriEdge0; + float fB1 = kDiff | TriEdge1; + float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11 - fA01*fA01); + float fS = fA01*fB1-fA11*fB0; + float fT = fA01*fB0-fA00*fB1; + float fSqrDist; + + if(fS + fT <= fDet) + { + if(fS < 0.0f) + { + if(fT < 0.0f) // region 4 + { + if(fB0 < 0.0f) + { + if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + if(fB1 >= 0.0f) fSqrDist = fC; + else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else // region 3 + { + if(fB1 >= 0.0f) fSqrDist = fC; + else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else if(fT < 0.0f) // region 5 + { + if(fB0 >= 0.0f) fSqrDist = fC; + else if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else // region 0 + { + // minimum at interior IcePoint + if(fDet==0.0f) + { + fSqrDist = MAX_FLOAT; + } + else + { + float fInvDet = 1.0f/fDet; + fS *= fInvDet; + fT *= fInvDet; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + } + else + { + float fTmp0, fTmp1, fNumer, fDenom; + + if(fS < 0.0f) // region 2 + { + fTmp0 = fA01 + fB0; + fTmp1 = fA11 + fB1; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else + { + fS = fNumer/fDenom; + fT = 1.0f - fS; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + else + { + if(fTmp1 <= 0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else if(fB1 >= 0.0f) fSqrDist = fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else if(fT < 0.0f) // region 6 + { + fTmp0 = fA01 + fB1; + fTmp1 = fA00 + fB0; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fT = fNumer/fDenom; + fS = 1.0f - fT; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + else + { + if(fTmp1 <= 0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(fB0 >= 0.0f) fSqrDist = fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + } + else // region 1 + { + fNumer = fA11 + fB1 - fA01 - fB0; + if(fNumer <= 0.0f) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else + { + fS = fNumer/fDenom; + fT = 1.0f - fS; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + } + } + return fabsf(fSqrDist); +} + +static float OPC_SegmentSegmentSqrDist(const IceSegment& rkSeg0, const IceSegment& rkSeg1) +{ + // Hook + IcePoint rkSeg0Direction = rkSeg0.ComputeDirection(); + IcePoint rkSeg1Direction = rkSeg1.ComputeDirection(); + + IcePoint kDiff = rkSeg0.mP0 - rkSeg1.mP0; + float fA00 = rkSeg0Direction.SquareMagnitude(); + float fA01 = -rkSeg0Direction.Dot(rkSeg1Direction); + float fA11 = rkSeg1Direction.SquareMagnitude(); + float fB0 = kDiff.Dot(rkSeg0Direction); + float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11-fA01*fA01); + + float fB1, fS, fT, fSqrDist, fTmp; + + if(fDet>=gs_fTolerance) + { + // line segments are not parallel + fB1 = -kDiff.Dot(rkSeg1Direction); + fS = fA01*fB1-fA11*fB0; + fT = fA01*fB0-fA00*fB1; + + if(fS >= 0.0f) + { + if(fS <= fDet) + { + if(fT >= 0.0f) + { + if(fT <= fDet) // region 0 (interior) + { + // minimum at two interior points of 3D lines + float fInvDet = 1.0f/fDet; + fS *= fInvDet; + fT *= fInvDet; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + else // region 3 (side) + { + fTmp = fA01+fB0; + if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + } + else // region 7 (side) + { + if(fB0>=0.0f) fSqrDist = fC; + else if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + } + else + { + if ( fT >= 0.0 ) + { + if ( fT <= fDet ) // region 1 (side) + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + else // region 2 (corner) + { + fTmp = fA01+fB0; + if ( -fTmp <= fA00 ) + { + if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + else + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + } + } + else // region 8 (corner) + { + if ( -fB0 < fA00 ) + { + if(fB0>=0.0f) fSqrDist = fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + } + } + } + else + { + if ( fT >= 0.0f ) + { + if ( fT <= fDet ) // region 5 (side) + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + else // region 4 (corner) + { + fTmp = fA01+fB0; + if ( fTmp < 0.0f ) + { + if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + else + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + } + else // region 6 (corner) + { + if ( fB0 < 0.0f ) + { + if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + } + } + else + { + // line segments are parallel + if ( fA01 > 0.0f ) + { + // direction vectors form an obtuse angle + if ( fB0 >= 0.0f ) + { + fSqrDist = fC; + } + else if ( -fB0 <= fA00 ) + { + fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fB1 = -kDiff.Dot(rkSeg1Direction); + fTmp = fA00+fB0; + if ( -fTmp >= fA01 ) + { + fSqrDist = fA00+fA11+fC+2.0f*(fA01+fB0+fB1); + } + else + { + fT = -fTmp/fA01; + fSqrDist = fA00+2.0f*fB0+fC+fT*(fA11*fT+2.0f*(fA01+fB1)); + } + } + } + else + { + // direction vectors form an acute angle + if ( -fB0 >= fA00 ) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else if ( fB0 <= 0.0f ) + { + fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fB1 = -kDiff.Dot(rkSeg1Direction); + if ( fB0 >= -fA01 ) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fT = -fB0/fA01; + fSqrDist = fC+fT*(2.0f*fB1+fA11*fT); + } + } + } + } + return fabsf(fSqrDist); +} + +inline_ float OPC_SegmentRaySqrDist(const IceSegment& rkSeg0, const Ray& rkSeg1) +{ + return OPC_SegmentSegmentSqrDist(rkSeg0, IceSegment(rkSeg1.mOrig, rkSeg1.mOrig + rkSeg1.mDir)); +} + +static float OPC_SegmentTriangleSqrDist(const IceSegment& segment, const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) +{ + // Hook + const IcePoint TriEdge0 = p1 - p0; + const IcePoint TriEdge1 = p2 - p0; + + const IcePoint& rkSegOrigin = segment.GetOrigin(); + IcePoint rkSegDirection = segment.ComputeDirection(); + + IcePoint kDiff = p0 - rkSegOrigin; + float fA00 = rkSegDirection.SquareMagnitude(); + float fA01 = -rkSegDirection.Dot(TriEdge0); + float fA02 = -rkSegDirection.Dot(TriEdge1); + float fA11 = TriEdge0.SquareMagnitude(); + float fA12 = TriEdge0.Dot(TriEdge1); + float fA22 = TriEdge1.Dot(TriEdge1); + float fB0 = -kDiff.Dot(rkSegDirection); + float fB1 = kDiff.Dot(TriEdge0); + float fB2 = kDiff.Dot(TriEdge1); + float fCof00 = fA11*fA22-fA12*fA12; + float fCof01 = fA02*fA12-fA01*fA22; + float fCof02 = fA01*fA12-fA02*fA11; + float fDet = fA00*fCof00+fA01*fCof01+fA02*fCof02; + + Ray kTriSeg; + IcePoint kPt; + float fSqrDist, fSqrDist0; + + if(fabsf(fDet)>=gs_fTolerance) + { + float fCof11 = fA00*fA22-fA02*fA02; + float fCof12 = fA02*fA01-fA00*fA12; + float fCof22 = fA00*fA11-fA01*fA01; + float fInvDet = 1.0f/fDet; + float fRhs0 = -fB0*fInvDet; + float fRhs1 = -fB1*fInvDet; + float fRhs2 = -fB2*fInvDet; + + float fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2; + float fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2; + float fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2; + + if ( fR < 0.0f ) + { + if ( fS+fT <= 1.0f ) + { + if ( fS < 0.0f ) + { + if ( fT < 0.0f ) // region 4m + { + // min on face s=0 or t=0 or r=0 + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge1; + fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge0; + fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); + if(fSqrDist0 1 + { + if ( fS+fT <= 1.0f ) + { + if ( fS < 0.0f ) + { + if ( fT < 0.0f ) // region 4p + { + // min on face s=0 or t=0 or r=1 + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge1; + fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge0; + fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); + if(fSqrDist0GetTriangle(triangle_index); + * // Setup pointers to vertices for the collision system + * triangle.Vertex[0] = MyMesh->GetVertex(Tri->mVRef[0]); + * triangle.Vertex[1] = MyMesh->GetVertex(Tri->mVRef[1]); + * triangle.Vertex[2] = MyMesh->GetVertex(Tri->mVRef[2]); + * } + * + * // Setup callbacks + * MeshInterface0->SetCallback(ColCallback, udword(Mesh0)); + * MeshInterface1->SetCallback(ColCallback, udword(Mesh1)); + * \endcode + * + * Of course, you should make this callback as fast as possible. And you're also not supposed + * to modify the geometry *after* the collision trees have been built. The alternative was to + * store the geometry & topology in the collision system as well (as in RAPID) but we have found + * this approach to waste a lot of ram in many cases. + * + * + * POINTERS: + * + * If you're internally using the following canonical structures: + * - a vertex made of three 32-bits floating IcePoint values + * - a triangle made of three 32-bits integer vertex references + * ...then you may want to use pointers instead of callbacks. This is the same, except OPCODE will directly + * use provided pointers to access the topology and geometry, without using a callback. It might be faster, + * but probably not as safe. Pointers have been introduced in OPCODE 1.2. + * + * Ex: + * + * \code + * // Setup pointers + * MeshInterface0->SetPointers(Mesh0->GetFaces(), Mesh0->GetVerts()); + * MeshInterface1->SetPointers(Mesh1->GetFaces(), Mesh1->GetVerts()); + * \endcode + * + * + * STRIDES: + * + * If your vertices are D3D-like entities interleaving a position, a normal and/or texture coordinates + * (i.e. if your vertices are FVFs), you might want to use a vertex stride to skip extra data OPCODE + * doesn't need. Using a stride shouldn't be notably slower than not using it, but it might increase + * cache misses. Please also note that you *shouldn't* read from AGP or video-memory buffers ! + * + * + * In any case, compilation flags are here to select callbacks/pointers/strides at compile time, so + * choose what's best for your application. All of this has been wrapped into this MeshInterface. + * + * \class MeshInterface + * \author Pierre Terdiman + * \version 1.3 + * \date November, 27, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +MeshInterface::MeshInterface() : +#ifdef OPC_USE_CALLBACKS + mUserData (null), + mObjCallback (null), +#else + mTris (null), + mVerts (null), + #ifdef OPC_USE_STRIDE + mTriStride (sizeof(IndexedTriangle)), + mVertexStride (sizeof(IcePoint)), + #endif +#endif + mNbTris (0), + mNbVerts (0) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +MeshInterface::~MeshInterface() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the mesh interface is valid, i.e. things have been setup correctly. + * \return true if valid + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool MeshInterface::IsValid() const +{ + if(!mNbTris || !mNbVerts) return false; +#ifdef OPC_USE_CALLBACKS + if(!mObjCallback) return false; +#else + if(!mTris || !mVerts) return false; +#endif + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the mesh itself is valid. + * Currently we only look for degenerate faces. + * \return number of degenerate faces + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword MeshInterface::CheckTopology() const +{ + // Check topology. If the model contains degenerate faces, collision report can be wrong in some cases. + // e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner + // you can try this: www.codercorner.com/Consolidation.zip + + udword NbDegenerate = 0; + + VertexPointers VP; + + // Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for + // redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides). + for(udword i=0;i= 0.0f; + } + }; + +#ifdef OPC_USE_CALLBACKS + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE to request vertices from the app. + * \param triangle_index [in] face index for which the system is requesting the vertices + * \param triangle [out] triangle's vertices (must be provided by the user) + * \param user_data [in] user-defined data from SetCallback() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef void (*RequestCallback) (udword triangle_index, VertexPointers& triangle, void* user_data); +#endif + + class OPCODE_API MeshInterface + { + public: + // Constructor / Destructor + MeshInterface(); + ~MeshInterface(); + // Common settings + inline_ udword GetNbTriangles() const { return mNbTris; } + inline_ udword GetNbVertices() const { return mNbVerts; } + inline_ void SetNbTriangles(udword nb) { mNbTris = nb; } + inline_ void SetNbVertices(udword nb) { mNbVerts = nb; } + +#ifdef OPC_USE_CALLBACKS + // Callback settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index. + * \param callback [in] user-defined callback + * \param user_data [in] user-defined data + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetCallback(RequestCallback callback, void* user_data); + inline_ void* GetUserData() const { return mUserData; } + inline_ RequestCallback GetCallback() const { return mObjCallback; } +#else + // Pointers settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object. + * \param tris [in] pointer to triangles + * \param verts [in] pointer to vertices + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetPointers(const IndexedTriangle* tris, const IcePoint* verts); + inline_ const IndexedTriangle* GetTris() const { return mTris; } + inline_ const IcePoint* GetVerts() const { return mVerts; } + + #ifdef OPC_USE_STRIDE + // Strides settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Strides control + * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices. + * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(IcePoint) bytes are used to get vertex position. + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetStrides(udword tri_stride=sizeof(IndexedTriangle), udword vertex_stride=sizeof(IcePoint)); + inline_ udword GetTriStride() const { return mTriStride; } + inline_ udword GetVertexStride() const { return mVertexStride; } + #endif +#endif + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Fetches a triangle given a triangle index. + * \param vp [out] required triangle's vertex pointers + * \param index [in] triangle index + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void GetTriangle(VertexPointers& vp, udword index) const + { +#ifdef OPC_USE_CALLBACKS + (mObjCallback)(index, vp, mUserData); +#else + #ifdef OPC_USE_STRIDE + const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride); + vp.Vertex[0] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[0] * mVertexStride); + vp.Vertex[1] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[1] * mVertexStride); + vp.Vertex[2] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[2] * mVertexStride); + #else + const IndexedTriangle* T = &mTris[index]; + vp.Vertex[0] = &mVerts[T->mVRef[0]]; + vp.Vertex[1] = &mVerts[T->mVRef[1]]; + vp.Vertex[2] = &mVerts[T->mVRef[2]]; + #endif +#endif + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Remaps client's mesh according to a permutation. + * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles) + * \param permutation [in] list of triangle indices + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool RemapClient(udword nb_indices, const udword* permutation) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the mesh interface is valid, i.e. things have been setup correctly. + * \return true if valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool IsValid() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the mesh itself is valid. + * Currently we only look for degenerate faces. + * \return number of degenerate faces + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + udword CheckTopology() const; + private: + + udword mNbTris; //!< Number of triangles in the input model + udword mNbVerts; //!< Number of vertices in the input model +#ifdef OPC_USE_CALLBACKS + // User callback + void* mUserData; //!< User-defined data sent to callback + RequestCallback mObjCallback; //!< Object callback +#else + // User pointers + const IndexedTriangle* mTris; //!< Array of indexed triangles + const IcePoint* mVerts; //!< Array of vertices + #ifdef OPC_USE_STRIDE + udword mTriStride; //!< Possible triangle stride in bytes [Opcode 1.3] + udword mVertexStride; //!< Possible vertex stride in bytes [Opcode 1.3] + #endif +#endif + }; + +#endif //__OPC_MESHINTERFACE_H__ \ No newline at end of file diff --git a/third-party/Opcode/OPC_Model.cpp b/third-party/Opcode/OPC_Model.cpp new file mode 100644 index 0000000..a9e660c --- /dev/null +++ b/third-party/Opcode/OPC_Model.cpp @@ -0,0 +1,222 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for OPCODE models. + * \file OPC_Model.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * The main collision wrapper, for all trees. Supported trees are: + * - Normal trees (2*N-1 nodes, full size) + * - No-leaf trees (N-1 nodes, full size) + * - Quantized trees (2*N-1 nodes, half size) + * - Quantized no-leaf trees (N-1 nodes, half size) + * + * Usage: + * + * 1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp). + * Keep it around in your app, since a pointer to this interface is saved internally and + * used until you release the collision structures. + * + * 2) Build a Model using a creation structure: + * + * \code + * Model Sample; + * + * OPCODECREATE OPCC; + * OPCC.IMesh = ...; + * OPCC.Rules = ...; + * OPCC.NoLeaf = ...; + * OPCC.Quantized = ...; + * OPCC.KeepOriginal = ...; + * bool Status = Sample.Build(OPCC); + * \endcode + * + * 3) Create a tree collider and set it up: + * + * \code + * AABBTreeCollider TC; + * TC.SetFirstContact(...); + * TC.SetFullBoxBoxTest(...); + * TC.SetFullPrimBoxTest(...); + * TC.SetTemporalCoherence(...); + * \endcode + * + * 4) Perform a collision query + * + * \code + * // Setup cache + * static BVTCache ColCache; + * ColCache.Model0 = &Model0; + * ColCache.Model1 = &Model1; + * + * // Collision query + * bool IsOk = TC.Collide(ColCache, World0, World1); + * + * // Get collision status => if true, objects overlap + * BOOL Status = TC.GetContactStatus(); + * + * // Number of colliding pairs and list of pairs + * udword NbPairs = TC.GetNbPairs(); + * const Pair* p = TC.GetPairs() + * \endcode + * + * 5) Stats + * + * \code + * Model0.GetUsedBytes() = number of bytes used for this collision tree + * TC.GetNbBVBVTests() = number of BV-BV overlap tests performed during last query + * TC.GetNbPrimPrimTests() = number of Triangle-Triangle overlap tests performed during last query + * TC.GetNbBVPrimTests() = number of Triangle-BV overlap tests performed during last query + * \endcode + * + * \class Model + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Model::Model() +{ +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + mHull = null; +#endif // __MESHMERIZER_H__ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Model::~Model() +{ + Release(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases the model. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Model::Release() +{ + ReleaseBase(); +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + DELETESINGLE(mHull); +#endif // __MESHMERIZER_H__ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Model::Build(const OPCODECREATE& create) +{ + // 1) Checkings + if(!create.mIMesh || !create.mIMesh->IsValid()) return false; + + // For this model, we only support complete trees + if (create.mSettings.mLimit != 1) return SetIceError; // ("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null); + + // Look for degenerate faces. + udword NbDegenerate = create.mIMesh->CheckTopology(); + if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); + // We continue nonetheless.... + + Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam] + + // 1-1) Setup mesh interface automatically [Opcode 1.3] + SetMeshInterface(create.mIMesh); + + // Special case for 1-triangle meshes [Opcode 1.3] + udword NbTris = create.mIMesh->GetNbTriangles(); + if(NbTris==1) + { + // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway. + // It's a waste to use a "model" for this but at least it will work. + mModelCode |= OPC_SINGLE_NODE; + return true; + } + + // 2) Build a generic AABB Tree. + mSource = new AABBTree; + CHECKALLOC(mSource); + + // 2-1) Setup a builder. Our primitives here are triangles from input mesh, + // so we use an AABBTreeOfTrianglesBuilder..... + { + AABBTreeOfTrianglesBuilder TB; + TB.mIMesh = create.mIMesh; + TB.mSettings = create.mSettings; + TB.mNbPrimitives = NbTris; + if(!mSource->Build(&TB)) return false; + } + + // 3) Create an optimized tree according to user-settings + if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false; + + // 3-2) Create optimized tree + if(!mTree->Build(mSource)) return false; + + // 3-3) Delete generic tree if needed + if(!create.mKeepOriginal) DELETESINGLE(mSource); + +#ifdef __MESHMERIZER_H__ + // 4) Convex hull + if(create.mCollisionHull) + { + // Create hull + mHull = new CollisionHull; + CHECKALLOC(mHull); + + CONVEXHULLCREATE CHC; + // ### doesn't work with strides + CHC.NbVerts = create.mIMesh->GetNbVertices(); + CHC.Vertices = create.mIMesh->GetVerts(); + CHC.UnifyNormals = true; + CHC.ReduceVertices = true; + CHC.WordFaces = false; + mHull->Compute(CHC); + } +#endif // __MESHMERIZER_H__ + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword Model::GetUsedBytes() const +{ + if(!mTree) return 0; + return mTree->GetUsedBytes(); +} diff --git a/third-party/Opcode/OPC_Model.h b/third-party/Opcode/OPC_Model.h new file mode 100644 index 0000000..1b39e60 --- /dev/null +++ b/third-party/Opcode/OPC_Model.h @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for OPCODE models. + * \file OPC_Model.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_MODEL_H__ +#define __OPC_MODEL_H__ + + class OPCODE_API Model : public BaseModel + { + public: + // Constructor/Destructor + Model(); + virtual ~Model(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Build(const OPCODECREATE& create); + +#ifdef __MESHMERIZER_H__ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the collision hull. + * \return the collision hull if it exists + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const CollisionHull* GetHull() const { return mHull; } +#endif // __MESHMERIZER_H__ + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) udword GetUsedBytes() const; + + private: +#ifdef __MESHMERIZER_H__ + CollisionHull* mHull; //!< Possible convex hull +#endif // __MESHMERIZER_H__ + // Internal methods + void Release(); + }; + +#endif //__OPC_MODEL_H__ \ No newline at end of file diff --git a/third-party/Opcode/OPC_OBBCollider.cpp b/third-party/Opcode/OPC_OBBCollider.cpp new file mode 100644 index 0000000..8761fce --- /dev/null +++ b/third-party/Opcode/OPC_OBBCollider.cpp @@ -0,0 +1,767 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an OBB collider. + * \file OPC_OBBCollider.cpp + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an OBB-vs-tree collider. + * + * \class OBBCollider + * \author Pierre Terdiman + * \version 1.3 + * \date January, 1st, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#include "OPC_BoxBoxOverlap.h" +#include "OPC_TriBoxOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! OBB-triangle test +#define OBB_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + /* Transform them in a common space */ \ + TransformPoint(mLeafVerts[0], *VP.Vertex[0], mRModelToBox, mTModelToBox); \ + TransformPoint(mLeafVerts[1], *VP.Vertex[1], mRModelToBox, mTModelToBox); \ + TransformPoint(mLeafVerts[2], *VP.Vertex[2], mRModelToBox, mTModelToBox); \ + /* Perform triangle-box overlap test */ \ + if(TriBoxOverlap()) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OBBCollider::OBBCollider() : mFullBoxBoxTest(true) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OBBCollider::~OBBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* OBBCollider::ValidateSettings() +{ + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; + + return VolumeCollider::ValidateSettings(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision OBB in local space + * \param model [in] Opcode model to collide with + * \param worldb [in] OBB's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBBCollider::Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box, worldb, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] a box cache + * \param box [in] obb in local space + * \param worldb [in] obb's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL OBBCollider::InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute obb in world space + mBoxExtents = box.mExtents; + + Matrix4x4 WorldB; + + if(worldb) + { + WorldB = Matrix4x4( box.mRot * Matrix3x3(*worldb) ); + WorldB.SetTrans(box.mCenter * *worldb); + } + else + { + WorldB = box.mRot; + WorldB.SetTrans(box.mCenter); + } + + // Setup matrices + Matrix4x4 InvWorldB; + InvertPRMatrix(InvWorldB, WorldB); + + if(worldm) + { + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + Matrix4x4 WorldBtoM = WorldB * InvWorldM; + Matrix4x4 WorldMtoB = *worldm * InvWorldB; + + mRModelToBox = WorldMtoB; WorldMtoB.GetTrans(mTModelToBox); + mRBoxToModel = WorldBtoM; WorldBtoM.GetTrans(mTBoxToModel); + } + else + { + mRModelToBox = InvWorldB; InvWorldB.GetTrans(mTModelToBox); + mRBoxToModel = WorldB; WorldB.GetTrans(mTBoxToModel); + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the box (and set contact status if needed) + OBB_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence: + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the box (and set contact status if needed) + OBB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // ### rewrite this + OBB TestBox(mTBoxToModel, mBoxExtents, mRBoxToModel); + + // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): + if(IsCacheValid(cache) && TestBox.IsInside(cache.FatBox)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat box so that coherence will work for subsequent frames + TestBox.mExtents *= cache.FatCoeff; + mBoxExtents *= cache.FatCoeff; + + // Update cache with query data (signature for cached faces) + cache.FatBox = TestBox; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + // Now we can precompute box-box data + + // Precompute absolute box-to-model rotation matrix + for(udword i=0;i<3;i++) + { + for(udword j=0;j<3;j++) + { + // Epsilon value prevents floating-IcePoint inaccuracies (strategy borrowed from RAPID) + mAR.m[i][j] = 1e-6f + fabsf(mRBoxToModel.m[i][j]); + } + } + + // Precompute bounds for box-in-box test + mB0 = mBoxExtents - mTModelToBox; + mB1 = - mBoxExtents - mTModelToBox; + + // Precompute box-box data - Courtesy of Erwin de Vries + mBBx1 = mBoxExtents.x*mAR.m[0][0] + mBoxExtents.y*mAR.m[1][0] + mBoxExtents.z*mAR.m[2][0]; + mBBy1 = mBoxExtents.x*mAR.m[0][1] + mBoxExtents.y*mAR.m[1][1] + mBoxExtents.z*mAR.m[2][1]; + mBBz1 = mBoxExtents.x*mAR.m[0][2] + mBoxExtents.y*mAR.m[1][2] + mBoxExtents.z*mAR.m[2][2]; + + mBB_1 = mBoxExtents.y*mAR.m[2][0] + mBoxExtents.z*mAR.m[1][0]; + mBB_2 = mBoxExtents.x*mAR.m[2][0] + mBoxExtents.z*mAR.m[0][0]; + mBB_3 = mBoxExtents.x*mAR.m[1][0] + mBoxExtents.y*mAR.m[0][0]; + mBB_4 = mBoxExtents.y*mAR.m[2][1] + mBoxExtents.z*mAR.m[1][1]; + mBB_5 = mBoxExtents.x*mAR.m[2][1] + mBoxExtents.z*mAR.m[0][1]; + mBB_6 = mBoxExtents.x*mAR.m[1][1] + mBoxExtents.y*mAR.m[0][1]; + mBB_7 = mBoxExtents.y*mAR.m[2][2] + mBoxExtents.z*mAR.m[1][2]; + mBB_8 = mBoxExtents.x*mAR.m[2][2] + mBoxExtents.z*mAR.m[0][2]; + mBB_9 = mBoxExtents.x*mAR.m[1][2] + mBoxExtents.y*mAR.m[0][2]; + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the OBB completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the OBB contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL OBBCollider::OBBContainsBox(const IcePoint& bc, const IcePoint& be) +{ + // I assume if all 8 box vertices are inside the OBB, so does the whole box. + // Sounds ok but maybe there's a better way? +/* +#define TEST_PT(a,b,c) \ + p.x=a; p.y=b; p.z=c; p+=bc; \ + f = p.x * mRModelToBox.m[0][0] + p.y * mRModelToBox.m[1][0] + p.z * mRModelToBox.m[2][0]; if(f>mB0.x || fmB0.y || fmB0.z || f NCx-NEx) return FALSE; + + float NCy = bc.x * mRModelToBox.m[0][1] + bc.y * mRModelToBox.m[1][1] + bc.z * mRModelToBox.m[2][1]; + float NEy = fabsf(mRModelToBox.m[0][1] * be.x) + fabsf(mRModelToBox.m[1][1] * be.y) + fabsf(mRModelToBox.m[2][1] * be.z); + + if(mB0.y < NCy+NEy) return FALSE; + if(mB1.y > NCy-NEy) return FALSE; + + float NCz = bc.x * mRModelToBox.m[0][2] + bc.y * mRModelToBox.m[1][2] + bc.z * mRModelToBox.m[2][2]; + float NEz = fabsf(mRModelToBox.m[0][2] * be.x) + fabsf(mRModelToBox.m[1][2] * be.y) + fabsf(mRModelToBox.m[2][2] * be.z); + + if(mB0.z < NCz+NEz) return FALSE; + if(mB1.z > NCz-NEz) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_OBB(center, extents) \ + if(OBBContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->IsLeaf()) + { + OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridOBBCollider::HybridOBBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridOBBCollider::~HybridOBBCollider() +{ +} + +bool HybridOBBCollider::Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box, worldb, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + OBB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + OBB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/third-party/Opcode/OPC_OBBCollider.h b/third-party/Opcode/OPC_OBBCollider.h new file mode 100644 index 0000000..9753384 --- /dev/null +++ b/third-party/Opcode/OPC_OBBCollider.h @@ -0,0 +1,142 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an OBB collider. + * \file OPC_OBBCollider.h + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_OBBCOLLIDER_H__ +#define __OPC_OBBCOLLIDER_H__ + + struct OPCODE_API OBBCache : VolumeCache + { + OBBCache() : FatCoeff(1.1f) + { + FatBox.mCenter.Zero(); + FatBox.mExtents.Zero(); + FatBox.mRot.Identity(); + } + + // Cached faces signature + OBB FatBox; //!< Box used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< extents multiplier used to create a fat box + }; + + class OPCODE_API OBBCollider : public VolumeCollider + { + public: + // Constructor / Destructor + OBBCollider(); + virtual ~OBBCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision OBB in local space + * \param model [in] Opcode model to collide with + * \param worldb [in] OBB's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: select between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Precomputed data + Matrix3x3 mAR; //!< Absolute rotation matrix + Matrix3x3 mRModelToBox; //!< Rotation from model space to obb space + Matrix3x3 mRBoxToModel; //!< Rotation from obb space to model space + IcePoint mTModelToBox; //!< Translation from model space to obb space + IcePoint mTBoxToModel; //!< Translation from obb space to model space + + IcePoint mBoxExtents; + IcePoint mB0; //!< - mTModelToBox + mBoxExtents + IcePoint mB1; //!< - mTModelToBox - mBoxExtents + + float mBBx1; + float mBBy1; + float mBBz1; + + float mBB_1; + float mBB_2; + float mBB_3; + float mBB_4; + float mBB_5; + float mBB_6; + float mBB_7; + float mBB_8; + float mBB_9; + + // Leaf description + IcePoint mLeafVerts[3]; //!< Triangle vertices + // Settings + bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL OBBContainsBox(const IcePoint& bc, const IcePoint& be); + inline_ BOOL BoxBoxOverlap(const IcePoint& extents, const IcePoint& center); + inline_ BOOL TriBoxOverlap(); + // Init methods + BOOL InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridOBBCollider : public OBBCollider + { + public: + // Constructor / Destructor + HybridOBBCollider(); + virtual ~HybridOBBCollider(); + + bool Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_OBBCOLLIDER_H__ diff --git a/third-party/Opcode/OPC_OptimizedTree.cpp b/third-party/Opcode/OPC_OptimizedTree.cpp new file mode 100644 index 0000000..a84ac5a --- /dev/null +++ b/third-party/Opcode/OPC_OptimizedTree.cpp @@ -0,0 +1,782 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for optimized trees. Implements 4 trees: + * - normal + * - no leaf + * - quantized + * - no leaf / quantized + * + * \file OPC_OptimizedTree.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A standard AABB tree. + * + * \class AABBCollisionTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A no-leaf AABB tree. + * + * \class AABBNoLeafTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized AABB tree. + * + * \class AABBQuantizedTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized no-leaf AABB tree. + * + * \class AABBQuantizedNoLeafTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +//! Compilation flag: +//! - true to fix quantized boxes (i.e. make sure they enclose the original ones) +//! - false to see the effects of quantization errors (faster, but wrong results in some cases) +static bool gFixQuantized = true; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds an implicit tree from a standard one. An implicit tree is a complete tree (2*N-1 nodes) whose negative + * box pointers and primitive pointers have been made implicit, hence packing 3 pointers in one. + * + * Layout for implicit trees: + * Node: + * - box + * - data (32-bits value) + * + * if data's LSB = 1 => remaining bits are a primitive pointer + * else remaining bits are a P-node pointer, and N = P + 1 + * + * \relates AABBCollisionNode + * \fn _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) + * \param linear [in] base address of destination nodes + * \param box_id [in] index of destination node + * \param current_id [in] current running index + * \param current_node [in] current node from input tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) +{ + // Current node from input tree is "current_node". Must be flattened into "linear[boxid]". + + // Store the AABB + current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); + current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); + // Store remaining info + if(current_node->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(current_node->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = current_node->GetPrimitives()[0]; + // Setup box data as the primitive index, marked as leaf + linear[box_id].mData = (PrimitiveIndex<<1)|1; + } + else + { + // To make the negative one implicit, we must store P and N in successive order + udword PosID = current_id++; // Get a new id for positive child + udword NegID = current_id++; // Get a new id for negative child + // Setup box data as the forthcoming new P pointer + linear[box_id].mData = (udword)&linear[PosID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mData&1)); + // Recurse with new IDs + _BuildCollisionTree(linear, PosID, current_id, current_node->GetPos()); + _BuildCollisionTree(linear, NegID, current_id, current_node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a "no-leaf" tree from a standard one. This is a tree whose leaf nodes have been removed. + * + * Layout for no-leaf trees: + * + * Node: + * - box + * - P pointer => a node (LSB=0) or a primitive (LSB=1) + * - N pointer => a node (LSB=0) or a primitive (LSB=1) + * + * \relates AABBNoLeafNode + * \fn _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) + * \param linear [in] base address of destination nodes + * \param box_id [in] index of destination node + * \param current_id [in] current running index + * \param current_node [in] current node from input tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) +{ + const AABBTreeNode* P = current_node->GetPos(); + const AABBTreeNode* N = current_node->GetNeg(); + // Leaf nodes here?! + ASSERT(P); + ASSERT(N); + // Internal node => keep the box + current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); + current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); + + if(P->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(P->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = P->GetPrimitives()[0]; + // Setup prev box data as the primitive index, marked as leaf + linear[box_id].mPosData = (PrimitiveIndex<<1)|1; + } + else + { + // Get a new id for positive child + udword PosID = current_id++; + // Setup box data + linear[box_id].mPosData = (udword)&linear[PosID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mPosData&1)); + // Recurse + _BuildNoLeafTree(linear, PosID, current_id, P); + } + + if(N->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(N->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = N->GetPrimitives()[0]; + // Setup prev box data as the primitive index, marked as leaf + linear[box_id].mNegData = (PrimitiveIndex<<1)|1; + } + else + { + // Get a new id for negative child + udword NegID = current_id++; + // Setup box data + linear[box_id].mNegData = (udword)&linear[NegID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mNegData&1)); + // Recurse + _BuildNoLeafTree(linear, NegID, current_id, N); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollisionTree::AABBCollisionTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollisionTree::~AABBCollisionTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + if(mNbNodes!=NbNodes) // Same number of nodes => keep moving + { + mNbNodes = NbNodes; + DELETEARRAY(mNodes); + mNodes = new AABBCollisionNode[mNbNodes]; + CHECKALLOC(mNodes); + } + + // Build the tree + udword CurID = 1; + _BuildCollisionTree(mNodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Refit(const MeshInterface* mesh_interface) +{ + ASSERT(!"Not implemented since AABBCollisionTrees have twice as more nodes to refit as AABBNoLeafTrees!"); + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Walk(GenericWalkingCallback callback, void* user_data) const +{ + if(!callback) return false; + + struct Local + { + static void _Walk(const AABBCollisionNode* current_node, GenericWalkingCallback callback, void* user_data) + { + if(!current_node || !(callback)(current_node, user_data)) return; + + if(!current_node->IsLeaf()) + { + _Walk(current_node->GetPos(), callback, user_data); + _Walk(current_node->GetNeg(), callback, user_data); + } + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBNoLeafTree::AABBNoLeafTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBNoLeafTree::~AABBNoLeafTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + if(mNbNodes!=NbTriangles-1) // Same number of nodes => keep moving + { + mNbNodes = NbTriangles-1; + DELETEARRAY(mNodes); + mNodes = new AABBNoLeafNode[mNbNodes]; + CHECKALLOC(mNodes); + } + + // Build the tree + udword CurID = 1; + _BuildNoLeafTree(mNodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + return true; +} + +inline_ void ComputeMinMax(IcePoint& min, IcePoint& max, const VertexPointers& vp) +{ + // Compute triangle's AABB = a leaf box +#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much + min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + + min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + + min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); + max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); +#else + min = *vp.Vertex[0]; + max = *vp.Vertex[0]; + min.Min(*vp.Vertex[1]); + max.Max(*vp.Vertex[1]); + min.Min(*vp.Vertex[2]); + max.Max(*vp.Vertex[2]); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface) +{ + // Checkings + if(!mesh_interface) return false; + + // Bottom-up update + VertexPointers VP; + IcePoint Min,Max; + IcePoint Min_,Max_; + udword Index = mNbNodes; + while(Index--) + { + AABBNoLeafNode& Current = mNodes[Index]; + + if(Current.HasPosLeaf()) + { + mesh_interface->GetTriangle(VP, Current.GetPosPrimitive()); + ComputeMinMax(Min, Max, VP); + } + else + { + const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; + CurrentBox.GetMin(Min); + CurrentBox.GetMax(Max); + } + + if(Current.HasNegLeaf()) + { + mesh_interface->GetTriangle(VP, Current.GetNegPrimitive()); + ComputeMinMax(Min_, Max_, VP); + } + else + { + const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; + CurrentBox.GetMin(Min_); + CurrentBox.GetMax(Max_); + } +#ifdef OPC_USE_FCOMI + Min.x = FCMin2(Min.x, Min_.x); + Max.x = FCMax2(Max.x, Max_.x); + Min.y = FCMin2(Min.y, Min_.y); + Max.y = FCMax2(Max.y, Max_.y); + Min.z = FCMin2(Min.z, Min_.z); + Max.z = FCMax2(Max.z, Max_.z); +#else + Min.Min(Min_); + Max.Max(Max_); +#endif + Current.mAABB.SetMinMax(Min, Max); + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const +{ + if(!callback) return false; + + struct Local + { + static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data) + { + if(!current_node || !(callback)(current_node, user_data)) return; + + if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); + if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + +// Quantization notes: +// - We could use the highest bits of mData to store some more quantized bits. Dequantization code +// would be slightly more complex, but number of overlap tests would be reduced (and anyhow those +// bits are currently wasted). Of course it's not possible if we move to 16 bits mData. +// - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion. +// - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some +// lazy-dequantization which may save some work in case of early exits). At the very least some +// muls could be saved by precomputing several more matrices. But maybe not worth the pain. +// - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has +// been scaled, for example. +// - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed +// number of quantization bits. Even better, could probably be best delta-encoded. + + +// Find max values. Some people asked why I wasn't simply using the first node. Well, I can't. +// I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal +// centers/extents in order to quantize them. The first node would only give a single center and +// a single extents. While extents would be the biggest, the center wouldn't. +#define FIND_MAX_VALUES \ + /* Get max values */ \ + IcePoint CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ + IcePoint EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ + for(udword i=0;iCMax.x) CMax.x = fabsf(Nodes[i].mAABB.mCenter.x); \ + if(fabsf(Nodes[i].mAABB.mCenter.y)>CMax.y) CMax.y = fabsf(Nodes[i].mAABB.mCenter.y); \ + if(fabsf(Nodes[i].mAABB.mCenter.z)>CMax.z) CMax.z = fabsf(Nodes[i].mAABB.mCenter.z); \ + if(fabsf(Nodes[i].mAABB.mExtents.x)>EMax.x) EMax.x = fabsf(Nodes[i].mAABB.mExtents.x); \ + if(fabsf(Nodes[i].mAABB.mExtents.y)>EMax.y) EMax.y = fabsf(Nodes[i].mAABB.mExtents.y); \ + if(fabsf(Nodes[i].mAABB.mExtents.z)>EMax.z) EMax.z = fabsf(Nodes[i].mAABB.mExtents.z); \ + } + +#define INIT_QUANTIZATION \ + udword nbc=15; /* Keep one bit for sign */ \ + udword nbe=15; /* Keep one bit for fix */ \ + if(!gFixQuantized) nbe++; \ + \ + /* Compute quantization coeffs */ \ + IcePoint CQuantCoeff, EQuantCoeff; \ + CQuantCoeff.x = CMax.x!=0.0f ? float((1<Min[j]) mNodes[i].mAABB.mExtents[j]++; \ + else FixMe=false; \ + /* Prevent wrapping */ \ + if(!mNodes[i].mAABB.mExtents[j]) \ + { \ + mNodes[i].mAABB.mExtents[j]=0xffff; \ + FixMe=false; \ + } \ + }while(FixMe); \ + } \ + } + +#define REMAP_DATA(member) \ + /* Fix data */ \ + Data = Nodes[i].member; \ + if(!(Data&1)) \ + { \ + /* Compute box number */ \ + udword Nb = (Data - udword(Nodes))/Nodes[i].GetNodeSize(); \ + Data = udword(&mNodes[Nb]); \ + } \ + /* ...remapped */ \ + mNodes[i].member = Data; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedTree::AABBQuantizedTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedTree::~AABBQuantizedTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBQuantizedTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + mNbNodes = NbNodes; + DELETEARRAY(mNodes); + AABBCollisionNode* Nodes = new AABBCollisionNode[mNbNodes]; + CHECKALLOC(Nodes); + + // Build the tree + udword CurID = 1; + _BuildCollisionTree(Nodes, 0, CurID, tree); + + // Quantize + { + mNodes = new AABBQuantizedNode[mNbNodes]; + CHECKALLOC(mNodes); + + // Get max values + FIND_MAX_VALUES + + // Quantization + INIT_QUANTIZATION + + // Quantize + udword Data; + for(udword i=0;iIsLeaf()) + { + _Walk(current_node->GetPos(), callback, user_data); + _Walk(current_node->GetNeg(), callback, user_data); + } + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBQuantizedNoLeafTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + mNbNodes = NbTriangles-1; + DELETEARRAY(mNodes); + AABBNoLeafNode* Nodes = new AABBNoLeafNode[mNbNodes]; + CHECKALLOC(Nodes); + + // Build the tree + udword CurID = 1; + _BuildNoLeafTree(Nodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + // Quantize + { + mNodes = new AABBQuantizedNoLeafNode[mNbNodes]; + CHECKALLOC(mNodes); + + // Get max values + FIND_MAX_VALUES + + // Quantization + INIT_QUANTIZATION + + // Quantize + udword Data; + for(udword i=0;iHasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); + if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} diff --git a/third-party/Opcode/OPC_OptimizedTree.h b/third-party/Opcode/OPC_OptimizedTree.h new file mode 100644 index 0000000..c36e21e --- /dev/null +++ b/third-party/Opcode/OPC_OptimizedTree.h @@ -0,0 +1,206 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for optimized trees. + * \file OPC_OptimizedTree.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_OPTIMIZEDTREE_H__ +#define __OPC_OPTIMIZEDTREE_H__ + + //! Common interface for a node of an implicit tree + #define IMPLEMENT_IMPLICIT_NODE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + inline_ base_class() : mData(0) {} \ + inline_ ~base_class() {} \ + /* Leaf test */ \ + inline_ BOOL IsLeaf() const { return mData&1; } \ + /* Data access */ \ + inline_ const base_class* GetPos() const { return (base_class*)mData; } \ + inline_ const base_class* GetNeg() const { return ((base_class*)mData)+1; } \ + inline_ udword GetPrimitive() const { return (mData>>1); } \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + \ + volume mAABB; \ + udword mData; + + //! Common interface for a node of a no-leaf tree + #define IMPLEMENT_NOLEAF_NODE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + inline_ base_class() : mPosData(0), mNegData(0) {} \ + inline_ ~base_class() {} \ + /* Leaf tests */ \ + inline_ BOOL HasPosLeaf() const { return mPosData&1; } \ + inline_ BOOL HasNegLeaf() const { return mNegData&1; } \ + /* Data access */ \ + inline_ const base_class* GetPos() const { return (base_class*)mPosData; } \ + inline_ const base_class* GetNeg() const { return (base_class*)mNegData; } \ + inline_ udword GetPosPrimitive() const { return (mPosData>>1); } \ + inline_ udword GetNegPrimitive() const { return (mNegData>>1); } \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + \ + volume mAABB; \ + udword mPosData; \ + udword mNegData; + + class OPCODE_API AABBCollisionNode + { + IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB) + + inline_ float GetVolume() const { return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z; } + inline_ float GetSize() const { return mAABB.mExtents.SquareMagnitude(); } + inline_ udword GetRadius() const + { + udword* Bits = (udword*)&mAABB.mExtents.x; + udword Max = Bits[0]; + if(Bits[1]>Max) Max = Bits[1]; + if(Bits[2]>Max) Max = Bits[2]; + return Max; + } + + // NB: using the square-magnitude or the true volume of the box, seems to yield better results + // (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size" + // otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's + // needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is + // always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices + // whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very + // good strategy. + }; + + class OPCODE_API AABBQuantizedNode + { + IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB) + + inline_ uword GetSize() const + { + const uword* Bits = mAABB.mExtents; + uword Max = Bits[0]; + if(Bits[1]>Max) Max = Bits[1]; + if(Bits[2]>Max) Max = Bits[2]; + return Max; + } + // NB: for quantized nodes I don't feel like computing a square-magnitude with integers all + // over the place.......! + }; + + class OPCODE_API AABBNoLeafNode + { + IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB) + }; + + class OPCODE_API AABBQuantizedNoLeafNode + { + IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB) + }; + + //! Common interface for a collision tree + #define IMPLEMENT_COLLISION_TREE(base_class, node) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + virtual ~base_class(); \ + /* Builds from a standard tree */ \ + override(AABBOptimizedTree) bool Build(AABBTree* tree); \ + /* Refits the tree */ \ + override(AABBOptimizedTree) bool Refit(const MeshInterface* mesh_interface); \ + /* Walks the tree */ \ + override(AABBOptimizedTree) bool Walk(GenericWalkingCallback callback, void* user_data) const; \ + /* Data access */ \ + inline_ const node* GetNodes() const { return mNodes; } \ + /* Stats */ \ + override(AABBOptimizedTree) udword GetUsedBytes() const { return mNbNodes*sizeof(node); } \ + private: \ + node* mNodes; + + typedef bool (*GenericWalkingCallback) (const void* current, void* user_data); + + class OPCODE_API AABBOptimizedTree + { + public: + // Constructor / Destructor + AABBOptimizedTree() : + mNbNodes (0) + {} + virtual ~AABBOptimizedTree() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Build(AABBTree* tree) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Refit(const MeshInterface* mesh_interface) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Walk(GenericWalkingCallback callback, void* user_data) const = 0; + + // Data access + virtual udword GetUsedBytes() const = 0; + inline_ udword GetNbNodes() const { return mNbNodes; } + + protected: + udword mNbNodes; + }; + + class OPCODE_API AABBCollisionTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode) + }; + + class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode) + }; + + class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode) + + public: + IcePoint mCenterCoeff; + IcePoint mExtentsCoeff; + }; + + class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode) + + public: + IcePoint mCenterCoeff; + IcePoint mExtentsCoeff; + }; + +#endif // __OPC_OPTIMIZEDTREE_H__ diff --git a/third-party/Opcode/OPC_Picking.cpp b/third-party/Opcode/OPC_Picking.cpp new file mode 100644 index 0000000..5a48403 --- /dev/null +++ b/third-party/Opcode/OPC_Picking.cpp @@ -0,0 +1,182 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to perform "picking". + * \file OPC_Picking.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#ifdef OPC_RAYHIT_CALLBACK + +/* + Possible RayCollider usages: + - boolean query (shadow feeler) + - closest hit + - all hits + - number of intersection (boolean) + +*/ + +bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts) +{ + struct Local + { + static void AllContacts(const CollisionFace& hit, void* user_data) + { + CollisionFaces* CF = (CollisionFaces*)user_data; + CF->AddFace(hit); + } + }; + + collider.SetFirstContact(false); + collider.SetHitCallback(Local::AllContacts); + collider.SetUserData(&contacts); + return true; +} + +bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact) +{ + struct Local + { + static void ClosestContact(const CollisionFace& hit, void* user_data) + { + CollisionFace* CF = (CollisionFace*)user_data; + if(hit.mDistancemDistance) *CF = hit; + } + }; + + collider.SetFirstContact(false); + collider.SetHitCallback(Local::ClosestContact); + collider.SetUserData(&closest_contact); + closest_contact.mDistance = MAX_FLOAT; + return true; +} + +bool Opcode::SetupShadowFeeler(RayCollider& collider) +{ + collider.SetFirstContact(true); + collider.SetHitCallback(null); + return true; +} + +bool Opcode::SetupInOutTest(RayCollider& collider) +{ + collider.SetFirstContact(false); + collider.SetHitCallback(null); + // Results with collider.GetNbIntersections() + return true; +} + +bool Opcode::Picking( +CollisionFace& picked_face, +const Ray& world_ray, const Model& model, const Matrix4x4* world, +float min_dist, float max_dist, const IcePoint& view_point, CullModeCallback callback, void* user_data) +{ + struct Local + { + struct CullData + { + CollisionFace* Closest; + float MinLimit; + CullModeCallback Callback; + void* UserData; + IcePoint ViewPoint; + const MeshInterface* IMesh; + }; + + // Called for each stabbed face + static void RenderCullingCallback(const CollisionFace& hit, void* user_data) + { + CullData* Data = (CullData*)user_data; + + // Discard face if we already have a closer hit + if(hit.mDistance>=Data->Closest->mDistance) return; + + // Discard face if hit IcePoint is smaller than min limit. This mainly happens when the face is in front + // of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an + // object that he may not even be able to see, which is very annoying. + if(hit.mDistance<=Data->MinLimit) return; + + // This is the index of currently stabbed triangle. + udword StabbedFaceIndex = hit.mFaceID; + + // We may keep it or not, depending on backface culling + bool KeepIt = true; + + // Catch *render* cull mode for this face + CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData); + + if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles + { + // Compute backface culling for current face + + VertexPointers VP; + Data->IMesh->GetTriangle(VP, StabbedFaceIndex); + if(VP.BackfaceCulling(Data->ViewPoint)) + { + if(CM==CULLMODE_CW) KeepIt = false; + } + else + { + if(CM==CULLMODE_CCW) KeepIt = false; + } + } + + if(KeepIt) *Data->Closest = hit; + } + }; + + RayCollider RC; + RC.SetMaxDist(max_dist); + RC.SetTemporalCoherence(false); + RC.SetCulling(false); // We need all faces since some of them can be double-sided + RC.SetFirstContact(false); + RC.SetHitCallback(Local::RenderCullingCallback); + + picked_face.mFaceID = INVALID_ID; + picked_face.mDistance = MAX_FLOAT; + picked_face.mU = 0.0f; + picked_face.mV = 0.0f; + + Local::CullData Data; + Data.Closest = &picked_face; + Data.MinLimit = min_dist; + Data.Callback = callback; + Data.UserData = user_data; + Data.ViewPoint = view_point; + Data.IMesh = model.GetMeshInterface(); + + if(world) + { + // Get matrices + Matrix4x4 InvWorld; + InvertPRMatrix(InvWorld, *world); + + // Compute camera position in mesh space + Data.ViewPoint *= InvWorld; + } + + RC.SetUserData(&Data); + if(RC.Collide(world_ray, model, world)) + { + return picked_face.mFaceID!=INVALID_ID; + } + return false; +} + +#endif diff --git a/third-party/Opcode/OPC_Picking.h b/third-party/Opcode/OPC_Picking.h new file mode 100644 index 0000000..cae5402 --- /dev/null +++ b/third-party/Opcode/OPC_Picking.h @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to perform "picking". + * \file OPC_Picking.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_PICKING_H__ +#define __OPC_PICKING_H__ + +#ifdef OPC_RAYHIT_CALLBACK + + enum CullMode + { + CULLMODE_NONE = 0, + CULLMODE_CW = 1, + CULLMODE_CCW = 2 + }; + + typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data); + + OPCODE_API bool SetupAllHits (RayCollider& collider, CollisionFaces& contacts); + OPCODE_API bool SetupClosestHit (RayCollider& collider, CollisionFace& closest_contact); + OPCODE_API bool SetupShadowFeeler (RayCollider& collider); + OPCODE_API bool SetupInOutTest (RayCollider& collider); + + OPCODE_API bool Picking( + CollisionFace& picked_face, + const Ray& world_ray, const Model& model, const Matrix4x4* world, + float min_dist, float max_dist, const IcePoint& view_point, CullModeCallback callback, void* user_data); +#endif + +#endif //__OPC_PICKING_H__ \ No newline at end of file diff --git a/third-party/Opcode/OPC_PlanesAABBOverlap.h b/third-party/Opcode/OPC_PlanesAABBOverlap.h new file mode 100644 index 0000000..2bc70d7 --- /dev/null +++ b/third-party/Opcode/OPC_PlanesAABBOverlap.h @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Planes-AABB overlap test. + * - original code by Ville Miettinen, from Umbra/dPVS (released on the GD-Algorithms mailing list) + * - almost used "as-is", I even left the comments (hence the frustum-related notes) + * + * \param center [in] box center + * \param extents [in] box extents + * \param out_clip_mask [out] bitmask for active planes + * \param in_clip_mask [in] bitmask for active planes + * \return TRUE if boxes overlap planes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL PlanesCollider::PlanesAABBOverlap(const IcePoint& center, const IcePoint& extents, udword& out_clip_mask, udword in_clip_mask) +{ + // Stats + mNbVolumeBVTests++; + + const IcePlane* p = mPlanes; + + // Evaluate through all active frustum planes. We determine the relation + // between the AABB and a plane by using the concept of "near" and "far" + // vertices originally described by Zhang (and later by Möller). Our + // variant here uses 3 fabs ops, 6 muls, 7 adds and two floating IcePoint + // comparisons per plane. The routine early-exits if the AABB is found + // to be outside any of the planes. The loop also constructs a new output + // clip mask. Most FPUs have a native single-cycle fabsf() operation. + + udword Mask = 1; // current mask index (1,2,4,8,..) + udword TmpOutClipMask = 0; // initialize output clip mask into empty. + + while(Mask<=in_clip_mask) // keep looping while we have active planes left... + { + if(in_clip_mask & Mask) // if clip plane is active, process it.. + { + float NP = extents.x*fabsf(p->n.x) + extents.y*fabsf(p->n.y) + extents.z*fabsf(p->n.z); // ### fabsf could be precomputed + float MP = center.x*p->n.x + center.y*p->n.y + center.z*p->n.z + p->d; + + if(NP < MP) // near vertex behind the clip plane... + return FALSE; // .. so there is no intersection.. + if((-NP) < MP) // near and far vertices on different sides of plane.. + TmpOutClipMask |= Mask; // .. so update the clip mask... + } + Mask+=Mask; // mk = (1<Add(prim_index); + +//! Planes-triangle test +#define PLANES_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + mIMesh->GetTriangle(mVP, prim_index); \ + /* Perform triangle-box overlap test */ \ + if(PlanesTriOverlap(clip_mask)) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +PlanesCollider::PlanesCollider() : + mPlanes (null), + mNbPlanes (0) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +PlanesCollider::~PlanesCollider() +{ + DELETEARRAY(mPlanes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* PlanesCollider::ValidateSettings() +{ + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; + + return VolumeCollider::ValidateSettings(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a planes cache + * \param planes [in] list of planes in world space + * \param nb_planes [in] number of planes + * \param model [in] Opcode model to collide with + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool PlanesCollider::Collide(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, planes, nb_planes, worldm)) return true; + + udword PlaneMask = (1<mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - compute planes in model space + * - check temporal coherence + * + * \param cache [in/out] a planes cache + * \param planes [in] list of planes + * \param nb_planes [in] number of planes + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL PlanesCollider::InitQuery(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute planes in model space + if(nb_planes>mNbPlanes) + { + DELETEARRAY(mPlanes); + mPlanes = new IcePlane[nb_planes]; + } + mNbPlanes = nb_planes; + + if(worldm) + { + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + +// for(udword i=0;iHasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the planes (and set contact status if needed) + udword clip_mask = (1< check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the planes (and set contact status if needed) + udword clip_mask = (1< we'll have to perform a normal query + } + else mTouchedPrimitives->Reset(); + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +#define TEST_CLIP_MASK \ + /* If the box is completely included, so are its children. We don't need to do extra tests, we */ \ + /* can immediately output a list of visible children. Those ones won't need to be clipped. */ \ + if(!OutClipMask) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBCollisionNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _Collide(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBQuantizedNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _Collide(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBNoLeafNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); +} + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridPlanesCollider::HybridPlanesCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridPlanesCollider::~HybridPlanesCollider() +{ +} + +bool HybridPlanesCollider::Collide(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, planes, nb_planes, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + udword clip_mask = (1<mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + udword clip_mask = (1<Distance(*mVP.Vertex[0]); + float d1 = p->Distance(*mVP.Vertex[1]); + float d2 = p->Distance(*mVP.Vertex[2]); + if(d0>0.0f && d1>0.0f && d2>0.0f) return FALSE; +// if(!(IR(d0)&SIGN_BITMASK) && !(IR(d1)&SIGN_BITMASK) && !(IR(d2)&SIGN_BITMASK)) return FALSE; + } + Mask+=Mask; + p++; + } +/* + for(udword i=0;i<6;i++) + { + float d0 = p[i].Distance(mLeafVerts[0]); + float d1 = p[i].Distance(mLeafVerts[1]); + float d2 = p[i].Distance(mLeafVerts[2]); + if(d0>0.0f && d1>0.0f && d2>0.0f) return false; + } +*/ + return TRUE; +} diff --git a/third-party/Opcode/OPC_RayAABBOverlap.h b/third-party/Opcode/OPC_RayAABBOverlap.h new file mode 100644 index 0000000..cd2bdfb --- /dev/null +++ b/third-party/Opcode/OPC_RayAABBOverlap.h @@ -0,0 +1,63 @@ +// Opcode 1.1: ray-AABB overlap tests based on Woo's code +// Opcode 1.2: ray-AABB overlap tests based on the separating axis theorem +// +// The IcePoint of intersection is not computed anymore. The distance to impact is not needed anymore +// since we now have two different queries for segments or rays. + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a segment-AABB overlap test using the separating axis theorem. IceSegment is cached within the class. + * \param center [in] AABB center + * \param extents [in] AABB extents + * \return true on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::SegmentAABBOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbRayBVTests++; + + float Dx = mData2.x - center.x; if(fabsf(Dx) > extents.x + mFDir.x) return FALSE; + float Dy = mData2.y - center.y; if(fabsf(Dy) > extents.y + mFDir.y) return FALSE; + float Dz = mData2.z - center.z; if(fabsf(Dz) > extents.z + mFDir.z) return FALSE; + + float f; + f = mData.y * Dz - mData.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; + f = mData.z * Dx - mData.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; + f = mData.x * Dy - mData.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; + + return TRUE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a ray-AABB overlap test using the separating axis theorem. Ray is cached within the class. + * \param center [in] AABB center + * \param extents [in] AABB extents + * \return true on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::RayAABBOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbRayBVTests++; + +// float Dx = mOrigin.x - center.x; if(fabsf(Dx) > extents.x && Dx*mDir.x>=0.0f) return FALSE; +// float Dy = mOrigin.y - center.y; if(fabsf(Dy) > extents.y && Dy*mDir.y>=0.0f) return FALSE; +// float Dz = mOrigin.z - center.z; if(fabsf(Dz) > extents.z && Dz*mDir.z>=0.0f) return FALSE; + + float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && Dx*mDir.x>=0.0f) return FALSE; + float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && Dy*mDir.y>=0.0f) return FALSE; + float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && Dz*mDir.z>=0.0f) return FALSE; + +// float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && ((SIR(Dx)-1)^SIR(mDir.x))>=0.0f) return FALSE; +// float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && ((SIR(Dy)-1)^SIR(mDir.y))>=0.0f) return FALSE; +// float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && ((SIR(Dz)-1)^SIR(mDir.z))>=0.0f) return FALSE; + + float f; + f = mDir.y * Dz - mDir.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; + f = mDir.z * Dx - mDir.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; + f = mDir.x * Dy - mDir.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; + + return TRUE; +} diff --git a/third-party/Opcode/OPC_RayCollider.cpp b/third-party/Opcode/OPC_RayCollider.cpp new file mode 100644 index 0000000..d1c90a5 --- /dev/null +++ b/third-party/Opcode/OPC_RayCollider.cpp @@ -0,0 +1,762 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a ray collider. + * \file OPC_RayCollider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a ray-vs-tree collider. + * This class performs a stabbing query on an AABB tree, i.e. does a ray-mesh collision. + * + * HIGHER DISTANCE BOUND: + * + * If P0 and P1 are two 3D points, let's define: + * - d = distance between P0 and P1 + * - Origin = P0 + * - Direction = (P1 - P0) / d = normalized direction vector + * - A parameter t such as a IcePoint P on the line (P0,P1) is P = Origin + t * Direction + * - t = 0 --> P = P0 + * - t = d --> P = P1 + * + * Then we can define a general "ray" as: + * + * struct Ray + * { + * IcePoint Origin; + * IcePoint Direction; + * }; + * + * But it actually maps three different things: + * - a segment, when 0 <= t <= d + * - a half-line, when 0 <= t < +infinity, or -infinity < t <= d + * - a line, when -infinity < t < +infinity + * + * In Opcode, we support segment queries, which yield half-line queries by setting d = +infinity. + * We don't support line-queries. If you need them, shift the origin along the ray by an appropriate margin. + * + * In short, the lower bound is always 0, and you can setup the higher bound "d" with RayCollider::SetMaxDist(). + * + * Query |segment |half-line |line + * --------|-------------------|---------------|---------------- + * Usages |-shadow feelers |-raytracing |- + * |-sweep tests |-in/out tests | + * + * FIRST CONTACT: + * + * - You can setup "first contact" mode or "all contacts" mode with RayCollider::SetFirstContact(). + * - In "first contact" mode we return as soon as the ray hits one face. If can be useful e.g. for shadow feelers, where + * you want to know whether the path to the light is free or not (a boolean answer is enough). + * - In "all contacts" mode we return all faces hit by the ray. + * + * TEMPORAL COHERENCE: + * + * - You can enable or disable temporal coherence with RayCollider::SetTemporalCoherence(). + * - It currently only works in "first contact" mode. + * - If temporal coherence is enabled, the previously hit triangle is cached during the first query. Then, next queries + * start by colliding the ray against the cached triangle. If they still collide, we return immediately. + * + * CLOSEST HIT: + * + * - You can enable or disable "closest hit" with RayCollider::SetClosestHit(). + * - It currently only works in "all contacts" mode. + * - If closest hit is enabled, faces are sorted by distance on-the-fly and the closest one only is reported. + * + * BACKFACE CULLING: + * + * - You can enable or disable backface culling with RayCollider::SetCulling(). + * - If culling is enabled, ray will not hit back faces (only front faces). + * + * + * + * \class RayCollider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * This class describes a face hit by a ray or segment. + * This is a particular class dedicated to stabbing queries. + * + * \class CollisionFace + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * This class is a dedicated collection of CollisionFace. + * + * \class CollisionFaces + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#include "OPC_RayAABBOverlap.h" +#include "OPC_RayTriOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + mNbIntersections++; \ + /* Set contact status */ \ + mFlags |= flag; \ + /* In any case the contact has been found and recorded in mStabbedFace */ \ + mStabbedFace.mFaceID = prim_index; + +#ifdef OPC_RAYHIT_CALLBACK + + #define HANDLE_CONTACT(prim_index, flag) \ + SET_CONTACT(prim_index, flag) \ + \ + if(mHitCallback) (mHitCallback)(mStabbedFace, mUserData); + + #define UPDATE_CACHE \ + if(cache && GetContactStatus()) \ + { \ + *cache = mStabbedFace.mFaceID; \ + } +#else + + #define HANDLE_CONTACT(prim_index, flag) \ + SET_CONTACT(prim_index, flag) \ + \ + /* Now we can also record it in mStabbedFaces if available */ \ + if(mStabbedFaces) \ + { \ + /* If we want all faces or if that's the first one we hit */ \ + if(!mClosestHit || !mStabbedFaces->GetNbFaces()) \ + { \ + mStabbedFaces->AddFace(mStabbedFace); \ + } \ + else \ + { \ + /* We only keep closest hit */ \ + CollisionFace* Current = const_cast(mStabbedFaces->GetFaces()); \ + if(Current && mStabbedFace.mDistancemDistance) \ + { \ + *Current = mStabbedFace; \ + } \ + } \ + } + + #define UPDATE_CACHE \ + if(cache && GetContactStatus() && mStabbedFaces) \ + { \ + const CollisionFace* Current = mStabbedFaces->GetFaces(); \ + if(Current) *cache = Current->mFaceID; \ + else *cache = INVALID_ID; \ + } +#endif + +#define SEGMENT_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform ray-tri overlap test and return */ \ + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + /* Intersection IcePoint is valid if dist < segment's length */ \ + /* We know dist>0 so we can use integers */ \ + if(IR(mStabbedFace.mDistance)GetTriangle(VP, prim_index); \ + \ + /* Perform ray-tri overlap test and return */ \ + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + HANDLE_CONTACT(prim_index, flag) \ + } + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RayCollider::RayCollider() : + mNbRayBVTests (0), + mNbRayPrimTests (0), + mNbIntersections (0), + mCulling (true), +#ifdef OPC_RAYHIT_CALLBACK + mHitCallback (null), + mUserData (0), +#else + mClosestHit (false), + mStabbedFaces (null), +#endif + mMaxDist (MAX_FLOAT) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RayCollider::~RayCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* RayCollider::ValidateSettings() +{ + if(mMaxDist<0.0f) return "Higher distance bound must be positive!"; + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; +#ifndef OPC_RAYHIT_CALLBACK + if(mClosestHit && FirstContactEnabled()) return "Closest hit doesn't work with ""First contact"" mode!"; + if(TemporalCoherenceEnabled() && mClosestHit) return "Temporal coherence can't guarantee to report closest hit!"; +#endif + if(SkipPrimitiveTests()) return "SkipPrimitiveTests not possible for RayCollider ! (not implemented)"; + return null; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic stabbing query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - in the user-provided destination array + * + * \param world_ray [in] stabbing ray in world space + * \param model [in] Opcode model to collide with + * \param world [in] model's world matrix, or null + * \param cache [in] a possibly cached face index, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool RayCollider::Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world, udword* cache) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(world_ray, world, cache)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + } + + // Update cache if needed + UPDATE_CACHE + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a stabbing query : + * - reset stats & contact status + * - compute ray in local space + * - check temporal coherence + * + * \param world_ray [in] stabbing ray in world space + * \param world [in] object's world matrix, or null + * \param face_id [in] index of previously stabbed triangle + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword* face_id) +{ + // Reset stats & contact status + Collider::InitQuery(); + mNbRayBVTests = 0; + mNbRayPrimTests = 0; + mNbIntersections = 0; +#ifndef OPC_RAYHIT_CALLBACK + if(mStabbedFaces) mStabbedFaces->Reset(); +#endif + + // Compute ray in local space + // The (Origin/Dir) form is needed for the ray-triangle test anyway (even for segment tests) + if(world) + { + Matrix3x3 InvWorld = *world; + mDir = InvWorld * world_ray.mDir; + + Matrix4x4 World; + InvertPRMatrix(World, *world); + mOrigin = world_ray.mOrig * World; + } + else + { + mDir = world_ray.mDir; + mOrigin = world_ray.mOrig; + } + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + if(!SkipPrimitiveTests()) + { + // Perform overlap test between the unique triangle and the ray (and set contact status if needed) + SEGMENT_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // Check temporal coherence : + + // Test previously colliding primitives first + if(TemporalCoherenceEnabled() && FirstContactEnabled() && face_id && *face_id!=INVALID_ID) + { +#ifdef OLD_CODE +#ifndef OPC_RAYHIT_CALLBACK + if(!mClosestHit) +#endif + { + // Request vertices from the app + VertexPointers VP; + mIMesh->GetTriangle(VP, *face_id); + // Perform ray-cached tri overlap test + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Intersection IcePoint is valid if: + // - distance is positive (else it can just be a face behind the orig IcePoint) + // - distance is smaller than a given max distance (useful for shadow feelers) +// if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistanceAddFace(mStabbedFace); +#endif + return TRUE; + } + } + } +#else + // New code + // We handle both IceSegment/ray queries with the same segment code, and a possible infinite limit + SEGMENT_PRIM(*face_id, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; +#endif + } + + // Precompute data (moved after temporal coherence since only needed for ray-AABB) + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) + { + // For IceSegment-AABB overlap + mData = 0.5f * mDir * mMaxDist; + mData2 = mOrigin + mData; + + // Precompute mFDir; + mFDir.x = fabsf(mData.x); + mFDir.y = fabsf(mData.y); + mFDir.z = fabsf(mData.z); + } + else + { + // For Ray-AABB overlap +// udword x = SIR(mDir.x)-1; +// udword y = SIR(mDir.y)-1; +// udword z = SIR(mDir.z)-1; +// mData.x = FR(x); +// mData.y = FR(y); +// mData.z = FR(z); + + // Precompute mFDir; + mFDir.x = fabsf(mDir.x); + mFDir.y = fabsf(mDir.y); + mFDir.z = fabsf(mDir.z); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Stabbing query for vanilla AABB trees. + * \param world_ray [in] stabbing ray in world space + * \param tree [in] AABB tree + * \param box_indices [out] indices of stabbed boxes + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool RayCollider::Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices) +{ + // ### bad design here + + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + // Basically this is only called to initialize precomputed data + if(InitQuery(world_ray)) return true; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(tree, box_indices); + else _RayStab(tree, box_indices); + + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBCollisionNode* node) +{ + // Perform IceSegment-AABB overlap test + if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->IsLeaf()) + { + SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + _SegmentStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform IceSegment-AABB overlap test + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + _SegmentStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBNoLeafNode* node) +{ + // Perform IceSegment-AABB overlap test + if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->HasPosLeaf()) + { + SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform IceSegment-AABB overlap test + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->HasPosLeaf()) + { + SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for vanilla AABB trees. + * \param node [in] current collision node + * \param box_indices [out] indices of stabbed boxes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBTreeNode* node, Container& box_indices) +{ + // Test the box against the segment + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _SegmentStab(node->GetPos(), box_indices); + _SegmentStab(node->GetNeg(), box_indices); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBCollisionNode* node) +{ + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->IsLeaf()) + { + RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _RayStab(node->GetPos()); + + if(ContactFound()) return; + + _RayStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _RayStab(node->GetPos()); + + if(ContactFound()) return; + + _RayStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBNoLeafNode* node) +{ + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->HasPosLeaf()) + { + RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->HasPosLeaf()) + { + RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for vanilla AABB trees. + * \param node [in] current collision node + * \param box_indices [out] indices of stabbed boxes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBTreeNode* node, Container& box_indices) +{ + // Test the box against the ray + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + mFlags |= OPC_CONTACT; + box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _RayStab(node->GetPos(), box_indices); + _RayStab(node->GetNeg(), box_indices); + } +} diff --git a/third-party/Opcode/OPC_RayCollider.h b/third-party/Opcode/OPC_RayCollider.h new file mode 100644 index 0000000..393bc5f --- /dev/null +++ b/third-party/Opcode/OPC_RayCollider.h @@ -0,0 +1,225 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a ray collider. + * \file OPC_RayCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_RAYCOLLIDER_H__ +#define __OPC_RAYCOLLIDER_H__ + + class OPCODE_API CollisionFace + { + public: + //! Constructor + inline_ CollisionFace() {} + //! Destructor + inline_ ~CollisionFace() {} + + udword mFaceID; //!< Index of touched face + float mDistance; //!< Distance from collider to hitpoint + float mU, mV; //!< Impact barycentric coordinates + }; + + class OPCODE_API CollisionFaces : private Container + { + public: + //! Constructor + CollisionFaces() {} + //! Destructor + ~CollisionFaces() {} + + inline_ udword GetNbFaces() const { return GetNbEntries()>>2; } + inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); } + + inline_ void Reset() { Container::Reset(); } + + inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); } + }; + +#ifdef OPC_RAYHIT_CALLBACK + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE to record a hit. + * \param hit [in] current hit + * \param user_data [in] user-defined data from SetCallback() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef void (*HitCallback) (const CollisionFace& hit, void* user_data); +#endif + + class OPCODE_API RayCollider : public Collider + { + public: + // Constructor / Destructor + RayCollider(); + virtual ~RayCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic stabbing query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - in the user-provided destination array + * + * \param world_ray [in] stabbing ray in world space + * \param model [in] Opcode model to collide with + * \param world [in] model's world matrix, or null + * \param cache [in] a possibly cached face index, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null); + // + bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices); + // Settings + +#ifndef OPC_RAYHIT_CALLBACK + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: enable or disable "closest hit" mode. + * \param flag [in] true to report closest hit only + * \see SetCulling(bool flag) + * \see SetMaxDist(float max_dist) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetClosestHit(bool flag) { mClosestHit = flag; } +#endif + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: enable or disable backface culling. + * \param flag [in] true to enable backface culling + * \see SetClosestHit(bool flag) + * \see SetMaxDist(float max_dist) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetCulling(bool flag) { mCulling = flag; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: sets the higher distance bound. + * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment) + * \see SetClosestHit(bool flag) + * \see SetCulling(bool flag) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; } + +#ifdef OPC_RAYHIT_CALLBACK + inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; } + inline_ void SetUserData(void* user_data) { mUserData = user_data; } +#else + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: sets the destination array for stabbed faces. + * \param cf [in] destination array, filled during queries + * \see SetClosestHit(bool flag) + * \see SetCulling(bool flag) + * \see SetMaxDist(float max_dist) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; } +#endif + // Stats + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Ray-BV overlap tests after a collision query. + * \see GetNbRayPrimTests() + * \see GetNbIntersections() + * \return the number of Ray-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Ray-Triangle overlap tests after a collision query. + * \see GetNbRayBVTests() + * \see GetNbIntersections() + * \return the number of Ray-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; } + + // In-out test + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests. + * \see GetNbRayBVTests() + * \see GetNbRayPrimTests() + * \return the number of valid intersections during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbIntersections() const { return mNbIntersections; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Ray in local space + IcePoint mOrigin; //!< Ray origin + IcePoint mDir; //!< Ray direction (normalized) + IcePoint mFDir; //!< fabsf(mDir) + IcePoint mData, mData2; + // Stabbed faces + CollisionFace mStabbedFace; //!< Current stabbed face +#ifdef OPC_RAYHIT_CALLBACK + HitCallback mHitCallback; //!< Callback used to record a hit + void* mUserData; //!< User-defined data +#else + CollisionFaces* mStabbedFaces; //!< List of stabbed faces +#endif + // Stats + udword mNbRayBVTests; //!< Number of Ray-BV tests + udword mNbRayPrimTests; //!< Number of Ray-Primitive tests + // In-out test + udword mNbIntersections; //!< Number of valid intersections + // Dequantization coeffs + IcePoint mCenterCoeff; + IcePoint mExtentsCoeff; + // Settings + float mMaxDist; //!< Valid segment on the ray +#ifndef OPC_RAYHIT_CALLBACK + bool mClosestHit; //!< Report closest hit only +#endif + bool mCulling; //!< Stab culled faces or not + // Internal methods + void _SegmentStab(const AABBCollisionNode* node); + void _SegmentStab(const AABBNoLeafNode* node); + void _SegmentStab(const AABBQuantizedNode* node); + void _SegmentStab(const AABBQuantizedNoLeafNode* node); + void _SegmentStab(const AABBTreeNode* node, Container& box_indices); + void _RayStab(const AABBCollisionNode* node); + void _RayStab(const AABBNoLeafNode* node); + void _RayStab(const AABBQuantizedNode* node); + void _RayStab(const AABBQuantizedNoLeafNode* node); + void _RayStab(const AABBTreeNode* node, Container& box_indices); + // Overlap tests + inline_ BOOL RayAABBOverlap(const IcePoint& center, const IcePoint& extents); + inline_ BOOL SegmentAABBOverlap(const IcePoint& center, const IcePoint& extents); + inline_ BOOL RayTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); + // Init methods + BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null); + }; + +#endif // __OPC_RAYCOLLIDER_H__ diff --git a/third-party/Opcode/OPC_RayTriOverlap.h b/third-party/Opcode/OPC_RayTriOverlap.h new file mode 100644 index 0000000..405c7e1 --- /dev/null +++ b/third-party/Opcode/OPC_RayTriOverlap.h @@ -0,0 +1,89 @@ +#define LOCAL_EPSILON 0.000001f + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a ray-triangle intersection test. + * Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection". + * It's been optimized a bit with integer code, and modified to return a non-intersection if distance from + * ray origin to triangle is negative. + * + * \param vert0 [in] triangle vertex + * \param vert1 [in] triangle vertex + * \param vert2 [in] triangle vertex + * \return true on overlap. mStabbedFace is filled with relevant info. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::RayTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2) +{ + // Stats + mNbRayPrimTests++; + + // Find vectors for two edges sharing vert0 + IcePoint edge1 = vert1 - vert0; + IcePoint edge2 = vert2 - vert0; + + // Begin calculating determinant - also used to calculate U parameter + IcePoint pvec = mDir^edge2; + + // If determinant is near zero, ray lies in plane of triangle + float det = edge1|pvec; + + if(mCulling) + { + if(det 0. So we can use integer cmp. + + // Calculate distance from vert0 to ray origin + IcePoint tvec = mOrigin - vert0; + + // Calculate U parameter and test bounds + mStabbedFace.mU = tvec|pvec; +// if(IR(u)&0x80000000 || u>det) return FALSE; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IR(det)) return FALSE; + + // Prepare to test V parameter + IcePoint qvec = tvec^edge1; + + // Calculate V parameter and test bounds + mStabbedFace.mV = mDir|qvec; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>det) return FALSE; + + // Calculate t, scale parameters, ray intersects triangle + mStabbedFace.mDistance = edge2|qvec; + // Det > 0 so we can early exit here + // Intersection IcePoint is valid if distance is positive (else it can just be a face behind the orig IcePoint) + if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; + // Else go on + float OneOverDet = 1.0f / det; + mStabbedFace.mDistance *= OneOverDet; + mStabbedFace.mU *= OneOverDet; + mStabbedFace.mV *= OneOverDet; + } + else + { + // the non-culling branch + if(det>-LOCAL_EPSILON && det1.0f) return FALSE; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IEEE_1_0) return FALSE; + + // prepare to test V parameter + IcePoint qvec = tvec^edge1; + + // Calculate V parameter and test bounds + mStabbedFace.mV = (mDir|qvec) * OneOverDet; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>1.0f) return FALSE; + + // Calculate t, ray intersects triangle + mStabbedFace.mDistance = (edge2|qvec) * OneOverDet; + // Intersection IcePoint is valid if distance is positive (else it can just be a face behind the orig IcePoint) + if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; + } + return TRUE; +} diff --git a/third-party/Opcode/OPC_Settings.h b/third-party/Opcode/OPC_Settings.h new file mode 100644 index 0000000..88d2ccd --- /dev/null +++ b/third-party/Opcode/OPC_Settings.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains compilation flags. + * \file OPC_Settings.h + * \author Pierre Terdiman + * \date May, 12, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SETTINGS_H__ +#define __OPC_SETTINGS_H__ + + //! Use CPU comparisons (comment that line to use standard FPU compares) + #define OPC_CPU_COMPARE + + //! Use FCOMI / FCMOV on Pentium-Pro based processors (comment that line to use plain C++) + #define OPC_USE_FCOMI + + //! Use epsilon value in tri-tri overlap test + #define OPC_TRITRI_EPSILON_TEST + + //! Use tree-coherence or not [not implemented yet] +// #define OPC_USE_TREE_COHERENCE + + //! Use callbacks or direct pointers. Using callbacks might be a bit slower (but probably not much) +// #define OPC_USE_CALLBACKS + + //! Support triangle and vertex strides or not. Using strides might be a bit slower (but probably not much) +// #define OPC_USE_STRIDE + + //! Discard negative pointer in vanilla trees + #define OPC_NO_NEG_VANILLA_TREE + + //! Use a callback in the ray collider + #define OPC_RAYHIT_CALLBACK + + // NB: no compilation flag to enable/disable stats since they're actually needed in the box/box overlap test + +#endif //__OPC_SETTINGS_H__ \ No newline at end of file diff --git a/third-party/Opcode/OPC_SphereAABBOverlap.h b/third-party/Opcode/OPC_SphereAABBOverlap.h new file mode 100644 index 0000000..b7b4376 --- /dev/null +++ b/third-party/Opcode/OPC_SphereAABBOverlap.h @@ -0,0 +1,128 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Sphere-AABB overlap test, based on Jim Arvo's code. + * \param center [in] box center + * \param extents [in] box extents + * \return TRUE on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL SphereCollider::SphereAABBOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbVolumeBVTests++; + + float d = 0.0f; + + //find the square of the distance + //from the sphere to the box +#ifdef OLDIES + for(udword i=0;i<3;i++) + { + float tmp = mCenter[i] - center[i]; + float s = tmp + extents[i]; + + if(s<0.0f) d += s*s; + else + { + s = tmp - extents[i]; + if(s>0.0f) d += s*s; + } + } +#endif + +//#ifdef NEW_TEST + +// float tmp = mCenter.x - center.x; +// float s = tmp + extents.x; + + float tmp,s; + + tmp = mCenter.x - center.x; + s = tmp + extents.x; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.x; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } + + tmp = mCenter.y - center.y; + s = tmp + extents.y; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.y; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } + + tmp = mCenter.z - center.z; + s = tmp + extents.z; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.z; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } +//#endif + +#ifdef OLDIES +// IcePoint Min = center - extents; +// IcePoint Max = center + extents; + + float d = 0.0f; + + //find the square of the distance + //from the sphere to the box + for(udword i=0;i<3;i++) + { +float Min = center[i] - extents[i]; + +// if(mCenter[i]Max[i]) + if(mCenter[i]>Max) + { + float s = mCenter[i] - Max; + d += s*s; + } + } + } +#endif + return d <= mRadius2; +} diff --git a/third-party/Opcode/OPC_SphereCollider.cpp b/third-party/Opcode/OPC_SphereCollider.cpp new file mode 100644 index 0000000..32af6e6 --- /dev/null +++ b/third-party/Opcode/OPC_SphereCollider.cpp @@ -0,0 +1,726 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a sphere collider. + * \file OPC_SphereCollider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a sphere-vs-tree collider. + * This class performs a collision test between a sphere and an AABB tree. You can use this to do a standard player vs world collision, + * in a Nettle/Telemachos way. It doesn't suffer from all reported bugs in those two classic codes - the "new" one by Paul Nettle is a + * debuggued version I think. Collision response can be driven by reported collision data - it works extremely well for me. In sake of + * efficiency, all meshes (that is, all AABB trees) should of course also be kept in an extra hierarchical structure (octree, whatever). + * + * \class SphereCollider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#include "OPC_SphereAABBOverlap.h" +#include "OPC_SphereTriOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! Sphere-triangle overlap test +#define SPHERE_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform sphere-tri overlap test */ \ + if(SphereTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SphereCollider::SphereCollider() +{ + mCenter.Zero(); + mRadius2 = 0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SphereCollider::~SphereCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in local space + * \param model [in] Opcode model to collide with + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, sphere, worlds, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] a sphere cache + * \param sphere [in] sphere in local space + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL SphereCollider::InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute sphere in model space: + // - Precompute R^2 + mRadius2 = sphere.mRadius * sphere.mRadius; + // - Compute center position + mCenter = sphere.mCenter; + // -> to world space + if(worlds) mCenter *= *worlds; + // -> to model space + if(worldm) + { + // Invert model matrix + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + mCenter *= InvWorldM; + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the sphere (and set contact status if needed) + SPHERE_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the sphere (and set contact status if needed) + SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious): + float r = sqrtf(cache.FatRadius2) - sphere.mRadius; + if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat sphere so that coherence will work for subsequent frames + mRadius2 *= cache.FatCoeff; +// mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff); + + // Update cache with query data (signature for cached faces) + cache.Center = mCenter; + cache.FatRadius2 = mRadius2; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, sphere)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the sphere completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the sphere contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL SphereCollider::SphereContainsBox(const IcePoint& bc, const IcePoint& be) +{ + // I assume if all 8 box vertices are inside the sphere, so does the whole box. + // Sounds ok but maybe there's a better way? + IcePoint p; + p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z+be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z-be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_SPHERE(center, extents) \ + if(SphereContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->IsLeaf()) + { + SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBTreeNode* node) +{ + // Perform Sphere-AABB overlap test + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!SphereAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || SphereContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridSphereCollider::HybridSphereCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridSphereCollider::~HybridSphereCollider() +{ +} + +bool HybridSphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, sphere, worlds, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + SPHERE_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + SPHERE_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/third-party/Opcode/OPC_SphereCollider.h b/third-party/Opcode/OPC_SphereCollider.h new file mode 100644 index 0000000..095824a --- /dev/null +++ b/third-party/Opcode/OPC_SphereCollider.h @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a sphere collider. + * \file OPC_SphereCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SPHERECOLLIDER_H__ +#define __OPC_SPHERECOLLIDER_H__ + + struct OPCODE_API SphereCache : VolumeCache + { + SphereCache() : Center(0.0f,0.0f,0.0f), FatRadius2(0.0f), FatCoeff(1.1f) {} + ~SphereCache() {} + + // Cached faces signature + IcePoint Center; //!< Sphere used when performing the query resulting in cached faces + float FatRadius2; //!< Sphere used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere + }; + + class OPCODE_API SphereCollider : public VolumeCollider + { + public: + // Constructor / Destructor + SphereCollider(); + virtual ~SphereCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in local space + * \param model [in] Opcode model to collide with + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + + // + bool Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree); + protected: + // Sphere in model space + IcePoint mCenter; //!< Sphere center + float mRadius2; //!< Sphere radius squared + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL SphereContainsBox(const IcePoint& bc, const IcePoint& be); + inline_ BOOL SphereAABBOverlap(const IcePoint& center, const IcePoint& extents); + BOOL SphereTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); + // Init methods + BOOL InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridSphereCollider : public SphereCollider + { + public: + // Constructor / Destructor + HybridSphereCollider(); + virtual ~HybridSphereCollider(); + + bool Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_SPHERECOLLIDER_H__ diff --git a/third-party/Opcode/OPC_SphereTriOverlap.h b/third-party/Opcode/OPC_SphereTriOverlap.h new file mode 100644 index 0000000..012d9ea --- /dev/null +++ b/third-party/Opcode/OPC_SphereTriOverlap.h @@ -0,0 +1,187 @@ + +// This is collision detection. If you do another distance test for collision *response*, +// if might be useful to simply *skip* the test below completely, and report a collision. +// - if sphere-triangle overlap, result is ok +// - if they don't, we'll discard them during collision response with a similar test anyway +// Overall this approach should run faster. + +// Original code by David Eberly in Magic. +BOOL SphereCollider::SphereTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2) +{ + // Stats + mNbVolumePrimTests++; + + // Early exit if one of the vertices is inside the sphere + IcePoint kDiff = vert2 - mCenter; + float fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + kDiff = vert1 - mCenter; + fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + kDiff = vert0 - mCenter; + fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + // Else do the full distance test + IcePoint TriEdge0 = vert1 - vert0; + IcePoint TriEdge1 = vert2 - vert0; + +//IcePoint kDiff = vert0 - mCenter; + float fA00 = TriEdge0.SquareMagnitude(); + float fA01 = TriEdge0 | TriEdge1; + float fA11 = TriEdge1.SquareMagnitude(); + float fB0 = kDiff | TriEdge0; + float fB1 = kDiff | TriEdge1; +//float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11 - fA01*fA01); + float u = fA01*fB1-fA11*fB0; + float v = fA01*fB0-fA00*fB1; + float SqrDist; + + if(u + v <= fDet) + { + if(u < 0.0f) + { + if(v < 0.0f) // region 4 + { + if(fB0 < 0.0f) + { +// v = 0.0f; + if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + else + { +// u = 0.0f; + if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else // region 3 + { +// u = 0.0f; + if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else if(v < 0.0f) // region 5 + { +// v = 0.0f; + if(fB0>=0.0f) { /*u = 0.0f;*/ SqrDist = fC; } + else if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + else // region 0 + { + // minimum at interior IcePoint + if(fDet==0.0f) + { +// u = 0.0f; +// v = 0.0f; + SqrDist = MAX_FLOAT; + } + else + { + float fInvDet = 1.0f/fDet; + u *= fInvDet; + v *= fInvDet; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + } + else + { + float fTmp0, fTmp1, fNumer, fDenom; + + if(u < 0.0f) // region 2 + { + fTmp0 = fA01 + fB0; + fTmp1 = fA11 + fB1; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// u = 1.0f; +// v = 0.0f; + SqrDist = fA00+2.0f*fB0+fC; + } + else + { + u = fNumer/fDenom; + v = 1.0f - u; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + else + { +// u = 0.0f; + if(fTmp1 <= 0.0f) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else if(fB1 >= 0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else if(v < 0.0f) // region 6 + { + fTmp0 = fA01 + fB1; + fTmp1 = fA00 + fB0; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// v = 1.0f; +// u = 0.0f; + SqrDist = fA11+2.0f*fB1+fC; + } + else + { + v = fNumer/fDenom; + u = 1.0f - v; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + else + { +// v = 0.0f; + if(fTmp1 <= 0.0f) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else if(fB0 >= 0.0f) { /*u = 0.0f;*/ SqrDist = fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + } + else // region 1 + { + fNumer = fA11 + fB1 - fA01 - fB0; + if(fNumer <= 0.0f) + { +// u = 0.0f; +// v = 1.0f; + SqrDist = fA11+2.0f*fB1+fC; + } + else + { + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// u = 1.0f; +// v = 0.0f; + SqrDist = fA00+2.0f*fB0+fC; + } + else + { + u = fNumer/fDenom; + v = 1.0f - u; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + } + } + + return fabsf(SqrDist) < mRadius2; +} diff --git a/third-party/Opcode/OPC_SweepAndPrune.cpp b/third-party/Opcode/OPC_SweepAndPrune.cpp new file mode 100644 index 0000000..e56e7ab --- /dev/null +++ b/third-party/Opcode/OPC_SweepAndPrune.cpp @@ -0,0 +1,664 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) + * \file OPC_SweepAndPrune.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +inline_ void Sort(udword& id0, udword& id1) +{ + if(id0>id1) Swap(id0, id1); +} + + class Opcode::SAP_Element + { + public: + inline_ SAP_Element() {} + inline_ SAP_Element(udword id, SAP_Element* next) : mID(id), mNext(next) {} + inline_ ~SAP_Element() {} + + udword mID; + SAP_Element* mNext; + }; + + class Opcode::SAP_Box + { + public: + SAP_EndPoint* Min[3]; + SAP_EndPoint* Max[3]; + }; + + class Opcode::SAP_EndPoint + { + public: + float Value; // Min or Max value + SAP_EndPoint* Previous; // Previous EndPoint whose Value is smaller than ours (or null) + SAP_EndPoint* Next; // Next EndPoint whose Value is greater than ours (or null) + udword Data; // Parent box ID *2 | MinMax flag + + inline_ void SetData(udword box_id, BOOL is_max) { Data = (box_id<<1)|is_max; } + inline_ BOOL IsMax() const { return Data & 1; } + inline_ udword GetBoxID() const { return Data>>1; } + + inline_ void InsertAfter(SAP_EndPoint* element) + { + if(this!=element && this!=element->Next) + { + // Remove + if(Previous) Previous->Next = Next; + if(Next) Next->Previous = Previous; + + // Insert + Next = element->Next; + if(Next) Next->Previous = this; + + element->Next = this; + Previous = element; + } + } + + inline_ void InsertBefore(SAP_EndPoint* element) + { + if(this!=element && this!=element->Previous) + { + // Remove + if(Previous) Previous->Next = Next; + if(Next) Next->Previous = Previous; + + // Insert + Previous = element->Previous; + element->Previous = this; + + Next = element; + if(Previous) Previous->Next = this; + } + } + }; + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_PairData::SAP_PairData() : + mNbElements (0), + mNbUsedElements (0), + mElementPool (null), + mFirstFree (null), + mNbObjects (0), + mArray (null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_PairData::~SAP_PairData() +{ + Release(); +} + +void SAP_PairData::Release() +{ + mNbElements = 0; + mNbUsedElements = 0; + mNbObjects = 0; + DELETEARRAY(mElementPool); + DELETEARRAY(mArray); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes. + * \param nb_objects [in] + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SAP_PairData::Init(udword nb_objects) +{ + // Make sure everything has been released + Release(); + if(!nb_objects) return false; + + mArray = new SAP_Element*[nb_objects]; + CHECKALLOC(mArray); + ZeroMemory(mArray, nb_objects*sizeof(SAP_Element*)); + mNbObjects = nb_objects; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Remaps a pointer when pool gets resized. + * \param element [in/out] remapped element + * \param delta [in] offset in bytes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void Remap(SAP_Element*& element, udword delta) +{ + if(element) element = (SAP_Element*)(udword(element) + delta); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets a free element in the pool. + * \param id [in] element id + * \param next [in] next element + * \param remap [out] possible remapping offset + * \return the new element + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_Element* SAP_PairData::GetFreeElem(udword id, SAP_Element* next, udword* remap) +{ + if(remap) *remap = 0; + + SAP_Element* FreeElem; + if(mFirstFree) + { + // Recycle + FreeElem = mFirstFree; + mFirstFree = mFirstFree->mNext; // First free = next free (or null) + } + else + { + if(mNbUsedElements==mNbElements) + { + // Resize + mNbElements = mNbElements ? (mNbElements<<1) : 2; + + SAP_Element* NewElems = new SAP_Element[mNbElements]; + + if(mNbUsedElements) CopyMemory(NewElems, mElementPool, mNbUsedElements*sizeof(SAP_Element)); + + // Remap everything + { + udword Delta = udword(NewElems) - udword(mElementPool); + + for(udword i=0;imID = id; + FreeElem->mNext = next; + + return FreeElem; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Frees an element of the pool. + * \param elem [in] element to free/recycle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void SAP_PairData::FreeElem(SAP_Element* elem) +{ + elem->mNext = mFirstFree; // Next free + mFirstFree = elem; +} + +// Add a pair to the set. +void SAP_PairData::AddPair(udword id1, udword id2) +{ + // Order the ids + Sort(id1, id2); + + ASSERT(id1=mNbObjects) return; + + // Select the right list from "mArray". + SAP_Element* Current = mArray[id1]; + + if(!Current) + { + // Empty slot => create new element + mArray[id1] = GetFreeElem(id2, null); + } + else if(Current->mID>id2) + { + // The list is not empty but all elements are greater than id2 => insert id2 in the front. + mArray[id1] = GetFreeElem(id2, mArray[id1]); + } + else + { + // Else find the correct location in the sorted list (ascending order) and insert id2 there. + while(Current->mNext) + { + if(Current->mNext->mID > id2) break; + + Current = Current->mNext; + } + + if(Current->mID==id2) return; // The pair already exists + +// Current->mNext = GetFreeElem(id2, Current->mNext); + udword Delta; + SAP_Element* E = GetFreeElem(id2, Current->mNext, &Delta); + if(Delta) Remap(Current, Delta); + Current->mNext = E; + } +} + +// Delete a pair from the set. +void SAP_PairData::RemovePair(udword id1, udword id2) +{ + // Order the ids. + Sort(id1, id2); + + // Exit if the pair doesn't exist in the set + if(id1>=mNbObjects) return; + + // Otherwise, select the correct list. + SAP_Element* Current = mArray[id1]; + + // If this list is empty, the pair doesn't exist. + if(!Current) return; + + // Otherwise, if id2 is the first element, delete it. + if(Current->mID==id2) + { + mArray[id1] = Current->mNext; + FreeElem(Current); + } + else + { + // If id2 is not the first element, start traversing the sorted list. + while(Current->mNext) + { + // If we have moved too far away without hitting id2, then the pair doesn't exist + if(Current->mNext->mID > id2) return; + + // Otherwise, delete id2. + if(Current->mNext->mID == id2) + { + SAP_Element* Temp = Current->mNext; + Current->mNext = Temp->mNext; + FreeElem(Temp); + return; + } + Current = Current->mNext; + } + } +} + +void SAP_PairData::DumpPairs(Pairs& pairs) const +{ + // ### Ugly and slow + for(udword i=0;imIDmID); + Current = Current->mNext; + } + } +} + +void SAP_PairData::DumpPairs(PairCallback callback, void* user_data) const +{ + if(!callback) return; + + // ### Ugly and slow + for(udword i=0;imIDmID, user_data)) return; + Current = Current->mNext; + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SweepAndPrune::SweepAndPrune() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SweepAndPrune::~SweepAndPrune() +{ +} + +void SweepAndPrune::GetPairs(Pairs& pairs) const +{ + mPairs.DumpPairs(pairs); +} + +void SweepAndPrune::GetPairs(PairCallback callback, void* user_data) const +{ + mPairs.DumpPairs(callback, user_data); +} + +bool SweepAndPrune::Init(udword nb_objects, const AABB** boxes) +{ + // 1) Create sorted lists + mNbObjects = nb_objects; + + mBoxes = new SAP_Box[nb_objects]; +// for(udword i=0;iGetMin(Axis); + Data[i*2+1] = boxes[i]->GetMax(Axis); + } + RadixSort RS; + const udword* Sorted = RS.Sort(Data, nb_objects*2).GetRanks(); + + SAP_EndPoint* PreviousEndPoint = null; + + for(udword i=0;i>1; + + ASSERT(BoxIndexValue = SortedCoord; +// CurrentEndPoint->IsMax = SortedIndex&1; // ### could be implicit ? +// CurrentEndPoint->ID = BoxIndex; // ### could be implicit ? + CurrentEndPoint->SetData(BoxIndex, SortedIndex&1); // ### could be implicit ? + CurrentEndPoint->Previous = PreviousEndPoint; + CurrentEndPoint->Next = null; + if(PreviousEndPoint) PreviousEndPoint->Next = CurrentEndPoint; + + if(CurrentEndPoint->IsMax()) mBoxes[BoxIndex].Max[Axis] = CurrentEndPoint; + else mBoxes[BoxIndex].Min[Axis] = CurrentEndPoint; + + PreviousEndPoint = CurrentEndPoint; + } + } + + DELETEARRAY(Data); + + CheckListsIntegrity(); + + // 2) Quickly find starting pairs + + mPairs.Init(nb_objects); + + { + Pairs P; + CompleteBoxPruning(nb_objects, boxes, P, Axes(AXES_XZY)); + for(udword i=0;iid0; + udword id1 = PP->id1; + + if(id0!=id1 && boxes[id0]->Intersect(*boxes[id1])) + { + mPairs.AddPair(id0, id1); + } + else ASSERT(0); + } + } + + return true; +} + +bool SweepAndPrune::CheckListsIntegrity() +{ + for(udword Axis=0;Axis<3;Axis++) + { + // Find list head + SAP_EndPoint* Current = mList[Axis]; + while(Current->Previous) Current = Current->Previous; + + udword Nb = 0; + + SAP_EndPoint* Previous = null; + while(Current) + { + Nb++; + + if(Previous) + { + ASSERT(Previous->Value <= Current->Value); + if(Previous->Value > Current->Value) return false; + } + + ASSERT(Current->Previous==Previous); + if(Current->Previous!=Previous) return false; + + Previous = Current; + Current = Current->Next; + } + + ASSERT(Nb==mNbObjects*2); + } + return true; +} + +inline_ BOOL Intersect(const AABB& a, const SAP_Box& b) +{ + if(b.Max[0]->Value < a.GetMin(0) || a.GetMax(0) < b.Min[0]->Value + || b.Max[1]->Value < a.GetMin(1) || a.GetMax(1) < b.Min[1]->Value + || b.Max[2]->Value < a.GetMin(2) || a.GetMax(2) < b.Min[2]->Value) return FALSE; + + return TRUE; +} + + + +bool SweepAndPrune::UpdateObject(udword i, const AABB& box) +{ + for(udword Axis=0;Axis<3;Axis++) + { +// udword Base = (udword)&mList[Axis][0]; + + // Update min + { + SAP_EndPoint* const CurrentMin = mBoxes[i].Min[Axis]; + ASSERT(!CurrentMin->IsMax()); + + const float Limit = box.GetMin(Axis); + if(Limit == CurrentMin->Value) + { + } + else if(Limit < CurrentMin->Value) + { + CurrentMin->Value = Limit; + + // Min is moving left: + SAP_EndPoint* NewPos = CurrentMin; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Previous) && tmp->Value > Limit) + { + NewPos = tmp; + + if(NewPos->IsMax()) + { + // Our min passed a max => start overlap + //udword SortedIndex = (udword(CurrentMin) - Base)/sizeof(NS_EndPoint); + const udword id0 = CurrentMin->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1); + } + } + + CurrentMin->InsertBefore(NewPos); + } + else// if(Limit > CurrentMin->Value) + { + CurrentMin->Value = Limit; + + // Min is moving right: + SAP_EndPoint* NewPos = CurrentMin; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Next) && tmp->Value < Limit) + { + NewPos = tmp; + + if(NewPos->IsMax()) + { + // Our min passed a max => stop overlap + const udword id0 = CurrentMin->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1) mPairs.RemovePair(id0, id1); + } + } + + CurrentMin->InsertAfter(NewPos); + } + } + + // Update max + { + SAP_EndPoint* const CurrentMax = mBoxes[i].Max[Axis]; + ASSERT(CurrentMax->IsMax()); + + const float Limit = box.GetMax(Axis); + if(Limit == CurrentMax->Value) + { + } + else if(Limit > CurrentMax->Value) + { + CurrentMax->Value = Limit; + + // Max is moving right: + SAP_EndPoint* NewPos = CurrentMax; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Next) && tmp->Value < Limit) + { + NewPos = tmp; + + if(!NewPos->IsMax()) + { + // Our max passed a min => start overlap + const udword id0 = CurrentMax->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1); + } + } + + CurrentMax->InsertAfter(NewPos); + } + else// if(Limit < CurrentMax->Value) + { + CurrentMax->Value = Limit; + + // Max is moving left: + SAP_EndPoint* NewPos = CurrentMax; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Previous) && tmp->Value > Limit) + { + NewPos = tmp; + + if(!NewPos->IsMax()) + { + // Our max passed a min => stop overlap + const udword id0 = CurrentMax->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1) mPairs.RemovePair(id0, id1); + } + } + + CurrentMax->InsertBefore(NewPos); + } + } + } + + return true; +} diff --git a/third-party/Opcode/OPC_SweepAndPrune.h b/third-party/Opcode/OPC_SweepAndPrune.h new file mode 100644 index 0000000..cbb87ac --- /dev/null +++ b/third-party/Opcode/OPC_SweepAndPrune.h @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) + * \file OPC_SweepAndPrune.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SWEEPANDPRUNE_H__ +#define __OPC_SWEEPANDPRUNE_H__ + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE for each colliding pairs. + * \param id0 [in] id of colliding object + * \param id1 [in] id of colliding object + * \param user_data [in] user-defined data + * \return TRUE to continue enumeration + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef BOOL (*PairCallback) (udword id0, udword id1, void* user_data); + + class SAP_Element; + class SAP_EndPoint; + class SAP_Box; + + class OPCODE_API SAP_PairData + { + public: + SAP_PairData(); + ~SAP_PairData(); + + bool Init(udword nb_objects); + + void AddPair(udword id1, udword id2); + void RemovePair(udword id1, udword id2); + + void DumpPairs(Pairs& pairs) const; + void DumpPairs(PairCallback callback, void* user_data) const; + private: + udword mNbElements; //!< Total number of elements in the pool + udword mNbUsedElements; //!< Number of used elements + SAP_Element* mElementPool; //!< Array of mNbElements elements + SAP_Element* mFirstFree; //!< First free element in the pool + + udword mNbObjects; //!< Max number of objects we can handle + SAP_Element** mArray; //!< Pointers to pool + // Internal methods + SAP_Element* GetFreeElem(udword id, SAP_Element* next, udword* remap=null); + inline_ void FreeElem(SAP_Element* elem); + void Release(); + }; + + class OPCODE_API SweepAndPrune + { + public: + SweepAndPrune(); + ~SweepAndPrune(); + + bool Init(udword nb_objects, const AABB** boxes); + bool UpdateObject(udword i, const AABB& box); + + void GetPairs(Pairs& pairs) const; + void GetPairs(PairCallback callback, void* user_data) const; + private: + SAP_PairData mPairs; + + udword mNbObjects; + SAP_Box* mBoxes; + SAP_EndPoint* mList[3]; + // Internal methods + bool CheckListsIntegrity(); + }; + +#endif //__OPC_SWEEPANDPRUNE_H__ \ No newline at end of file diff --git a/third-party/Opcode/OPC_TreeBuilders.cpp b/third-party/Opcode/OPC_TreeBuilders.cpp new file mode 100644 index 0000000..89dd93b --- /dev/null +++ b/third-party/Opcode/OPC_TreeBuilders.cpp @@ -0,0 +1,255 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for tree builders. + * \file OPC_TreeBuilders.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of vertices. + * + * \class AABBTreeOfVerticesBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of AABBs. + * + * \class AABBTreeOfAABBsBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of triangles. + * + * \class AABBTreeOfTrianglesBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the AABB of a set of primitives. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [out] global AABB enclosing the set of input primitives + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeOfAABBsBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const +{ + // Checkings + if(!primitives || !nb_prims) return false; + + // Initialize global box + global_box = mAABBArray[primitives[0]]; + + // Loop through boxes + for(udword i=1;iGetTriangle(VP, *primitives++); + // Update global box + Min.Min(*VP.Vertex[0]).Min(*VP.Vertex[1]).Min(*VP.Vertex[2]); + Max.Max(*VP.Vertex[0]).Max(*VP.Vertex[1]).Max(*VP.Vertex[2]); + } + global_box.SetMinMax(Min, Max); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the splitting value along a given axis for a given primitive. + * \param index [in] index of the primitive to split + * \param axis [in] axis index (0,1,2) + * \return splitting value + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABBTreeOfTrianglesBuilder::GetSplittingValue(udword index, udword axis) const +{ +/* // Compute center of triangle + IcePoint Center; + mTriList[index].Center(mVerts, Center); + // Return value + return Center[axis];*/ + + // Compute correct component from center of triangle +// return (mVerts[mTriList[index].mVRef[0]][axis] +// +mVerts[mTriList[index].mVRef[1]][axis] +// +mVerts[mTriList[index].mVRef[2]][axis])*INV3; + + VertexPointers VP; + mIMesh->GetTriangle(VP, index); + + // Compute correct component from center of triangle + return ((*VP.Vertex[0])[axis] + +(*VP.Vertex[1])[axis] + +(*VP.Vertex[2])[axis])*INV3; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the splitting value along a given axis for a given node. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [in] global AABB enclosing the set of input primitives + * \param axis [in] axis index (0,1,2) + * \return splitting value + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABBTreeOfTrianglesBuilder::GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const +{ + if(mSettings.mRules&SPLIT_GEOM_CENTER) + { + // Loop through triangles + float SplitValue = 0.0f; + VertexPointers VP; + for(udword i=0;iGetTriangle(VP, primitives[i]); + // Update split value + SplitValue += (*VP.Vertex[0])[axis]; + SplitValue += (*VP.Vertex[1])[axis]; + SplitValue += (*VP.Vertex[2])[axis]; + } + return SplitValue / float(nb_prims*3); + } + else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the AABB of a set of primitives. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [out] global AABB enclosing the set of input primitives + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeOfVerticesBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const +{ + // Checkings + if(!primitives || !nb_prims) return false; + + // Initialize global box + global_box.SetEmpty(); + + // Loop through vertices + for(udword i=0;iHasLeafNodes()!=cache.Model1->HasLeafNodes()) return false; + if(cache.Model0->IsQuantized()!=cache.Model1->IsQuantized()) return false; + + /* + + Rules: + - perform hull test + - when hulls collide, disable hull test + - if meshes overlap, reset countdown + - if countdown reaches 0, enable hull test + + */ + +#ifdef __MESHMERIZER_H__ + // Handle hulls + if(cache.HullTest) + { + if(cache.Model0->GetHull() && cache.Model1->GetHull()) + { + struct Local + { + static IcePoint* SVCallback(const IcePoint& sv, udword& previndex, udword user_data) + { + CollisionHull* Hull = (CollisionHull*)user_data; + previndex = Hull->ComputeSupportingVertex(sv, previndex); + return (IcePoint*)&Hull->GetVerts()[previndex]; + } + }; + + bool Collide; + + if(0) + { + static GJKEngine GJK; + static bool GJKInitDone=false; + if(!GJKInitDone) + { + GJK.Enable(GJK_BACKUP_PROCEDURE); + GJK.Enable(GJK_DEGENERATE); + GJK.Enable(GJK_HILLCLIMBING); + GJKInitDone = true; + } + GJK.SetCallbackObj0(Local::SVCallback); + GJK.SetCallbackObj1(Local::SVCallback); + GJK.SetUserData0(udword(cache.Model0->GetHull())); + GJK.SetUserData1(udword(cache.Model1->GetHull())); + Collide = GJK.Collide(*world0, *world1, &cache.SepVector); + } + else + { + static SVEngine SVE; + SVE.SetCallbackObj0(Local::SVCallback); + SVE.SetCallbackObj1(Local::SVCallback); + SVE.SetUserData0(udword(cache.Model0->GetHull())); + SVE.SetUserData1(udword(cache.Model1->GetHull())); + Collide = SVE.Collide(*world0, *world1, &cache.SepVector); + } + + if(!Collide) + { + // Reset stats & contact status + mFlags &= ~OPC_CONTACT; + mNbBVBVTests = 0; + mNbPrimPrimTests = 0; + mNbBVPrimTests = 0; + mPairs.Reset(); + return true; + } + } + } + + // Here, hulls collide + cache.HullTest = false; +#endif // __MESHMERIZER_H__ + + // Checkings + if(!Setup(cache.Model0->GetMeshInterface(), cache.Model1->GetMeshInterface())) return false; + + // Simple double-dispatch + bool Status; + if(!cache.Model0->HasLeafNodes()) + { + if(cache.Model0->IsQuantized()) + { + const AABBQuantizedNoLeafTree* T0 = (const AABBQuantizedNoLeafTree*)cache.Model0->GetTree(); + const AABBQuantizedNoLeafTree* T1 = (const AABBQuantizedNoLeafTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + else + { + const AABBNoLeafTree* T0 = (const AABBNoLeafTree*)cache.Model0->GetTree(); + const AABBNoLeafTree* T1 = (const AABBNoLeafTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + } + else + { + if(cache.Model0->IsQuantized()) + { + const AABBQuantizedTree* T0 = (const AABBQuantizedTree*)cache.Model0->GetTree(); + const AABBQuantizedTree* T1 = (const AABBQuantizedTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + else + { + const AABBCollisionTree* T0 = (const AABBCollisionTree*)cache.Model0->GetTree(); + const AABBCollisionTree* T1 = (const AABBCollisionTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + } + +#ifdef __MESHMERIZER_H__ + if(Status) + { + // Reset counter as long as overlap occurs + if(GetContactStatus()) cache.ResetCountDown(); + + // Enable hull test again when counter reaches zero + cache.CountDown--; + if(!cache.CountDown) + { + cache.ResetCountDown(); + cache.HullTest = true; + } + } +#endif + return Status; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::InitQuery(const Matrix4x4* world0, const Matrix4x4* world1) +{ + // Reset stats & contact status + Collider::InitQuery(); + mNbBVBVTests = 0; + mNbPrimPrimTests = 0; + mNbBVPrimTests = 0; + mPairs.Reset(); + + // Setup matrices + Matrix4x4 InvWorld0, InvWorld1; + if(world0) InvertPRMatrix(InvWorld0, *world0); + else InvWorld0.Identity(); + + if(world1) InvertPRMatrix(InvWorld1, *world1); + else InvWorld1.Identity(); + + Matrix4x4 World0to1 = world0 ? (*world0 * InvWorld1) : InvWorld1; + Matrix4x4 World1to0 = world1 ? (*world1 * InvWorld0) : InvWorld0; + + mR0to1 = World0to1; World0to1.GetTrans(mT0to1); + mR1to0 = World1to0; World1to0.GetTrans(mT1to0); + + // Precompute absolute 1-to-0 rotation matrix + for(udword i=0;i<3;i++) + { + for(udword j=0;j<3;j++) + { + // Epsilon value prevents floating-IcePoint inaccuracies (strategy borrowed from RAPID) + mAR.m[i][j] = 1e-6f + fabsf(mR1to0.m[i][j]); + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Takes advantage of temporal coherence. + * \param cache [in] cache for a pair of previously colliding primitives + * \return true if we can return immediately + * \warning only works for "First Contact" mode + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::CheckTemporalCoherence(Pair* cache) +{ + // Checkings + if(!cache) return false; + + // Test previously colliding primitives first + if(TemporalCoherenceEnabled() && FirstContactEnabled()) + { + PrimTest(cache->id0, cache->id1); + if(GetContactStatus()) return true; + } + return false; +} + +#define UPDATE_CACHE \ + if(cache && GetContactStatus()) \ + { \ + cache->id0 = mPairs.GetEntry(0); \ + cache->id1 = mPairs.GetEntry(1); \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for normal AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for no-leaf AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for quantized AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Setup dequantization coeffs + mCenterCoeff0 = tree0->mCenterCoeff; + mExtentsCoeff0 = tree0->mExtentsCoeff; + mCenterCoeff1 = tree1->mCenterCoeff; + mExtentsCoeff1 = tree1->mExtentsCoeff; + + // Dequantize box A + const AABBQuantizedNode* N0 = tree0->GetNodes(); + const IcePoint a(float(N0->mAABB.mExtents[0]) * mExtentsCoeff0.x, float(N0->mAABB.mExtents[1]) * mExtentsCoeff0.y, float(N0->mAABB.mExtents[2]) * mExtentsCoeff0.z); + const IcePoint Pa(float(N0->mAABB.mCenter[0]) * mCenterCoeff0.x, float(N0->mAABB.mCenter[1]) * mCenterCoeff0.y, float(N0->mAABB.mCenter[2]) * mCenterCoeff0.z); + // Dequantize box B + const AABBQuantizedNode* N1 = tree1->GetNodes(); + const IcePoint b(float(N1->mAABB.mExtents[0]) * mExtentsCoeff1.x, float(N1->mAABB.mExtents[1]) * mExtentsCoeff1.y, float(N1->mAABB.mExtents[2]) * mExtentsCoeff1.z); + const IcePoint Pb(float(N1->mAABB.mCenter[0]) * mCenterCoeff1.x, float(N1->mAABB.mCenter[1]) * mCenterCoeff1.y, float(N1->mAABB.mCenter[2]) * mCenterCoeff1.z); + + // Perform collision query + _Collide(N0, N1, a, Pa, b, Pb); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for quantized no-leaf AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Setup dequantization coeffs + mCenterCoeff0 = tree0->mCenterCoeff; + mExtentsCoeff0 = tree0->mExtentsCoeff; + mCenterCoeff1 = tree1->mCenterCoeff; + mExtentsCoeff1 = tree1->mExtentsCoeff; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Standard trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// The normal AABB tree can use 2 different descent rules (with different performances) +//#define ORIGINAL_CODE //!< UNC-like descent rules +#define ALTERNATIVE_CODE //!< Alternative descent rules + +#ifdef ORIGINAL_CODE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) return; + + if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } + + if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) + { + _Collide(b0->GetNeg(), b1); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1); + } + else + { + _Collide(b0, b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0, b1->GetPos()); + } +} +#endif + +#ifdef ALTERNATIVE_CODE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) + { + return; + } + + if(b0->IsLeaf()) + { + if(b1->IsLeaf()) + { + PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); + } + else + { + _Collide(b0, b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0, b1->GetPos()); + } + } + else if(b1->IsLeaf()) + { + _Collide(b0->GetNeg(), b1); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1); + } + else + { + _Collide(b0->GetNeg(), b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0->GetNeg(), b1->GetPos()); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1->GetPos()); + } +} +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// No-leaf trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for two primitive indices. + * \param id0 [in] index from first leaf-triangle + * \param id1 [in] index from second leaf-triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::PrimTest(udword id0, udword id1) +{ + // Request vertices from the app + VertexPointers VP0; + VertexPointers VP1; + mIMesh0->GetTriangle(VP0, id0); + mIMesh1->GetTriangle(VP1, id1); + + // Transform from space 1 to space 0 + IcePoint u0,u1,u2; + TransformPoint(u0, *VP1.Vertex[0], mR1to0, mT1to0); + TransformPoint(u1, *VP1.Vertex[1], mR1to0, mT1to0); + TransformPoint(u2, *VP1.Vertex[2], mR1to0, mT1to0); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(*VP0.Vertex[0], *VP0.Vertex[1], *VP0.Vertex[2], u0, u1, u2)) + { + // Keep track of colliding pairs + mPairs.Add(id0).Add(id1); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for a previously fetched triangle from tree A (in B's space) and a new leaf from B. + * \param id1 [in] leaf-triangle index from tree B + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void AABBTreeCollider::PrimTestTriIndex(udword id1) +{ + // Request vertices from the app + VertexPointers VP; + mIMesh1->GetTriangle(VP, id1); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Keep track of colliding pairs + mPairs.Add(mLeafIndex).Add(id1); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for a previously fetched triangle from tree B (in A's space) and a new leaf from A. + * \param id0 [in] leaf-triangle index from tree A + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void AABBTreeCollider::PrimTestIndexTri(udword id0) +{ + // Request vertices from the app + VertexPointers VP; + mIMesh0->GetTriangle(VP, id0); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Keep track of colliding pairs + mPairs.Add(id0).Add(mLeafIndex); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from A and a branch from B. + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideTriBox(const AABBNoLeafNode* b) +{ + // Perform triangle-box overlap test + if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; + + // Keep same triangle, deal with first child + if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + // Keep same triangle, deal with second child + if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from B and a branch from A. + * \param b [in] collision node from first tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideBoxTri(const AABBNoLeafNode* b) +{ + // Perform triangle-box overlap test + if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; + + // Keep same triangle, deal with first child + if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); + else _CollideBoxTri(b->GetPos()); + + if(ContactFound()) return; + + // Keep same triangle, deal with second child + if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); + else _CollideBoxTri(b->GetNeg()); +} + +//! Request triangle vertices from the app and transform them +#define FETCH_LEAF(prim_index, imesh, rot, trans) \ + mLeafIndex = prim_index; \ + /* Request vertices from the app */ \ + VertexPointers VP; imesh->GetTriangle(VP, prim_index); \ + /* Transform them in a common space */ \ + TransformPoint(mLeafVerts[0], *VP.Vertex[0], rot, trans); \ + TransformPoint(mLeafVerts[1], *VP.Vertex[1], rot, trans); \ + TransformPoint(mLeafVerts[2], *VP.Vertex[2], rot, trans); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param a [in] collision node from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(a->mAABB.mExtents, a->mAABB.mCenter, b->mAABB.mExtents, b->mAABB.mCenter)) return; + + // Catch leaf status + BOOL BHasPosLeaf = b->HasPosLeaf(); + BOOL BHasNegLeaf = b->HasNegLeaf(); + + if(a->HasPosLeaf()) + { + FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetNeg()); + } + + if(ContactFound()) return; + + if(a->HasNegLeaf()) + { + FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Quantized trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + * \param a [in] extent from box A + * \param Pa [in] center from box A + * \param b [in] extent from box B + * \param Pb [in] center from box B + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const IcePoint& a, const IcePoint& Pa, const IcePoint& b, const IcePoint& Pb) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(a, Pa, b, Pb)) return; + + if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } + + if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) + { + // Dequantize box + const QuantizedAABB* Box = &b0->GetNeg()->mAABB; + const IcePoint negPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); + const IcePoint nega(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); + _Collide(b0->GetNeg(), b1, nega, negPa, b, Pb); + + if(ContactFound()) return; + + // Dequantize box + Box = &b0->GetPos()->mAABB; + const IcePoint posPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); + const IcePoint posa(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); + _Collide(b0->GetPos(), b1, posa, posPa, b, Pb); + } + else + { + // Dequantize box + const QuantizedAABB* Box = &b1->GetNeg()->mAABB; + const IcePoint negPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); + const IcePoint negb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); + _Collide(b0, b1->GetNeg(), a, Pa, negb, negPb); + + if(ContactFound()) return; + + // Dequantize box + Box = &b1->GetPos()->mAABB; + const IcePoint posPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); + const IcePoint posb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); + _Collide(b0, b1->GetPos(), a, Pa, posb, posPb); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Quantized no-leaf trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from A and a quantized branch from B. + * \param leaf [in] leaf triangle from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideTriBox(const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box + const QuantizedAABB* bb = &b->mAABB; + const IcePoint Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); + const IcePoint eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); + + // Perform triangle-box overlap test + if(!TriBoxOverlap(Pb, eb)) return; + + if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from B and a quantized branch from A. + * \param b [in] collision node from first tree + * \param leaf [in] leaf triangle from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideBoxTri(const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box + const QuantizedAABB* bb = &b->mAABB; + const IcePoint Pa(float(bb->mCenter[0]) * mCenterCoeff0.x, float(bb->mCenter[1]) * mCenterCoeff0.y, float(bb->mCenter[2]) * mCenterCoeff0.z); + const IcePoint ea(float(bb->mExtents[0]) * mExtentsCoeff0.x, float(bb->mExtents[1]) * mExtentsCoeff0.y, float(bb->mExtents[2]) * mExtentsCoeff0.z); + + // Perform triangle-box overlap test + if(!TriBoxOverlap(Pa, ea)) return; + + if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); + else _CollideBoxTri(b->GetPos()); + + if(ContactFound()) return; + + if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); + else _CollideBoxTri(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param a [in] collision node from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box A + const QuantizedAABB* ab = &a->mAABB; + const IcePoint Pa(float(ab->mCenter[0]) * mCenterCoeff0.x, float(ab->mCenter[1]) * mCenterCoeff0.y, float(ab->mCenter[2]) * mCenterCoeff0.z); + const IcePoint ea(float(ab->mExtents[0]) * mExtentsCoeff0.x, float(ab->mExtents[1]) * mExtentsCoeff0.y, float(ab->mExtents[2]) * mExtentsCoeff0.z); + // Dequantize box B + const QuantizedAABB* bb = &b->mAABB; + const IcePoint Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); + const IcePoint eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); + + // Perform BV-BV overlap test + if(!BoxBoxOverlap(ea, Pa, eb, Pb)) return; + + // Catch leaf status + BOOL BHasPosLeaf = b->HasPosLeaf(); + BOOL BHasNegLeaf = b->HasNegLeaf(); + + if(a->HasPosLeaf()) + { + FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetNeg()); + } + + if(ContactFound()) return; + + if(a->HasNegLeaf()) + { + FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetNeg()); + } +} diff --git a/third-party/Opcode/OPC_TreeCollider.h b/third-party/Opcode/OPC_TreeCollider.h new file mode 100644 index 0000000..ec0e517 --- /dev/null +++ b/third-party/Opcode/OPC_TreeCollider.h @@ -0,0 +1,244 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a tree collider. + * \file OPC_TreeCollider.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_TREECOLLIDER_H__ +#define __OPC_TREECOLLIDER_H__ + + //! This structure holds cached information used by the algorithm. + //! Two model pointers and two colliding primitives are cached. Model pointers are assigned + //! to their respective meshes, and the pair of colliding primitives is used for temporal + //! coherence. That is, in case temporal coherence is enabled, those two primitives are + //! tested for overlap before everything else. If they still collide, we're done before + //! even entering the recursive collision code. + struct OPCODE_API BVTCache : Pair + { + //! Constructor + inline_ BVTCache() + { + ResetCache(); + ResetCountDown(); + } + + void ResetCache() + { + Model0 = null; + Model1 = null; + id0 = 0; + id1 = 1; +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + HullTest = true; + SepVector.pid = 0; + SepVector.qid = 0; + SepVector.SV = IcePoint(1.0f, 0.0f, 0.0f); +#endif // __MESHMERIZER_H__ + } + + inline_ void ResetCountDown() + { +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + CountDown = 50; +#endif // __MESHMERIZER_H__ + } + + const Model* Model0; //!< Model for first object + const Model* Model1; //!< Model for second object + +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + SVCache SepVector; + udword CountDown; + bool HullTest; +#endif // __MESHMERIZER_H__ + }; + + class OPCODE_API AABBTreeCollider : public Collider + { + public: + // Constructor / Destructor + AABBTreeCollider(); + virtual ~AABBTreeCollider(); + // Generic collision query + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results with: + * - GetContactStatus() + * - GetNbPairs() + * - GetPairs() + * + * \param cache [in] collision cache for model pointers and a colliding pair of primitives + * \param world0 [in] world matrix for first object, or null + * \param world1 [in] world matrix for second object, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(BVTCache& cache, const Matrix4x4* world0=null, const Matrix4x4* world1=null); + + // Collision queries + bool Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: selects between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + * \see SetFullPrimBoxTest(bool flag) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: selects between full triangle-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + * \see SetFullBoxBoxTest(bool flag) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullPrimBoxTest(bool flag) { mFullPrimBoxTest = flag; } + + // Stats + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of BV-BV overlap tests after a collision query. + * \see GetNbPrimPrimTests() + * \see GetNbBVPrimTests() + * \return the number of BV-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbBVBVTests() const { return mNbBVBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Triangle-Triangle overlap tests after a collision query. + * \see GetNbBVBVTests() + * \see GetNbBVPrimTests() + * \return the number of Triangle-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbPrimPrimTests() const { return mNbPrimPrimTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of BV-Triangle overlap tests after a collision query. + * \see GetNbBVBVTests() + * \see GetNbPrimPrimTests() + * \return the number of BV-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbBVPrimTests() const { return mNbBVPrimTests; } + + // Data access + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of contacts after a collision query. + * \see GetContactStatus() + * \see GetPairs() + * \return the number of contacts / colliding pairs. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbPairs() const { return mPairs.GetNbEntries()>>1; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the pairs of colliding triangles after a collision query. + * \see GetContactStatus() + * \see GetNbPairs() + * \return the list of colliding pairs (triangle indices) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const Pair* GetPairs() const { return (const Pair*)mPairs.GetEntries(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Colliding pairs + Container mPairs; //!< Pairs of colliding primitives + // User mesh interfaces + const MeshInterface* mIMesh0; //!< User-defined mesh interface for object0 + const MeshInterface* mIMesh1; //!< User-defined mesh interface for object1 + // Stats + udword mNbBVBVTests; //!< Number of BV-BV tests + udword mNbPrimPrimTests; //!< Number of Primitive-Primitive tests + udword mNbBVPrimTests; //!< Number of BV-Primitive tests + // Precomputed data + Matrix3x3 mAR; //!< Absolute rotation matrix + Matrix3x3 mR0to1; //!< Rotation from object0 to object1 + Matrix3x3 mR1to0; //!< Rotation from object1 to object0 + IcePoint mT0to1; //!< Translation from object0 to object1 + IcePoint mT1to0; //!< Translation from object1 to object0 + // Dequantization coeffs + IcePoint mCenterCoeff0; + IcePoint mExtentsCoeff0; + IcePoint mCenterCoeff1; + IcePoint mExtentsCoeff1; + // Leaf description + IcePoint mLeafVerts[3]; //!< Triangle vertices + udword mLeafIndex; //!< Triangle index + // Settings + bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) + bool mFullPrimBoxTest; //!< Perform full Primitive-BV tests (true) or SAT-lite tests (false) + // Internal methods + + // Standard AABB trees + void _Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1); + // Quantized AABB trees + void _Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const IcePoint& a, const IcePoint& Pa, const IcePoint& b, const IcePoint& Pb); + // No-leaf AABB trees + void _CollideTriBox(const AABBNoLeafNode* b); + void _CollideBoxTri(const AABBNoLeafNode* b); + void _Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b); + // Quantized no-leaf AABB trees + void _CollideTriBox(const AABBQuantizedNoLeafNode* b); + void _CollideBoxTri(const AABBQuantizedNoLeafNode* b); + void _Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b); + // Overlap tests + void PrimTest(udword id0, udword id1); + inline_ void PrimTestTriIndex(udword id1); + inline_ void PrimTestIndexTri(udword id0); + + inline_ BOOL BoxBoxOverlap(const IcePoint& ea, const IcePoint& ca, const IcePoint& eb, const IcePoint& cb); + inline_ BOOL TriBoxOverlap(const IcePoint& center, const IcePoint& extents); + inline_ BOOL TriTriOverlap(const IcePoint& V0, const IcePoint& V1, const IcePoint& V2, const IcePoint& U0, const IcePoint& U1, const IcePoint& U2); + // Init methods + void InitQuery(const Matrix4x4* world0=null, const Matrix4x4* world1=null); + bool CheckTemporalCoherence(Pair* cache); + + inline_ BOOL Setup(const MeshInterface* mi0, const MeshInterface* mi1) + { + mIMesh0 = mi0; + mIMesh1 = mi1; + + if(!mIMesh0 || !mIMesh1) return FALSE; + + return TRUE; + } + }; + +#endif // __OPC_TREECOLLIDER_H__ diff --git a/third-party/Opcode/OPC_TriBoxOverlap.h b/third-party/Opcode/OPC_TriBoxOverlap.h new file mode 100644 index 0000000..e32673b --- /dev/null +++ b/third-party/Opcode/OPC_TriBoxOverlap.h @@ -0,0 +1,339 @@ + +//! This macro quickly finds the min & max values among 3 variables +#define FINDMINMAX(x0, x1, x2, min, max) \ + min = max = x0; \ + if(x1max) max=x1; \ + if(x2max) max=x2; + +//! TO BE DOCUMENTED +inline_ BOOL planeBoxOverlap(const IcePoint& normal, const float d, const IcePoint& maxbox) +{ + IcePoint vmin, vmax; + for(udword q=0;q<=2;q++) + { + if(normal[q]>0.0f) { vmin[q]=-maxbox[q]; vmax[q]=maxbox[q]; } + else { vmin[q]=maxbox[q]; vmax[q]=-maxbox[q]; } + } + if((normal|vmin)+d>0.0f) return FALSE; + if((normal|vmax)+d>=0.0f) return TRUE; + + return FALSE; +} + +//! TO BE DOCUMENTED +#define AXISTEST_X01(a, b, fa, fb) \ + min = a*v0.y - b*v0.z; \ + max = a*v2.y - b*v2.z; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.y + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_X2(a, b, fa, fb) \ + min = a*v0.y - b*v0.z; \ + max = a*v1.y - b*v1.z; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.y + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Y02(a, b, fa, fb) \ + min = b*v0.z - a*v0.x; \ + max = b*v2.z - a*v2.x; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Y1(a, b, fa, fb) \ + min = b*v0.z - a*v0.x; \ + max = b*v1.z - a*v1.x; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Z12(a, b, fa, fb) \ + min = a*v1.x - b*v1.y; \ + max = a*v2.x - b*v2.y; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.y; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Z0(a, b, fa, fb) \ + min = a*v0.x - b*v0.y; \ + max = a*v1.x - b*v1.y; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.y; \ + if(min>rad || max<-rad) return FALSE; + +// compute triangle edges +// - edges lazy evaluated to take advantage of early exits +// - fabs precomputed (half less work, possible since extents are always >0) +// - customized macros to take advantage of the null component +// - axis vector discarded, possibly saves useless movs +#define IMPLEMENT_CLASS3_TESTS \ + float rad; \ + float min, max; \ + \ + const float fey0 = fabsf(e0.y); \ + const float fez0 = fabsf(e0.z); \ + AXISTEST_X01(e0.z, e0.y, fez0, fey0); \ + const float fex0 = fabsf(e0.x); \ + AXISTEST_Y02(e0.z, e0.x, fez0, fex0); \ + AXISTEST_Z12(e0.y, e0.x, fey0, fex0); \ + \ + const float fey1 = fabsf(e1.y); \ + const float fez1 = fabsf(e1.z); \ + AXISTEST_X01(e1.z, e1.y, fez1, fey1); \ + const float fex1 = fabsf(e1.x); \ + AXISTEST_Y02(e1.z, e1.x, fez1, fex1); \ + AXISTEST_Z0(e1.y, e1.x, fey1, fex1); \ + \ + const IcePoint e2 = mLeafVerts[0] - mLeafVerts[2]; \ + const float fey2 = fabsf(e2.y); \ + const float fez2 = fabsf(e2.z); \ + AXISTEST_X2(e2.z, e2.y, fez2, fey2); \ + const float fex2 = fabsf(e2.x); \ + AXISTEST_Y1(e2.z, e2.x, fez2, fex2); \ + AXISTEST_Z12(e2.y, e2.x, fey2, fex2); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Triangle-Box overlap test using the separating axis theorem. + * This is the code from Tomas Möller, a bit optimized: + * - with some more lazy evaluation (faster path on PC) + * - with a tiny bit of assembly + * - with "SAT-lite" applied if needed + * - and perhaps with some more minor modifs... + * + * \param center [in] box center + * \param extents [in] box extents + * \return true if triangle & box overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::TriBoxOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbBVPrimTests++; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // move everything so that the boxcenter is in (0,0,0) + IcePoint v0, v1, v2; + v0.x = mLeafVerts[0].x - center.x; + v1.x = mLeafVerts[1].x - center.x; + v2.x = mLeafVerts[2].x - center.x; + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; + + // same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; + + // same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>extents.x || max<-extents.x) return FALSE; + + // Same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>extents.y || max<-extents.y) return FALSE; + + // Same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>extents.z || max<-extents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const IcePoint e0 = v1 - v0; + const IcePoint e1 = v2 - v1; + const IcePoint normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, extents)) return FALSE; + + // 3) "Class III" tests + if(mFullPrimBoxTest) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} + +//! A dedicated version where the box is constant +inline_ BOOL OBBCollider::TriBoxOverlap() +{ + // Stats + mNbVolumePrimTests++; + + // Hook + const IcePoint& extents = mBoxExtents; + const IcePoint& v0 = mLeafVerts[0]; + const IcePoint& v1 = mLeafVerts[1]; + const IcePoint& v2 = mLeafVerts[2]; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // Box center is already in (0,0,0) + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>mBoxExtents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-mBoxExtents.x) return FALSE; + + if(FCMin3(v0.y, v1.y, v2.y)>mBoxExtents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-mBoxExtents.y) return FALSE; + + if(FCMin3(v0.z, v1.z, v2.z)>mBoxExtents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-mBoxExtents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>mBoxExtents.x || max<-mBoxExtents.x) return FALSE; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>mBoxExtents.y || max<-mBoxExtents.y) return FALSE; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>mBoxExtents.z || max<-mBoxExtents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const IcePoint e0 = v1 - v0; + const IcePoint e1 = v2 - v1; + const IcePoint normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, mBoxExtents)) return FALSE; + + // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} + +//! ...and another one, jeez +inline_ BOOL AABBCollider::TriBoxOverlap() +{ + // Stats + mNbVolumePrimTests++; + + // Hook + const IcePoint& center = mBox.mCenter; + const IcePoint& extents = mBox.mExtents; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // move everything so that the boxcenter is in (0,0,0) + IcePoint v0, v1, v2; + v0.x = mLeafVerts[0].x - center.x; + v1.x = mLeafVerts[1].x - center.x; + v2.x = mLeafVerts[2].x - center.x; + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; + + // same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; + + // same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>extents.x || max<-extents.x) return FALSE; + + // Same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>extents.y || max<-extents.y) return FALSE; + + // Same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>extents.z || max<-extents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const IcePoint e0 = v1 - v0; + const IcePoint e1 = v2 - v1; + const IcePoint normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, extents)) return FALSE; + + // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} diff --git a/third-party/Opcode/OPC_TriTriOverlap.h b/third-party/Opcode/OPC_TriTriOverlap.h new file mode 100644 index 0000000..a9ee9c5 --- /dev/null +++ b/third-party/Opcode/OPC_TriTriOverlap.h @@ -0,0 +1,279 @@ + +//! if OPC_TRITRI_EPSILON_TEST is true then we do a check (if |dv|b) \ + { \ + const float c=a; \ + a=b; \ + b=c; \ + } + +//! Edge to edge test based on Franlin Antonio's gem: "Faster Line IceSegment Intersection", in Graphics Gems III, pp. 199-202 +#define EDGE_EDGE_TEST(V0, U0, U1) \ + Bx = U0[i0] - U1[i0]; \ + By = U0[i1] - U1[i1]; \ + Cx = V0[i0] - U0[i0]; \ + Cy = V0[i1] - U0[i1]; \ + f = Ay*Bx - Ax*By; \ + d = By*Cx - Bx*Cy; \ + if((f>0.0f && d>=0.0f && d<=f) || (f<0.0f && d<=0.0f && d>=f)) \ + { \ + const float e=Ax*Cy - Ay*Cx; \ + if(f>0.0f) \ + { \ + if(e>=0.0f && e<=f) return TRUE; \ + } \ + else \ + { \ + if(e<=0.0f && e>=f) return TRUE; \ + } \ + } + +//! TO BE DOCUMENTED +#define EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2) \ +{ \ + float Bx,By,Cx,Cy,d,f; \ + const float Ax = V1[i0] - V0[i0]; \ + const float Ay = V1[i1] - V0[i1]; \ + /* test edge U0,U1 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U0, U1); \ + /* test edge U1,U2 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U1, U2); \ + /* test edge U2,U1 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U2, U0); \ +} + +//! TO BE DOCUMENTED +#define POINT_IN_TRI(V0, U0, U1, U2) \ +{ \ + /* is T1 completly inside T2? */ \ + /* check if V0 is inside tri(U0,U1,U2) */ \ + float a = U1[i1] - U0[i1]; \ + float b = -(U1[i0] - U0[i0]); \ + float c = -a*U0[i0] - b*U0[i1]; \ + float d0 = a*V0[i0] + b*V0[i1] + c; \ + \ + a = U2[i1] - U1[i1]; \ + b = -(U2[i0] - U1[i0]); \ + c = -a*U1[i0] - b*U1[i1]; \ + const float d1 = a*V0[i0] + b*V0[i1] + c; \ + \ + a = U0[i1] - U2[i1]; \ + b = -(U0[i0] - U2[i0]); \ + c = -a*U2[i0] - b*U2[i1]; \ + const float d2 = a*V0[i0] + b*V0[i1] + c; \ + if(d0*d1>0.0f) \ + { \ + if(d0*d2>0.0f) return TRUE; \ + } \ +} + +//! TO BE DOCUMENTED +BOOL CoplanarTriTri(const IcePoint& n, const IcePoint& v0, const IcePoint& v1, const IcePoint& v2, const IcePoint& u0, const IcePoint& u1, const IcePoint& u2) +{ + float A[3]; + short i0,i1; + /* first project onto an axis-aligned plane, that maximizes the area */ + /* of the triangles, compute indices: i0,i1. */ + A[0] = fabsf(n[0]); + A[1] = fabsf(n[1]); + A[2] = fabsf(n[2]); + if(A[0]>A[1]) + { + if(A[0]>A[2]) + { + i0=1; /* A[0] is greatest */ + i1=2; + } + else + { + i0=0; /* A[2] is greatest */ + i1=1; + } + } + else /* A[0]<=A[1] */ + { + if(A[2]>A[1]) + { + i0=0; /* A[2] is greatest */ + i1=1; + } + else + { + i0=0; /* A[1] is greatest */ + i1=2; + } + } + + /* test all edges of triangle 1 against the edges of triangle 2 */ + EDGE_AGAINST_TRI_EDGES(v0, v1, u0, u1, u2); + EDGE_AGAINST_TRI_EDGES(v1, v2, u0, u1, u2); + EDGE_AGAINST_TRI_EDGES(v2, v0, u0, u1, u2); + + /* finally, test if tri1 is totally contained in tri2 or vice versa */ + POINT_IN_TRI(v0, u0, u1, u2); + POINT_IN_TRI(u0, v0, v1, v2); + + return FALSE; +} + +//! TO BE DOCUMENTED +#define NEWCOMPUTE_INTERVALS(VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, A, B, C, X0, X1) \ +{ \ + if(D0D1>0.0f) \ + { \ + /* here we know that D0D2<=0.0 */ \ + /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ + A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ + } \ + else if(D0D2>0.0f) \ + { \ + /* here we know that d0d1<=0.0 */ \ + A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ + } \ + else if(D1*D2>0.0f || D0!=0.0f) \ + { \ + /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ + A=VV0; B=(VV1 - VV0)*D0; C=(VV2 - VV0)*D0; X0=D0 - D1; X1=D0 - D2; \ + } \ + else if(D1!=0.0f) \ + { \ + A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ + } \ + else if(D2!=0.0f) \ + { \ + A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ + } \ + else \ + { \ + /* triangles are coplanar */ \ + return CoplanarTriTri(N1, V0, V1, V2, U0, U1, U2); \ + } \ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Triangle/triangle intersection test routine, + * by Tomas Moller, 1997. + * See article "A Fast Triangle-Triangle Intersection Test", + * Journal of Graphics Tools, 2(2), 1997 + * + * Updated June 1999: removed the divisions -- a little faster now! + * Updated October 1999: added {} to CROSS and SUB macros + * + * int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3], + * float U0[3],float U1[3],float U2[3]) + * + * \param V0 [in] triangle 0, vertex 0 + * \param V1 [in] triangle 0, vertex 1 + * \param V2 [in] triangle 0, vertex 2 + * \param U0 [in] triangle 1, vertex 0 + * \param U1 [in] triangle 1, vertex 1 + * \param U2 [in] triangle 1, vertex 2 + * \return true if triangles overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::TriTriOverlap(const IcePoint& V0, const IcePoint& V1, const IcePoint& V2, const IcePoint& U0, const IcePoint& U1, const IcePoint& U2) +{ + // Stats + mNbPrimPrimTests++; + + // Compute plane equation of triangle(V0,V1,V2) + IcePoint E1 = V1 - V0; + IcePoint E2 = V2 - V0; + const IcePoint N1 = E1 ^ E2; + const float d1 =-N1 | V0; + // IcePlane equation 1: N1.X+d1=0 + + // Put U0,U1,U2 into plane equation 1 to compute signed distances to the plane + float du0 = (N1|U0) + d1; + float du1 = (N1|U1) + d1; + float du2 = (N1|U2) + d1; + + // Coplanarity robustness check +#ifdef OPC_TRITRI_EPSILON_TEST + if(fabsf(du0)0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ? + return FALSE; // no intersection occurs + + // Compute plane of triangle (U0,U1,U2) + E1 = U1 - U0; + E2 = U2 - U0; + const IcePoint N2 = E1 ^ E2; + const float d2=-N2 | U0; + // plane equation 2: N2.X+d2=0 + + // put V0,V1,V2 into plane equation 2 + float dv0 = (N2|V0) + d2; + float dv1 = (N2|V1) + d2; + float dv2 = (N2|V2) + d2; + +#ifdef OPC_TRITRI_EPSILON_TEST + if(fabsf(dv0)0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ? + return FALSE; // no intersection occurs + + // Compute direction of intersection line + const IcePoint D = N1^N2; + + // Compute and index to the largest component of D + float max=fabsf(D[0]); + short index=0; + float bb=fabsf(D[1]); + float cc=fabsf(D[2]); + if(bb>max) max=bb,index=1; + if(cc>max) max=cc,index=2; + + // This is the simplified projection onto L + const float vp0 = V0[index]; + const float vp1 = V1[index]; + const float vp2 = V2[index]; + + const float up0 = U0[index]; + const float up1 = U1[index]; + const float up2 = U2[index]; + + // Compute interval for triangle 1 + float a,b,c,x0,x1; + NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1); + + // Compute interval for triangle 2 + float d,e,f,y0,y1; + NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1); + + const float xx=x0*x1; + const float yy=y0*y1; + const float xxyy=xx*yy; + + float isect1[2], isect2[2]; + + float tmp=a*xxyy; + isect1[0]=tmp+b*x1*yy; + isect1[1]=tmp+c*x0*yy; + + tmp=d*xxyy; + isect2[0]=tmp+e*xx*y1; + isect2[1]=tmp+f*xx*y0; + + SORT(isect1[0],isect1[1]); + SORT(isect2[0],isect2[1]); + + if(isect1[1]HasPosLeaf()) mTouchedPrimitives->Add(node->GetPosPrimitive()); \ + else _Dump(node->GetPos()); \ + \ + if(ContactFound()) return; \ + \ + if(node->HasNegLeaf()) mTouchedPrimitives->Add(node->GetNegPrimitive()); \ + else _Dump(node->GetNeg()); \ +} + +#define IMPLEMENT_LEAFDUMP(type) \ +void VolumeCollider::_Dump(const type* node) \ +{ \ + if(node->IsLeaf()) \ + { \ + mTouchedPrimitives->Add(node->GetPrimitive()); \ + } \ + else \ + { \ + _Dump(node->GetPos()); \ + \ + if(ContactFound()) return; \ + \ + _Dump(node->GetNeg()); \ + } \ +} + +IMPLEMENT_NOLEAFDUMP(AABBNoLeafNode) +IMPLEMENT_NOLEAFDUMP(AABBQuantizedNoLeafNode) + +IMPLEMENT_LEAFDUMP(AABBCollisionNode) +IMPLEMENT_LEAFDUMP(AABBQuantizedNode) diff --git a/third-party/Opcode/OPC_VolumeCollider.h b/third-party/Opcode/OPC_VolumeCollider.h new file mode 100644 index 0000000..330f6a6 --- /dev/null +++ b/third-party/Opcode/OPC_VolumeCollider.h @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base volume collider class. + * \file OPC_VolumeCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_VOLUMECOLLIDER_H__ +#define __OPC_VOLUMECOLLIDER_H__ + + struct OPCODE_API VolumeCache + { + VolumeCache() : Model(null) {} + ~VolumeCache() {} + + Container TouchedPrimitives; //!< Indices of touched primitives + const BaseModel* Model; //!< Owner + }; + + class OPCODE_API VolumeCollider : public Collider + { + public: + // Constructor / Destructor + VolumeCollider(); + virtual ~VolumeCollider() = 0; + + // Collision report + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of touched primitives after a collision query. + * \see GetContactStatus() + * \see GetTouchedPrimitives() + * \return the number of touched primitives + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetNbEntries() : 0; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the list of touched primitives after a collision query. + * \see GetContactStatus() + * \see GetNbTouchedPrimitives() + * \return the list of touched primitives (primitive indices) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const udword* GetTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetEntries() : null; } + + // Stats + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Volume-BV overlap tests after a collision query. + * \see GetNbVolumePrimTests() + * \return the number of Volume-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbVolumeBVTests() const { return mNbVolumeBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Volume-Triangle overlap tests after a collision query. + * \see GetNbVolumeBVTests() + * \return the number of Volume-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbVolumePrimTests() const { return mNbVolumePrimTests; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Touched primitives + Container* mTouchedPrimitives; //!< List of touched primitives + + // Dequantization coeffs + IcePoint mCenterCoeff; + IcePoint mExtentsCoeff; + // Stats + udword mNbVolumeBVTests; //!< Number of Volume-BV tests + udword mNbVolumePrimTests; //!< Number of Volume-Primitive tests + // Internal methods + void _Dump(const AABBCollisionNode* node); + void _Dump(const AABBNoLeafNode* node); + void _Dump(const AABBQuantizedNode* node); + void _Dump(const AABBQuantizedNoLeafNode* node); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Initializes a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) inline_ void InitQuery() + { + // Reset stats & contact status + mNbVolumeBVTests = 0; + mNbVolumePrimTests = 0; + Collider::InitQuery(); + } + + inline_ BOOL IsCacheValid(VolumeCache& cache) + { + // We're going to do a volume-vs-model query. + if(cache.Model!=mCurrentModel) + { + // Cached list was for another model so we can't keep it + // Keep track of new owner and reset cache + cache.Model = mCurrentModel; + return FALSE; + } + else + { + // Same models, no problem + return TRUE; + } + } + }; + +#endif // __OPC_VOLUMECOLLIDER_H__ diff --git a/third-party/Opcode/Opcode.cpp b/third-party/Opcode/Opcode.cpp new file mode 100644 index 0000000..7a90153 --- /dev/null +++ b/third-party/Opcode/Opcode.cpp @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main file for Opcode.dll. + * \file Opcode.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + Finding a good name is difficult! + Here's the draft for this lib.... Spooky, uh? + + VOID? Very Optimized Interference Detection + ZOID? Zappy's Optimized Interference Detection + CID? Custom/Clever Interference Detection + AID / ACID! Accurate Interference Detection + QUID? Quick Interference Detection + RIDE? Realtime Interference DEtection + WIDE? Wicked Interference DEtection (....) + GUID! + KID ! k-dop interference detection :) + OPCODE! OPtimized COllision DEtection +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +bool Opcode::InitOpcode() +{ + Log("// Initializing OPCODE\n\n"); +// LogAPIInfo(); + return true; +} + +void ReleasePruningSorters(); +bool Opcode::CloseOpcode() +{ + Log("// Closing OPCODE\n\n"); + + ReleasePruningSorters(); + + return true; +} + +#ifdef ICE_MAIN + +void ModuleAttach(HINSTANCE hinstance) +{ +} + +void ModuleDetach() +{ +} + +#endif \ No newline at end of file diff --git a/third-party/Opcode/Opcode.h b/third-party/Opcode/Opcode.h new file mode 100644 index 0000000..a6f4adc --- /dev/null +++ b/third-party/Opcode/Opcode.h @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main file for Opcode.dll. + * \file Opcode.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPCODE_H__ +#define __OPCODE_H__ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Preprocessor +#ifdef WIN32 + #ifdef OPCODE_EXPORTS + #define OPCODE_API __declspec(dllexport) + #else + #define OPCODE_API __declspec(dllimport) + #endif +#else + #define OPCODE_API +#endif + + #include "OPC_IceHook.h" + + namespace Opcode + { + // Bulk-of-the-work + #include "OPC_Settings.h" + #include "OPC_Common.h" + #include "OPC_MeshInterface.h" + // Builders + #include "OPC_TreeBuilders.h" + // Trees + #include "OPC_AABBTree.h" + #include "OPC_OptimizedTree.h" + // Models + #include "OPC_BaseModel.h" + #include "OPC_Model.h" + #include "OPC_HybridModel.h" + // Colliders + #include "OPC_Collider.h" + #include "OPC_VolumeCollider.h" + #include "OPC_TreeCollider.h" + #include "OPC_RayCollider.h" + #include "OPC_SphereCollider.h" + #include "OPC_OBBCollider.h" + #include "OPC_AABBCollider.h" + #include "OPC_LSSCollider.h" + #include "OPC_PlanesCollider.h" + // Usages + #include "OPC_Picking.h" + // Sweep-and-prune + #include "OPC_BoxPruning.h" + #include "OPC_SweepAndPrune.h" + + FUNCTION OPCODE_API bool InitOpcode(); + FUNCTION OPCODE_API bool CloseOpcode(); + } + +#endif // __OPCODE_H__ diff --git a/third-party/Opcode/ReadMe.txt b/third-party/Opcode/ReadMe.txt new file mode 100644 index 0000000..ee16382 --- /dev/null +++ b/third-party/Opcode/ReadMe.txt @@ -0,0 +1,171 @@ + + OPCODE distribution 1.3 (june 2003) + ----------------------- + + New in Opcode 1.3: + - fixed the divide by 0 bug that was happening when all centers where located on a coordinate axis (thanks to Jorrit T) + - linearized "complete" vanilla AABB trees + - ANSI-compliant "for" loops (for the ones porting it to Linux...) + - callbacks & pointers moved to mesh interface + - support for triangle & vertex strides + - optimized the sphere-triangle overlap code a bit + - dynamic trees (refit) + - more builders + - ValidateSubdivision in builders + - LSS collider + - primitive-bv tests can now be skipped in most volume queries + - temporal coherence now also works for airborne objects + - temporal coherence completed for boxes / all contacts, LSS, etc + - ray-collider now uses a callback + - some common "usages" have been introduced (only picking for now) + - SPLIT_COMPLETE removed (now implicitely using mLimit = 1) + - hybrid collision models + - sweep-and-prune code added, moved from my old Z-Collide lib + - it now works with meshes made of only 1 triangle (except in mesh-mesh case!) + + Disclaimer: + + - I forced myself to actually *do* the release today no matter what. Else it would never have been done. That's + why the code may not be very polished. I also removed a *lot* of things (more usages, distance queries, etc...) + that weren't ready for prime-time (or that were linked to too many of my supporting libs) + + - Some comments may also be obsolete here and there. The old User Manual for Opcode 1.2 may not fit version 1.3 + either, since there's a new "mesh interface" to support strides, etc. + + - Everything in the "Ice" directory has been hacked out of my engine and edited until everything compiled. Don't + expect anything out there to be cute or something. In particular, some CPP files are not even included when not + needed, so you can expect some linker errors if you try messing around with them... + + Otherwise, it should be just like previous version, only better. In particular, hybrid models can be very + memory-friendly (sometimes using like 10 times less ram than the best trees from version 1.2). The possible + speed hit is often invisible (if it even exists), especially using temporal coherence in "all contacts" mode. + (Admittedly, this depends on your particular usage pattern / what you do on collided triangles). + + The sweep-and-prune code is similar to the "vanilla" version found in V-Collide (but that one's better IMHO...) + The simple "radix" version is often just as good, see for yourself. + + OPCODE distribution 1.2 (august 2002) + ----------------------- + + New in Opcode 1.2: + - new VolumeCollider base class + - simplified callback setup + - you can now use callbacks or pointers (setup at compile time) + - destination array not needed anymore in the RayCollider (faster in-out tests) + - renamed classes: AABBRayCollider => RayCollider, AABBSphereCollider => SphereCollider + - the sphere query now only returns a list of faces (extra info discarded). On the other hand it's a lot faster. + - OBB, AABB and planes queries. Original OBB and AABB queries contributed by Erwin de Vries. + - cosmetic changes in OPC_BoxBoxOverlap.h contributed by Gottfried Chen + - some inlining problems fixed + - faster ray-mesh tests using the separating axis theorem + - new split value in AABB tree construction (contributed by Igor Kravtchenko). Provides faster queries most of the time. + - improved temporal coherence for sphere & AABB queries (works in "All contacts" mode) + + Notes: + + - Everything in the "Ice code" directory (in VC++) is basically copy-pasted from my engine, with a lot + of code removed until there was no link error anymore. Don't expect those files to be cute or anything, + they've never been meant to be released and they're often updated/modified/messy. + - Some experimental features have been removed as well. Else I would never have released the 1.2... + - Not as polished/optimal as I would like it to be, but that's life. I promised myself to release it + before october 2002 (one YEAR later ?!).... That's the only reason why it's there. + - Some people reported ColDet was faster. Uh, come on. They were using Opcode in + "All contacts" mode whereas ColDet was doing "first contact"... + + OPCODE distribution 1.1 (october 2001) + ----------------------- + + New in Opcode 1.1: + - stabbing queries + - sphere queries + - abtract base class for colliders + - settings validation methods + - compilation flags now grouped in OPC_Settings.h + - smaller files, new VC++ virtual dirs (cleaner) + + Notes: + + - "override(baseclass)" is a personal cosmetic thing. It's the same as "virtual", but provides more info. + - I code in 1600*1200, so some lines may look a bit long.. + - This version is not as polished as the previous one due to lack of time. The stabbing & sphere queries + can still be optimized: for example by trying other atomic overlap tests. I'm using my first ray-AABB + code, but the newer one seems better. Tim Schröder's one is good as well. See: www.codercorner.com/RayAABB.cpp + - The trees can easily be compressed even more, I save this for later (lack of time, lack of time!) + - I removed various tests before releasing this one: + - a separation line, a.k.a. "front" in QuickCD, because gains were unclear + - distance queries in a PQP style, because it was way too slow + - support for deformable models, too slow as well + - You can easily use Opcode to do your player-vs-world collision detection, in a Nettle/Telemachos way. + If someone out there wants to donate some art / level for the cause, I'd be glad to release a demo. (current + demo uses copyrighted art I'm not allowed to spread) + - Sorry for the lack of real docs and/or solid examples. I just don't have enough time. + + OPCODE distribution 1.0 (march 2001) + ----------------------- + + - First release + + =============================================================================== + + WHAT ? + + OPCODE means OPtimized COllision DEtection. + So this is a collision detection package similar to RAPID. Here's a + quick list of features: + + - C++ interface, developed for Windows systems using VC++ 6.0 + - Works on arbitrary meshes (convex or non-convex), even polygon soups + - Current implementation uses AABB-trees + - Introduces Primitive-BV overlap tests during recursive collision queries (whereas + standard libraries only rely on Primitive-Primitive and BV-BV tests) + - Introduces no-leaf trees, i.e. collision trees whose leaf nodes have been removed + - Supports collision queries on quantized trees (decompressed on-the-fly) + - Supports "first contact" or "all contacts" modes (à la RAPID) + - Uses temporal coherence for "first contact" mode (~10 to 20 times faster, useful + in rigid body simulation during bisection) + - Memory footprint is 7.2 times smaller than RAPID's one, which is ideal for console + games with limited ram (actually, if you use the unmodified RAPID code using double + precision, it's more like 13 times smaller...) + - And yet it often runs faster than RAPID (according to RDTSC, sometimes more than 5 + times faster when objects are deeply overlapping) + - Performance is usually close to RAPID's one in close-proximity situations + - Stabbing, planes & volume queries (sphere, AABB, OBB, LSS) + - Sweep-and-prune + - Now works with deformable meshes + - Hybrid trees + + + What it can be used for: + - standard mesh-mesh collision detection (similar to RAPID, SOLID, QuickCD, PQP, ColDet...) + - N-body collisions (similar to V-Collide) + - camera-vs-world collisions (similar to Telemachos/Paul Nettle/Stan Melax articles) + - shadow feelers to speed up lightmap computations + - in-out tests to speed up voxelization processes + - picking + - rigid body simulation + - view frustum culling + - etc + + WHY ? + + - Because RAPID uses too many bytes. + - Because the idea was nice... + + WHEN ? + + It's been coded in march 2001 following a thread on the GD-Algorithms list. + + GDAlgorithms-list mailing list + GDAlgorithms-list@lists.sourceforge.net + http://lists.sourceforge.net/lists/listinfo/gdalgorithms-list + + WHO ? + + Pierre Terdiman + June, 1, 2003 + + p.terdiman@wanadoo.fr + p.terdiman@codercorner.com + + http://www.codercorner.com + http://www.codercorner.com/Opcode.htm diff --git a/third-party/Opcode/StdAfx.cpp b/third-party/Opcode/StdAfx.cpp new file mode 100644 index 0000000..2350f92 --- /dev/null +++ b/third-party/Opcode/StdAfx.cpp @@ -0,0 +1,10 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//#define ICE_MAIN +#include "StdAfx.h" diff --git a/third-party/Opcode/StdAfx.h b/third-party/Opcode/StdAfx.h new file mode 100644 index 0000000..0223a6c --- /dev/null +++ b/third-party/Opcode/StdAfx.h @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) +#define AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// Insert your headers here +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include "Opcode.h" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) diff --git a/third-party/Opcode/TemporalCoherence.txt b/third-party/Opcode/TemporalCoherence.txt new file mode 100644 index 0000000..8fde158 --- /dev/null +++ b/third-party/Opcode/TemporalCoherence.txt @@ -0,0 +1,32 @@ + +> Hi John, +> +> I know I'll forget to tell you this if I don't write it right now.... +> +> >(2) How is the receiving geometry for the shadow decided? +> +> I wrote about an LSS-test but actually performing a new VFC test (from the +> light's view) is the same. In both cases, here's a trick to take advantage +> of temporal coherence : test the world against a slightly larger than +> necessary LSS or frustum. Keep the list of touched surfaces. Then next +> frame, if the new volume is still contained within the previous one used +for +> the query, you can reuse the same list immediately. Actually it's a bit +> similar to what you did in your sphere-tree, I think. Anyway, now the +O(log +> N) VFC is O(1) for some frames. It's not worth it for the "real" VFC, but +> when you have N virtual frustum to test to drop N shadows, that's another +> story. +> +> Two downsides: +> - You need more ram to keep track of one list of meshes / shadow, but +> usually it's not a lot. +> - By using a larger volume for the query you possibly touch more +> faces/surfaces, which will be rendered in the shadow pass. Usually it's +not +> a problem either since rendering is simply faster than geometric queries +> those days. But of course, "your mileage may vary". +> +> Happy new year ! +> +> Pierre diff --git a/third-party/gtest/CMakeLists.txt b/third-party/gtest/CMakeLists.txt new file mode 100644 index 0000000..657bacc --- /dev/null +++ b/third-party/gtest/CMakeLists.txt @@ -0,0 +1,7 @@ +set(BUILD_GMOCK OFF CACHE INTERNAL "") +set(INSTALL_GTEST OFF CACHE INTERNAL "") +FetchContent_Declare( + GTest + URL https://github.com/google/googletest/archive/refs/tags/v1.13.0.tar.gz + URL_HASH SHA1=bfa4b5131b6eaac06962c251742c96aab3f7aa78 + DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/third-party/gtest/LICENSE b/third-party/gtest/LICENSE new file mode 100644 index 0000000..1941a11 --- /dev/null +++ b/third-party/gtest/LICENSE @@ -0,0 +1,28 @@ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third-party/infoware/1.current.patch b/third-party/infoware/1.current.patch new file mode 100644 index 0000000..9ef31bc --- /dev/null +++ b/third-party/infoware/1.current.patch @@ -0,0 +1,30 @@ +diff '--color=auto' -ru a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-09 23:00:40.101308564 +0100 ++++ b/CMakeLists.txt 2024-03-09 22:59:36.067973296 +0100 +@@ -84,7 +84,7 @@ + find_package(Git) + endif() + +-set(INFOWARE_PCI_DATA_DIR infoware_generated CACHE PATH "Output directory for the PCI ids generator") ++set(INFOWARE_PCI_DATA_DIR "${CMAKE_CURRENT_BINARY_DIR}/infoware_generated" CACHE PATH "Output directory for the PCI ids generator") + set(INFOWARE_PCI_DATA_HPP pci_data.hpp) + set(INFOWARE_PCI_DATA_GEN "${INFOWARE_PCI_DATA_DIR}/${INFOWARE_PCI_DATA_HPP}") + set(infoware_pci_ids_error "\ +@@ -132,13 +132,13 @@ + else() + include(ExternalProject) + ExternalProject_Add(infoware_generate_pcis +- SOURCE_DIR ${CMAKE_SOURCE_DIR} +- PREFIX ${CMAKE_BINARY_DIR}/pci_generator +- BINARY_DIR ${CMAKE_BINARY_DIR}/pci_generator ++ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ++ PREFIX ${CMAKE_CURRENT_BINARY_DIR}/pci_generator ++ BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/pci_generator + BUILD_COMMAND ${CMAKE_COMMAND} --build --target infoware_generate_pcis + INSTALL_COMMAND "" + BUILD_ALWAYS ON +- CMAKE_ARGS -DINFOWARE_PCI_DATA_DIR:PATH=${CMAKE_BINARY_DIR}/${INFOWARE_PCI_DATA_DIR}) ++ CMAKE_ARGS -DINFOWARE_PCI_DATA_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}/${INFOWARE_PCI_DATA_DIR}) + endif() + add_dependencies(infoware infoware_generate_pcis) + diff --git a/third-party/infoware/CMakeLists.txt b/third-party/infoware/CMakeLists.txt new file mode 100644 index 0000000..81c7b4b --- /dev/null +++ b/third-party/infoware/CMakeLists.txt @@ -0,0 +1,6 @@ +FetchContent_Declare( + infoware + URL https://github.com/ThePhD/infoware/archive/e469b86.tar.gz + URL_HASH SHA1=e844ae80c5ca3f6b944571130ac3795c96a4e9ab + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.current.patch" -P ${PATCH_SCRIPT} + DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/third-party/infoware/LICENSE b/third-party/infoware/LICENSE new file mode 100644 index 0000000..670154e --- /dev/null +++ b/third-party/infoware/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/third-party/libpng/1.zlib.patch b/third-party/libpng/1.zlib.patch new file mode 100644 index 0000000..7a225e9 --- /dev/null +++ b/third-party/libpng/1.zlib.patch @@ -0,0 +1,41 @@ +diff '--color=auto' -aru a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-03 01:47:51.488773684 +0100 ++++ b/CMakeLists.txt 2024-03-03 01:49:14.398777099 +0100 +@@ -37,10 +37,6 @@ + set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) + set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) + +-# needed packages +-find_package(ZLIB REQUIRED) +-include_directories(${ZLIB_INCLUDE_DIR}) +- + if(NOT WIN32) + find_library(M_LIBRARY + NAMES m +@@ -182,7 +178,7 @@ + endif() + + # NOW BUILD OUR TARGET +-include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR}) ++include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + + if(PNG_SHARED) + add_library(${PNG_LIB_NAME} SHARED ${libpng_sources}) +@@ -191,7 +187,7 @@ + set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib") + set_target_properties(${PNG_LIB_NAME} PROPERTIES IMPORT_PREFIX "lib") + endif() +- target_link_libraries(${PNG_LIB_NAME} ${ZLIB_LIBRARY} ${M_LIBRARY}) ++ target_link_libraries(${PNG_LIB_NAME} Zlib::zlib ${M_LIBRARY}) + endif() + + if(PNG_STATIC) +@@ -202,7 +198,7 @@ + # msvc does not append 'lib' - do it here to have consistent name + set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib") + endif() +- target_link_libraries(${PNG_LIB_NAME_STATIC} ${ZLIB_LIBRARY} ${M_LIBRARY}) ++ target_link_libraries(${PNG_LIB_NAME_STATIC} Zlib::zlibstatic ${M_LIBRARY}) + endif() + + diff --git a/third-party/libpng/2.export.patch b/third-party/libpng/2.export.patch new file mode 100644 index 0000000..089ff85 --- /dev/null +++ b/third-party/libpng/2.export.patch @@ -0,0 +1,16 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-03 02:11:53.952166254 +0100 ++++ b/CMakeLists.txt 2024-03-03 02:11:16.832164723 +0100 +@@ -380,12 +380,6 @@ + DESTINATION bin) + endif() + +-# On versions of CMake that support it, create an export file CMake +-# users can include() to import our targets +-if(PNG_EXPORT_RULE AND NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL ) +- install(EXPORT libpng DESTINATION lib/libpng FILE lib${PNG_LIB_NAME}.cmake) +-endif() +- + # what's with libpng-$VER%.txt and all the extra files? + + diff --git a/third-party/libpng/3.includes.patch b/third-party/libpng/3.includes.patch new file mode 100644 index 0000000..c48e163 --- /dev/null +++ b/third-party/libpng/3.includes.patch @@ -0,0 +1,37 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-03 02:11:16.832164723 +0100 ++++ b/CMakeLists.txt 2024-03-03 02:19:25.775518136 +0100 +@@ -106,7 +106,6 @@ + # Use the prebuilt pnglibconf.h file from the scripts folder + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt + ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h) +-include_directories(${CMAKE_CURRENT_BINARY_DIR}) + + # OUR SOURCES + set(libpng_public_hdrs +@@ -177,9 +176,6 @@ + add_definitions(-DPNG_NO_FLOATING_POINT_SUPPORTED) + endif() + +-# NOW BUILD OUR TARGET +-include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +- + if(PNG_SHARED) + add_library(${PNG_LIB_NAME} SHARED ${libpng_sources}) + if(MSVC) +@@ -187,6 +183,7 @@ + set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib") + set_target_properties(${PNG_LIB_NAME} PROPERTIES IMPORT_PREFIX "lib") + endif() ++ target_include_directories(${PNG_LIB_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${PNG_LIB_NAME} Zlib::zlib ${M_LIBRARY}) + endif() + +@@ -198,6 +195,7 @@ + # msvc does not append 'lib' - do it here to have consistent name + set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib") + endif() ++ target_include_directories(${PNG_LIB_NAME_STATIC} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${PNG_LIB_NAME_STATIC} Zlib::zlibstatic ${M_LIBRARY}) + endif() + diff --git a/third-party/libpng/4.aliases.patch b/third-party/libpng/4.aliases.patch new file mode 100644 index 0000000..14d81d4 --- /dev/null +++ b/third-party/libpng/4.aliases.patch @@ -0,0 +1,19 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-03 12:45:31.540235890 +0100 ++++ b/CMakeLists.txt 2024-03-03 12:46:11.986903772 +0100 +@@ -185,6 +185,7 @@ + endif() + target_include_directories(${PNG_LIB_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${PNG_LIB_NAME} Zlib::zlib ${M_LIBRARY}) ++ add_library(Png::png ALIAS ${PNG_LIB_NAME}) + endif() + + if(PNG_STATIC) +@@ -197,6 +198,7 @@ + endif() + target_include_directories(${PNG_LIB_NAME_STATIC} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${PNG_LIB_NAME_STATIC} Zlib::zlibstatic ${M_LIBRARY}) ++ add_library(Png::pngstatic ALIAS ${PNG_LIB_NAME_STATIC}) + endif() + + diff --git a/third-party/libpng/CMakeLists.txt b/third-party/libpng/CMakeLists.txt new file mode 100644 index 0000000..c8aafb6 --- /dev/null +++ b/third-party/libpng/CMakeLists.txt @@ -0,0 +1,11 @@ +FetchContent_Declare( + libpng + URL + https://download.sourceforge.net/libpng/libpng-1.5.1.tar.gz + https://ftp.ignore.pl/starshatter/resources/mirror/libpng-1.5.1.tar.gz + URL_HASH SHA1=29afc7422d4d8af1066f8783ae148e298520d5ba + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.zlib.patch" -P ${PATCH_SCRIPT} + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/2.export.patch" -P ${PATCH_SCRIPT} + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/3.includes.patch" -P ${PATCH_SCRIPT} + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/4.aliases.patch" -P ${PATCH_SCRIPT} + DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/third-party/libpng/LICENSE b/third-party/libpng/LICENSE new file mode 100644 index 0000000..b28f15c --- /dev/null +++ b/third-party/libpng/LICENSE @@ -0,0 +1,111 @@ + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.1, February 3, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +February 3, 2011 diff --git a/third-party/ogg/1.cmake.patch b/third-party/ogg/1.cmake.patch new file mode 100644 index 0000000..1534d17 --- /dev/null +++ b/third-party/ogg/1.cmake.patch @@ -0,0 +1,111 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 ++++ b/CMakeLists.txt 2024-03-03 12:39:28.260224931 +0100 +@@ -0,0 +1,107 @@ ++cmake_minimum_required(VERSION 2.8.7) ++project(libogg) ++ ++# Required modules ++include(GNUInstallDirs) ++include(CheckIncludeFiles) ++ ++# Build options ++option(BUILD_SHARED_LIBS "Build shared library" OFF) ++if(APPLE) ++ option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF) ++endif() ++ ++# Extract project version from configure.ac ++file(READ configure.ac CONFIGURE_AC_CONTENTS) ++string(REGEX MATCH "AC_INIT\\(\\[libogg\\],\\[([0-9]*).([0-9]*).([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) ++set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) ++set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) ++set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3}) ++set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) ++ ++# Helper function to get version-info ++function(get_version_info result current_var_name age_var_name revision_var_name) ++ string(REGEX MATCH "${current_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) ++ set(VERSION_INFO_CURRENT ${CMAKE_MATCH_1}) ++ ++ string(REGEX MATCH "${age_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) ++ set(VERSION_INFO_AGE ${CMAKE_MATCH_1}) ++ ++ string(REGEX MATCH "${revision_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) ++ set(VERSION_INFO_REVISION ${CMAKE_MATCH_1}) ++ ++ math(EXPR VERSION_INFO_CURRENT_MINUS_AGE "${VERSION_INFO_CURRENT} - ${VERSION_INFO_AGE}") ++ ++ set(${result} "${VERSION_INFO_CURRENT_MINUS_AGE}.${VERSION_INFO_AGE}.${VERSION_INFO_REVISION}" PARENT_SCOPE) ++endfunction() ++ ++# Helper function to configure pkg-config files ++function(configure_pkg_config_file pkg_config_file_in) ++ set(prefix ${CMAKE_INSTALL_PREFIX}) ++ set(exec_prefix ${CMAKE_INSTALL_FULL_BINDIR}) ++ set(libdir ${CMAKE_INSTALL_FULL_LIBDIR}) ++ set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR}) ++ set(VERSION ${PROJECT_VERSION}) ++ string(REPLACE ".in" "" pkg_config_file ${pkg_config_file_in}) ++ configure_file(${pkg_config_file_in} ${CMAKE_CURRENT_BINARY_DIR}/${pkg_config_file} @ONLY) ++endfunction() ++ ++message(STATUS "Configuring ${PROJECT_NAME} ${PROJECT_VERSION}") ++ ++# Configure config_type.h ++check_include_files(inttypes.h INCLUDE_INTTYPES_H) ++check_include_files(stdint.h INCLUDE_STDINT_H) ++check_include_files(sys/types.h INCLUDE_SYS_TYPES_H) ++ ++set(SIZE16 int16_t) ++set(USIZE16 uint16_t) ++set(SIZE32 int32_t) ++set(USIZE32 uint32_t) ++set(SIZE64 int64_t) ++ ++configure_file(include/ogg/config_types.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/ogg/config_types.h @ONLY) ++ ++set(OGG_HEADERS ++ ${CMAKE_CURRENT_BINARY_DIR}/include/ogg/config_types.h ++ include/ogg/ogg.h ++ include/ogg/os_types.h ++) ++ ++set(OGG_SOURCES ++ src/bitwise.c ++ src/framing.c ++) ++ ++if(MSVC) ++ list(APPEND OGG_SOURCES win32/ogg.def) ++endif() ++ ++if(BUILD_FRAMEWORK) ++ set(BUILD_SHARED_LIBS TRUE) ++endif() ++ ++include_directories(include ${CMAKE_CURRENT_BINARY_DIR}/include) ++add_library(ogg ${OGG_HEADERS} ${OGG_SOURCES}) ++target_include_directories(ogg PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) ++add_library(Ogg::ogg ALIAS ogg) ++ ++get_version_info(OGG_VERSION_INFO "LIB_CURRENT" "LIB_AGE" "LIB_REVISION") ++set_target_properties( ++ ogg PROPERTIES ++ SOVERSION ${OGG_VERSION_INFO} ++ PUBLIC_HEADER "${OGG_HEADERS}" ++) ++ ++if(BUILD_FRAMEWORK) ++ set_target_properties(ogg PROPERTIES ++ FRAMEWORK TRUE ++ FRAMEWORK_VERSION ${PROJECT_VERSION} ++ MACOSX_FRAMEWORK_IDENTIFIER org.xiph.ogg ++ MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PROJECT_VERSION} ++ MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION} ++ XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" ++ OUTPUT_NAME Ogg ++ ) ++endif() ++ ++configure_pkg_config_file(ogg.pc.in) diff --git a/third-party/ogg/CMakeLists.txt b/third-party/ogg/CMakeLists.txt new file mode 100644 index 0000000..a1d2372 --- /dev/null +++ b/third-party/ogg/CMakeLists.txt @@ -0,0 +1,8 @@ +FetchContent_Declare( + ogg + URL + https://downloads.xiph.org/releases/ogg/libogg-1.3.3.tar.gz + https://ftp.ignore.pl/starshatter/resources/mirror/libogg-1.3.3.tar.gz + URL_HASH SHA1=28ba40fd2e2d41988f658a0016fa7b534e509bc0 + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.cmake.patch" -P ${PATCH_SCRIPT} + DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/third-party/ogg/COPYING b/third-party/ogg/COPYING new file mode 100644 index 0000000..6111c6c --- /dev/null +++ b/third-party/ogg/COPYING @@ -0,0 +1,28 @@ +Copyright (c) 2002, Xiph.org Foundation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third-party/sha1/CMakeLists.txt b/third-party/sha1/CMakeLists.txt new file mode 100644 index 0000000..cc6fab2 --- /dev/null +++ b/third-party/sha1/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.20) +project(Sha1) +add_library(${PROJECT_NAME} STATIC Sha1.cpp) +target_include_directories( + ${PROJECT_NAME} + PUBLIC include) diff --git a/third-party/sha1/Sha1.cpp b/third-party/sha1/Sha1.cpp new file mode 100644 index 0000000..7e3de70 --- /dev/null +++ b/third-party/sha1/Sha1.cpp @@ -0,0 +1,589 @@ +/* +* Sha1.cpp +* +* Copyright (C) 1998 +* Paul E. Jones +* All Rights Reserved. +* +***************************************************************************** +* $Id: sha1.cpp,v 1.6 2001/03/20 06:54:54 paulej Exp $ +***************************************************************************** +* +* Description: +* This class implements the Secure Hashing Standard as defined +* in FIPS PUB 180-1 published April 17, 1995. +* +* The Secure Hashing Standard, which uses the Secure Hashing +* Algorithm (SHA), produces a 160-bit message digest for a +* given data stream. In theory, it is highly improbable that +* two messages will produce the same message digest. Therefore, +* this algorithm can serve as a means of providing a "fingerprint" +* for a message. +* +* Portability Issues: +* SHA-1 is defined in terms of 32-bit "words". This code was +* written with the expectation that the processor has at least +* a 32-bit machine word size. If the machine word size is larger, +* the code should still function properly. One caveat to that +* is that the input functions taking characters and character arrays +* assume that only 8 bits of information are stored in each character. +* +* Caveats: +* SHA-1 is designed to work with messages less than 2^64 bits long. +* Although SHA-1 allows a message digest to be generated for +* messages of any number of bits less than 2^64, this implementation +* only works with messages with a length that is a multiple of 8 +* bits. +* +*/ + + +#include "Sha1.h" + +/* +* SHA1 +* +* Description: +* This is the constructor for the sha1 class. +* +* Parameters: +* None. +* +* Returns: +* Nothing. +* +* Comments: +* +*/ +SHA1::SHA1() +{ + Reset(); +} + +/* +* ~SHA1 +* +* Description: +* This is the destructor for the sha1 class +* +* Parameters: +* None. +* +* Returns: +* Nothing. +* +* Comments: +* +*/ +SHA1::~SHA1() +{ + // The destructor does nothing +} + +/* +* Reset +* +* Description: +* This function will initialize the sha1 class member variables +* in preparation for computing a new message digest. +* +* Parameters: +* None. +* +* Returns: +* Nothing. +* +* Comments: +* +*/ +void SHA1::Reset() +{ + Length_Low = 0; + Length_High = 0; + Message_Block_Index = 0; + + H[0] = 0x67452301; + H[1] = 0xEFCDAB89; + H[2] = 0x98BADCFE; + H[3] = 0x10325476; + H[4] = 0xC3D2E1F0; + + Computed = false; + Corrupted = false; +} + +/* +* Result +* +* Description: +* This function will return the 160-bit message digest into the +* array provided. +* +* Parameters: +* message_digest_array: [out] +* This is an array of five unsigned integers which will be filled +* with the message digest that has been computed. +* +* Returns: +* True if successful, false if it failed. +* +* Comments: +* +*/ +bool SHA1::Result(unsigned *message_digest_array) +{ + int i; // Counter + + if (Corrupted) + { + return false; + } + + if (!Computed) + { + PadMessage(); + Computed = true; + } + + for(i = 0; i < 5; i++) + { + message_digest_array[i] = H[i]; + } + + return true; +} + +/* +* Input +* +* Description: +* This function accepts an array of octets as the next portion of +* the message. +* +* Parameters: +* message_array: [in] +* An array of characters representing the next portion of the +* message. +* +* Returns: +* Nothing. +* +* Comments: +* +*/ +void SHA1::Input( const unsigned char *message_array, +unsigned length) +{ + if (!length) + { + return; + } + + if (Computed || Corrupted) + { + Corrupted = true; + return; + } + + while(length-- && !Corrupted) + { + Message_Block[Message_Block_Index++] = (*message_array & 0xFF); + + Length_Low += 8; + Length_Low &= 0xFFFFFFFF; // Force it to 32 bits + if (Length_Low == 0) + { + Length_High++; + Length_High &= 0xFFFFFFFF; // Force it to 32 bits + if (Length_High == 0) + { + Corrupted = true; // Message is too long + } + } + + if (Message_Block_Index == 64) + { + ProcessMessageBlock(); + } + + message_array++; + } +} + +/* +* Input +* +* Description: +* This function accepts an array of octets as the next portion of +* the message. +* +* Parameters: +* message_array: [in] +* An array of characters representing the next portion of the +* message. +* length: [in] +* The length of the message_array +* +* Returns: +* Nothing. +* +* Comments: +* +*/ +void SHA1::Input( const char *message_array, +unsigned length) +{ + Input((unsigned char *) message_array, length); +} + +/* +* Input +* +* Description: +* This function accepts a single octets as the next message element. +* +* Parameters: +* message_element: [in] +* The next octet in the message. +* +* Returns: +* Nothing. +* +* Comments: +* +*/ +void SHA1::Input(unsigned char message_element) +{ + Input(&message_element, 1); +} + +/* +* Input +* +* Description: +* This function accepts a single octet as the next message element. +* +* Parameters: +* message_element: [in] +* The next octet in the message. +* +* Returns: +* Nothing. +* +* Comments: +* +*/ +void SHA1::Input(char message_element) +{ + Input((unsigned char *) &message_element, 1); +} + +/* +* operator<< +* +* Description: +* This operator makes it convenient to provide character strings to +* the SHA1 object for processing. +* +* Parameters: +* message_array: [in] +* The character array to take as input. +* +* Returns: +* A reference to the SHA1 object. +* +* Comments: +* Each character is assumed to hold 8 bits of information. +* +*/ +SHA1& SHA1::operator<<(const char *message_array) +{ + const char *p = message_array; + + while(*p) + { + Input(*p); + p++; + } + + return *this; +} + +/* +* operator<< +* +* Description: +* This operator makes it convenient to provide character strings to +* the SHA1 object for processing. +* +* Parameters: +* message_array: [in] +* The character array to take as input. +* +* Returns: +* A reference to the SHA1 object. +* +* Comments: +* Each character is assumed to hold 8 bits of information. +* +*/ +SHA1& SHA1::operator<<(const unsigned char *message_array) +{ + const unsigned char *p = message_array; + + while(*p) + { + Input(*p); + p++; + } + + return *this; +} + +/* +* operator<< +* +* Description: +* This function provides the next octet in the message. +* +* Parameters: +* message_element: [in] +* The next octet in the message +* +* Returns: +* A reference to the SHA1 object. +* +* Comments: +* The character is assumed to hold 8 bits of information. +* +*/ +SHA1& SHA1::operator<<(const char message_element) +{ + Input((unsigned char *) &message_element, 1); + + return *this; +} + +/* +* operator<< +* +* Description: +* This function provides the next octet in the message. +* +* Parameters: +* message_element: [in] +* The next octet in the message +* +* Returns: +* A reference to the SHA1 object. +* +* Comments: +* The character is assumed to hold 8 bits of information. +* +*/ +SHA1& SHA1::operator<<(const unsigned char message_element) +{ + Input(&message_element, 1); + + return *this; +} + +/* +* ProcessMessageBlock +* +* Description: +* This function will process the next 512 bits of the message +* stored in the Message_Block array. +* +* Parameters: +* None. +* +* Returns: +* Nothing. +* +* Comments: +* Many of the variable names in this function, especially the single +* character names, were used because those were the names used +* in the publication. +* +*/ +void SHA1::ProcessMessageBlock() +{ + const unsigned K[] = { // Constants defined for SHA-1 + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; // Loop counter + unsigned temp; // Temporary word value + unsigned W[80]; // Word sequence + unsigned A, B, C, D, E; // Word buffers + + /* + * Initialize the first 16 words in the array W + */ + for(t = 0; t < 16; t++) + { + W[t] = Message_Block[t * 4] << 24; + W[t] |= Message_Block[t * 4 + 1] << 16; + W[t] |= Message_Block[t * 4 + 2] << 8; + W[t] |= Message_Block[t * 4 + 3]; + } + + for(t = 16; t < 80; t++) + { + W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = H[0]; + B = H[1]; + C = H[2]; + D = H[3]; + E = H[4]; + + for(t = 0; t < 20; t++) + { + temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 20; t < 40; t++) + { + temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 40; t < 60; t++) + { + temp = CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 60; t < 80; t++) + { + temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = CircularShift(30,B); + B = A; + A = temp; + } + + H[0] = (H[0] + A) & 0xFFFFFFFF; + H[1] = (H[1] + B) & 0xFFFFFFFF; + H[2] = (H[2] + C) & 0xFFFFFFFF; + H[3] = (H[3] + D) & 0xFFFFFFFF; + H[4] = (H[4] + E) & 0xFFFFFFFF; + + Message_Block_Index = 0; +} + +/* +* PadMessage +* +* Description: +* According to the standard, the message must be padded to an even +* 512 bits. The first padding bit must be a '1'. The last 64 bits +* represent the length of the original message. All bits in between +* should be 0. This function will pad the message according to those +* rules by filling the message_block array accordingly. It will also +* call ProcessMessageBlock() appropriately. When it returns, it +* can be assumed that the message digest has been computed. +* +* Parameters: +* None. +* +* Returns: +* Nothing. +* +* Comments: +* +*/ +void SHA1::PadMessage() +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second block. + */ + if (Message_Block_Index > 55) + { + Message_Block[Message_Block_Index++] = 0x80; + while(Message_Block_Index < 64) + { + Message_Block[Message_Block_Index++] = 0; + } + + ProcessMessageBlock(); + + while(Message_Block_Index < 56) + { + Message_Block[Message_Block_Index++] = 0; + } + } + else + { + Message_Block[Message_Block_Index++] = 0x80; + while(Message_Block_Index < 56) + { + Message_Block[Message_Block_Index++] = 0; + } + + } + + /* + * Store the message length as the last 8 octets + */ + Message_Block[56] = (Length_High >> 24) & 0xFF; + Message_Block[57] = (Length_High >> 16) & 0xFF; + Message_Block[58] = (Length_High >> 8) & 0xFF; + Message_Block[59] = (Length_High) & 0xFF; + Message_Block[60] = (Length_Low >> 24) & 0xFF; + Message_Block[61] = (Length_Low >> 16) & 0xFF; + Message_Block[62] = (Length_Low >> 8) & 0xFF; + Message_Block[63] = (Length_Low) & 0xFF; + + ProcessMessageBlock(); +} + + +/* +* CircularShift +* +* Description: +* This member function will perform a circular shifting operation. +* +* Parameters: +* bits: [in] +* The number of bits to shift (1-31) +* word: [in] +* The value to shift (assumes a 32-bit integer) +* +* Returns: +* The shifted value. +* +* Comments: +* +*/ +unsigned SHA1::CircularShift(int bits, unsigned word) +{ + return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits)); +} diff --git a/third-party/sha1/include/Sha1.h b/third-party/sha1/include/Sha1.h new file mode 100644 index 0000000..ec64462 --- /dev/null +++ b/third-party/sha1/include/Sha1.h @@ -0,0 +1,89 @@ +/* +* Sha1.h +* +* Copyright (C) 1998 +* Paul E. Jones +* All Rights Reserved. +* +***************************************************************************** +* $Id: sha1.h,v 1.4 2001/03/20 06:25:06 paulej Exp $ +***************************************************************************** +* +* Description: +* This class implements the Secure Hashing Standard as defined +* in FIPS PUB 180-1 published April 17, 1995. +* +* Many of the variable names in this class, especially the single +* character names, were used because those were the names used +* in the publication. +* +* Please read the file sha1.cpp for more information. +* +*/ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +class SHA1 +{ + +public: + + SHA1(); + virtual ~SHA1(); + + /* + * Re-initialize the class + */ + void Reset(); + + /* + * Returns the message digest + */ + bool Result(unsigned *message_digest_array); + + /* + * Provide input to SHA1 + */ + void Input( const unsigned char *message_array, + unsigned length); + void Input( const char *message_array, + unsigned length); + void Input(unsigned char message_element); + void Input(char message_element); + SHA1& operator<<(const char *message_array); + SHA1& operator<<(const unsigned char *message_array); + SHA1& operator<<(const char message_element); + SHA1& operator<<(const unsigned char message_element); + +private: + + /* + * Process the next 512 bits of the message + */ + void ProcessMessageBlock(); + + /* + * Pads the current message block to 512 bits + */ + void PadMessage(); + + /* + * Performs a circular left shift operation + */ + inline unsigned CircularShift(int bits, unsigned word); + + unsigned H[5]; // Message digest buffers + + unsigned Length_Low; // Message length in bits + unsigned Length_High; // Message length in bits + + unsigned char Message_Block[64]; // 512-bit message blocks + int Message_Block_Index; // Index into message block array + + bool Computed; // Is the digest computed? + bool Corrupted; // Is the message digest corruped? + +}; + +#endif diff --git a/third-party/vorbis/1.cmake.patch b/third-party/vorbis/1.cmake.patch new file mode 100644 index 0000000..3737f42 --- /dev/null +++ b/third-party/vorbis/1.cmake.patch @@ -0,0 +1,176 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 ++++ b/CMakeLists.txt 2024-03-03 12:44:24.470233876 +0100 +@@ -0,0 +1,59 @@ ++cmake_minimum_required(VERSION 2.8.7) ++project(vorbis) ++ ++# Required modules ++include(GNUInstallDirs) ++include(CheckIncludeFiles) ++ ++# Build options ++option(BUILD_SHARED_LIBS "Build shared library" OFF) ++if(APPLE) ++ option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF) ++endif() ++ ++if(BUILD_FRAMEWORK) ++ set(BUILD_SHARED_LIBS TRUE) ++endif() ++ ++# Extract project version from configure.ac ++file(READ configure.ac CONFIGURE_AC_CONTENTS) ++string(REGEX MATCH "AC_INIT\\(\\[libvorbis\\],\\[([0-9]*).([0-9]*).([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) ++set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) ++set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) ++set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3}) ++set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) ++ ++# Helper function to get version-info ++function(get_version_info result current_var_name age_var_name revision_var_name) ++ string(REGEX MATCH "${current_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) ++ set(VERSION_INFO_CURRENT ${CMAKE_MATCH_1}) ++ ++ string(REGEX MATCH "${age_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) ++ set(VERSION_INFO_AGE ${CMAKE_MATCH_1}) ++ ++ string(REGEX MATCH "${revision_var_name}=([0-9]*)" DUMMY ${CONFIGURE_AC_CONTENTS}) ++ set(VERSION_INFO_REVISION ${CMAKE_MATCH_1}) ++ ++ math(EXPR VERSION_INFO_CURRENT_MINUS_AGE "${VERSION_INFO_CURRENT} - ${VERSION_INFO_AGE}") ++ ++ set(${result} "${VERSION_INFO_CURRENT_MINUS_AGE}.${VERSION_INFO_AGE}.${VERSION_INFO_REVISION}" PARENT_SCOPE) ++endfunction() ++ ++# Helper function to configure pkg-config files ++function(configure_pkg_config_file pkg_config_file_in) ++ set(prefix ${CMAKE_INSTALL_PREFIX}) ++ set(exec_prefix ${CMAKE_INSTALL_FULL_BINDIR}) ++ set(libdir ${CMAKE_INSTALL_FULL_LIBDIR}) ++ set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR}) ++ set(VERSION ${PROJECT_VERSION}) ++ string(REPLACE ".in" "" pkg_config_file ${pkg_config_file_in}) ++ configure_file(${pkg_config_file_in} ${pkg_config_file} @ONLY) ++endfunction() ++ ++message(STATUS "Configuring ${PROJECT_NAME} ${PROJECT_VERSION}") ++ ++add_subdirectory(lib) ++ ++configure_pkg_config_file(vorbis.pc.in) ++configure_pkg_config_file(vorbisenc.pc.in) ++configure_pkg_config_file(vorbisfile.pc.in) +diff '--color=auto' -arNu a/lib/CMakeLists.txt b/lib/CMakeLists.txt +--- a/lib/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 ++++ b/lib/CMakeLists.txt 2024-03-03 12:44:45.650234517 +0100 +@@ -0,0 +1,109 @@ ++set(VORBIS_PUBLIC_HEADERS ++ ../include/vorbis/codec.h ++ ../include/vorbis/vorbisenc.h ++ ../include/vorbis/vorbisfile.h ++) ++ ++set(VORBIS_HEADERS ++ envelope.h ++ lpc.h ++ lsp.h ++ codebook.h ++ misc.h ++ psy.h ++ masking.h ++ os.h ++ mdct.h ++ smallft.h ++ highlevel.h ++ registry.h ++ scales.h ++ window.h ++ lookup.h ++ lookup_data.h ++ codec_internal.h ++ backends.h ++ bitrate.h ++) ++ ++set(VORBIS_SOURCES ++ mdct.c ++ smallft.c ++ block.c ++ envelope.c ++ window.c ++ lsp.c ++ lpc.c ++ analysis.c ++ synthesis.c ++ psy.c ++ info.c ++ floor1.c ++ floor0.c ++ res0.c ++ mapping0.c ++ registry.c ++ codebook.c ++ sharedbook.c ++ lookup.c ++ bitrate.c ++) ++ ++set(VORBISFILE_SOURCES ++ vorbisfile.c ++) ++ ++set(VORBISENC_SOURCES ++ vorbisenc.c ++) ++ ++if(WIN32) ++ list(APPEND VORBIS_SOURCES vorbisenc.c) ++endif() ++ ++if(MSVC) ++ list(APPEND VORBIS_SOURCES ../win32/vorbis.def) ++ list(APPEND VORBISENC_SOURCES ../win32/vorbisenc.def) ++ list(APPEND VORBISFILE_SOURCES ../win32/vorbisfile.def) ++endif() ++ ++include_directories(../include) ++include_directories(.) ++ ++if (NOT BUILD_FRAMEWORK) ++ add_library(vorbis ${VORBIS_HEADERS} ${VORBIS_SOURCES}) ++ add_library(vorbisenc ${VORBISENC_SOURCES}) ++ add_library(vorbisfile ${VORBISFILE_SOURCES}) ++ ++ get_version_info(VORBIS_VERSION_INFO "V_LIB_CURRENT" "V_LIB_AGE" "V_LIB_REVISION") ++ set_target_properties(vorbis PROPERTIES SOVERSION ${VORBIS_VERSION_INFO}) ++ get_version_info(VORBISENC_VERSION_INFO "VE_LIB_CURRENT" "VE_LIB_AGE" "VE_LIB_REVISION") ++ set_target_properties(vorbisenc PROPERTIES SOVERSION ${VORBISENC_VERSION_INFO}) ++ get_version_info(VORBISFILE_VERSION_INFO "VF_LIB_CURRENT" "VF_LIB_AGE" "VF_LIB_REVISION") ++ set_target_properties(vorbisfile PROPERTIES SOVERSION ${VORBISFILE_VERSION_INFO}) ++ ++ target_include_directories(vorbis PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) ++ target_include_directories(vorbisenc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) ++ target_include_directories(vorbisfile PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) ++ ++ target_link_libraries(vorbis Ogg::ogg) ++ target_link_libraries(vorbisenc Ogg::ogg vorbis) ++ target_link_libraries(vorbisfile Ogg::ogg vorbis) ++ ++ add_library(Vorbis::vorbis ALIAS vorbis) ++ add_library(Vorbis::vorbisenc ALIAS vorbisenc) ++ add_library(Vorbis::vorbisfile ALIAS vorbisfile) ++else() ++ add_library(vorbis ${VORBIS_PUBLIC_HEADERS} ${VORBIS_HEADERS} ${VORBIS_SOURCES} ${VORBISFILE_SOURCES} ${VORBISENC_SOURCES}) ++ set_target_properties(vorbis PROPERTIES ++ FRAMEWORK TRUE ++ FRAMEWORK_VERSION ${PROJECT_VERSION} ++ MACOSX_FRAMEWORK_IDENTIFIER org.xiph.vorbis ++ MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PROJECT_VERSION} ++ MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION} ++ XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" ++ PUBLIC_HEADER "${VORBIS_PUBLIC_HEADERS}" ++ OUTPUT_NAME Vorbis ++ ) ++ target_link_libraries(vorbis ${OGG_LIBRARIES}) ++endif() diff --git a/third-party/vorbis/CMakeLists.txt b/third-party/vorbis/CMakeLists.txt new file mode 100644 index 0000000..643da7c --- /dev/null +++ b/third-party/vorbis/CMakeLists.txt @@ -0,0 +1,8 @@ +FetchContent_Declare( + vorbis + URL + https://downloads.xiph.org/releases/vorbis/libvorbis-1.3.6.tar.gz + https://ftp.ignore.pl/starshatter/resources/mirror/libvorbis-1.3.6.tar.gz + URL_HASH SHA1=91f140c220d1fe3376d637dc5f3d046263784b1f + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.cmake.patch" -P ${PATCH_SCRIPT} + DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/third-party/vorbis/COPYING b/third-party/vorbis/COPYING new file mode 100644 index 0000000..153b926 --- /dev/null +++ b/third-party/vorbis/COPYING @@ -0,0 +1,28 @@ +Copyright (c) 2002-2018 Xiph.org Foundation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third-party/zlib/1.zconf.patch b/third-party/zlib/1.zconf.patch new file mode 100644 index 0000000..eab40b7 --- /dev/null +++ b/third-party/zlib/1.zconf.patch @@ -0,0 +1,560 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-03 01:50:38.272113874 +0100 ++++ b/CMakeLists.txt 2024-03-03 01:54:30.605456738 +0100 +@@ -66,18 +66,6 @@ + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + endif() + +-if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) +- # If we're doing an out of source build and the user has a zconf.h +- # in their source tree... +- if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) +- message(STATUS "Renaming") +- message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") +- message(STATUS "to 'zconf.h.included' because this file is included with zlib") +- message(STATUS "but CMake generates it automatically in the build directory.") +- file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) +- endif() +-endif() +- + set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein + ${ZLIB_PC} @ONLY) +diff '--color=auto' -arNu a/zconf.h b/zconf.h +--- a/zconf.h 2024-03-03 01:49:53.568778704 +0100 ++++ b/zconf.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,534 +0,0 @@ +-/* zconf.h -- configuration of the zlib compression library +- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler +- * For conditions of distribution and use, see copyright notice in zlib.h +- */ +- +-/* @(#) $Id$ */ +- +-#ifndef ZCONF_H +-#define ZCONF_H +- +-/* +- * If you *really* need a unique prefix for all types and library functions, +- * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. +- * Even better than compiling with -DZ_PREFIX would be to use configure to set +- * this permanently in zconf.h using "./configure --zprefix". +- */ +-#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +-# define Z_PREFIX_SET +- +-/* all linked symbols and init macros */ +-# define _dist_code z__dist_code +-# define _length_code z__length_code +-# define _tr_align z__tr_align +-# define _tr_flush_bits z__tr_flush_bits +-# define _tr_flush_block z__tr_flush_block +-# define _tr_init z__tr_init +-# define _tr_stored_block z__tr_stored_block +-# define _tr_tally z__tr_tally +-# define adler32 z_adler32 +-# define adler32_combine z_adler32_combine +-# define adler32_combine64 z_adler32_combine64 +-# define adler32_z z_adler32_z +-# ifndef Z_SOLO +-# define compress z_compress +-# define compress2 z_compress2 +-# define compressBound z_compressBound +-# endif +-# define crc32 z_crc32 +-# define crc32_combine z_crc32_combine +-# define crc32_combine64 z_crc32_combine64 +-# define crc32_z z_crc32_z +-# define deflate z_deflate +-# define deflateBound z_deflateBound +-# define deflateCopy z_deflateCopy +-# define deflateEnd z_deflateEnd +-# define deflateGetDictionary z_deflateGetDictionary +-# define deflateInit z_deflateInit +-# define deflateInit2 z_deflateInit2 +-# define deflateInit2_ z_deflateInit2_ +-# define deflateInit_ z_deflateInit_ +-# define deflateParams z_deflateParams +-# define deflatePending z_deflatePending +-# define deflatePrime z_deflatePrime +-# define deflateReset z_deflateReset +-# define deflateResetKeep z_deflateResetKeep +-# define deflateSetDictionary z_deflateSetDictionary +-# define deflateSetHeader z_deflateSetHeader +-# define deflateTune z_deflateTune +-# define deflate_copyright z_deflate_copyright +-# define get_crc_table z_get_crc_table +-# ifndef Z_SOLO +-# define gz_error z_gz_error +-# define gz_intmax z_gz_intmax +-# define gz_strwinerror z_gz_strwinerror +-# define gzbuffer z_gzbuffer +-# define gzclearerr z_gzclearerr +-# define gzclose z_gzclose +-# define gzclose_r z_gzclose_r +-# define gzclose_w z_gzclose_w +-# define gzdirect z_gzdirect +-# define gzdopen z_gzdopen +-# define gzeof z_gzeof +-# define gzerror z_gzerror +-# define gzflush z_gzflush +-# define gzfread z_gzfread +-# define gzfwrite z_gzfwrite +-# define gzgetc z_gzgetc +-# define gzgetc_ z_gzgetc_ +-# define gzgets z_gzgets +-# define gzoffset z_gzoffset +-# define gzoffset64 z_gzoffset64 +-# define gzopen z_gzopen +-# define gzopen64 z_gzopen64 +-# ifdef _WIN32 +-# define gzopen_w z_gzopen_w +-# endif +-# define gzprintf z_gzprintf +-# define gzputc z_gzputc +-# define gzputs z_gzputs +-# define gzread z_gzread +-# define gzrewind z_gzrewind +-# define gzseek z_gzseek +-# define gzseek64 z_gzseek64 +-# define gzsetparams z_gzsetparams +-# define gztell z_gztell +-# define gztell64 z_gztell64 +-# define gzungetc z_gzungetc +-# define gzvprintf z_gzvprintf +-# define gzwrite z_gzwrite +-# endif +-# define inflate z_inflate +-# define inflateBack z_inflateBack +-# define inflateBackEnd z_inflateBackEnd +-# define inflateBackInit z_inflateBackInit +-# define inflateBackInit_ z_inflateBackInit_ +-# define inflateCodesUsed z_inflateCodesUsed +-# define inflateCopy z_inflateCopy +-# define inflateEnd z_inflateEnd +-# define inflateGetDictionary z_inflateGetDictionary +-# define inflateGetHeader z_inflateGetHeader +-# define inflateInit z_inflateInit +-# define inflateInit2 z_inflateInit2 +-# define inflateInit2_ z_inflateInit2_ +-# define inflateInit_ z_inflateInit_ +-# define inflateMark z_inflateMark +-# define inflatePrime z_inflatePrime +-# define inflateReset z_inflateReset +-# define inflateReset2 z_inflateReset2 +-# define inflateResetKeep z_inflateResetKeep +-# define inflateSetDictionary z_inflateSetDictionary +-# define inflateSync z_inflateSync +-# define inflateSyncPoint z_inflateSyncPoint +-# define inflateUndermine z_inflateUndermine +-# define inflateValidate z_inflateValidate +-# define inflate_copyright z_inflate_copyright +-# define inflate_fast z_inflate_fast +-# define inflate_table z_inflate_table +-# ifndef Z_SOLO +-# define uncompress z_uncompress +-# define uncompress2 z_uncompress2 +-# endif +-# define zError z_zError +-# ifndef Z_SOLO +-# define zcalloc z_zcalloc +-# define zcfree z_zcfree +-# endif +-# define zlibCompileFlags z_zlibCompileFlags +-# define zlibVersion z_zlibVersion +- +-/* all zlib typedefs in zlib.h and zconf.h */ +-# define Byte z_Byte +-# define Bytef z_Bytef +-# define alloc_func z_alloc_func +-# define charf z_charf +-# define free_func z_free_func +-# ifndef Z_SOLO +-# define gzFile z_gzFile +-# endif +-# define gz_header z_gz_header +-# define gz_headerp z_gz_headerp +-# define in_func z_in_func +-# define intf z_intf +-# define out_func z_out_func +-# define uInt z_uInt +-# define uIntf z_uIntf +-# define uLong z_uLong +-# define uLongf z_uLongf +-# define voidp z_voidp +-# define voidpc z_voidpc +-# define voidpf z_voidpf +- +-/* all zlib structs in zlib.h and zconf.h */ +-# define gz_header_s z_gz_header_s +-# define internal_state z_internal_state +- +-#endif +- +-#if defined(__MSDOS__) && !defined(MSDOS) +-# define MSDOS +-#endif +-#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +-# define OS2 +-#endif +-#if defined(_WINDOWS) && !defined(WINDOWS) +-# define WINDOWS +-#endif +-#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +-# ifndef WIN32 +-# define WIN32 +-# endif +-#endif +-#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +-# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +-# ifndef SYS16BIT +-# define SYS16BIT +-# endif +-# endif +-#endif +- +-/* +- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more +- * than 64k bytes at a time (needed on systems with 16-bit int). +- */ +-#ifdef SYS16BIT +-# define MAXSEG_64K +-#endif +-#ifdef MSDOS +-# define UNALIGNED_OK +-#endif +- +-#ifdef __STDC_VERSION__ +-# ifndef STDC +-# define STDC +-# endif +-# if __STDC_VERSION__ >= 199901L +-# ifndef STDC99 +-# define STDC99 +-# endif +-# endif +-#endif +-#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +-# define STDC +-#endif +-#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +-# define STDC +-#endif +-#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +-# define STDC +-#endif +-#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +-# define STDC +-#endif +- +-#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +-# define STDC +-#endif +- +-#ifndef STDC +-# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +-# define const /* note: need a more gentle solution here */ +-# endif +-#endif +- +-#if defined(ZLIB_CONST) && !defined(z_const) +-# define z_const const +-#else +-# define z_const +-#endif +- +-#ifdef Z_SOLO +- typedef unsigned long z_size_t; +-#else +-# define z_longlong long long +-# if defined(NO_SIZE_T) +- typedef unsigned NO_SIZE_T z_size_t; +-# elif defined(STDC) +-# include +- typedef size_t z_size_t; +-# else +- typedef unsigned long z_size_t; +-# endif +-# undef z_longlong +-#endif +- +-/* Maximum value for memLevel in deflateInit2 */ +-#ifndef MAX_MEM_LEVEL +-# ifdef MAXSEG_64K +-# define MAX_MEM_LEVEL 8 +-# else +-# define MAX_MEM_LEVEL 9 +-# endif +-#endif +- +-/* Maximum value for windowBits in deflateInit2 and inflateInit2. +- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files +- * created by gzip. (Files created by minigzip can still be extracted by +- * gzip.) +- */ +-#ifndef MAX_WBITS +-# define MAX_WBITS 15 /* 32K LZ77 window */ +-#endif +- +-/* The memory requirements for deflate are (in bytes): +- (1 << (windowBits+2)) + (1 << (memLevel+9)) +- that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) +- plus a few kilobytes for small objects. For example, if you want to reduce +- the default memory requirements from 256K to 128K, compile with +- make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" +- Of course this will generally degrade compression (there's no free lunch). +- +- The memory requirements for inflate are (in bytes) 1 << windowBits +- that is, 32K for windowBits=15 (default value) plus about 7 kilobytes +- for small objects. +-*/ +- +- /* Type declarations */ +- +-#ifndef OF /* function prototypes */ +-# ifdef STDC +-# define OF(args) args +-# else +-# define OF(args) () +-# endif +-#endif +- +-#ifndef Z_ARG /* function prototypes for stdarg */ +-# if defined(STDC) || defined(Z_HAVE_STDARG_H) +-# define Z_ARG(args) args +-# else +-# define Z_ARG(args) () +-# endif +-#endif +- +-/* The following definitions for FAR are needed only for MSDOS mixed +- * model programming (small or medium model with some far allocations). +- * This was tested only with MSC; for other MSDOS compilers you may have +- * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, +- * just define FAR to be empty. +- */ +-#ifdef SYS16BIT +-# if defined(M_I86SM) || defined(M_I86MM) +- /* MSC small or medium model */ +-# define SMALL_MEDIUM +-# ifdef _MSC_VER +-# define FAR _far +-# else +-# define FAR far +-# endif +-# endif +-# if (defined(__SMALL__) || defined(__MEDIUM__)) +- /* Turbo C small or medium model */ +-# define SMALL_MEDIUM +-# ifdef __BORLANDC__ +-# define FAR _far +-# else +-# define FAR far +-# endif +-# endif +-#endif +- +-#if defined(WINDOWS) || defined(WIN32) +- /* If building or using zlib as a DLL, define ZLIB_DLL. +- * This is not mandatory, but it offers a little performance increase. +- */ +-# ifdef ZLIB_DLL +-# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +-# ifdef ZLIB_INTERNAL +-# define ZEXTERN extern __declspec(dllexport) +-# else +-# define ZEXTERN extern __declspec(dllimport) +-# endif +-# endif +-# endif /* ZLIB_DLL */ +- /* If building or using zlib with the WINAPI/WINAPIV calling convention, +- * define ZLIB_WINAPI. +- * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. +- */ +-# ifdef ZLIB_WINAPI +-# ifdef FAR +-# undef FAR +-# endif +-# include +- /* No need for _export, use ZLIB.DEF instead. */ +- /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +-# define ZEXPORT WINAPI +-# ifdef WIN32 +-# define ZEXPORTVA WINAPIV +-# else +-# define ZEXPORTVA FAR CDECL +-# endif +-# endif +-#endif +- +-#if defined (__BEOS__) +-# ifdef ZLIB_DLL +-# ifdef ZLIB_INTERNAL +-# define ZEXPORT __declspec(dllexport) +-# define ZEXPORTVA __declspec(dllexport) +-# else +-# define ZEXPORT __declspec(dllimport) +-# define ZEXPORTVA __declspec(dllimport) +-# endif +-# endif +-#endif +- +-#ifndef ZEXTERN +-# define ZEXTERN extern +-#endif +-#ifndef ZEXPORT +-# define ZEXPORT +-#endif +-#ifndef ZEXPORTVA +-# define ZEXPORTVA +-#endif +- +-#ifndef FAR +-# define FAR +-#endif +- +-#if !defined(__MACTYPES__) +-typedef unsigned char Byte; /* 8 bits */ +-#endif +-typedef unsigned int uInt; /* 16 bits or more */ +-typedef unsigned long uLong; /* 32 bits or more */ +- +-#ifdef SMALL_MEDIUM +- /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +-# define Bytef Byte FAR +-#else +- typedef Byte FAR Bytef; +-#endif +-typedef char FAR charf; +-typedef int FAR intf; +-typedef uInt FAR uIntf; +-typedef uLong FAR uLongf; +- +-#ifdef STDC +- typedef void const *voidpc; +- typedef void FAR *voidpf; +- typedef void *voidp; +-#else +- typedef Byte const *voidpc; +- typedef Byte FAR *voidpf; +- typedef Byte *voidp; +-#endif +- +-#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +-# include +-# if (UINT_MAX == 0xffffffffUL) +-# define Z_U4 unsigned +-# elif (ULONG_MAX == 0xffffffffUL) +-# define Z_U4 unsigned long +-# elif (USHRT_MAX == 0xffffffffUL) +-# define Z_U4 unsigned short +-# endif +-#endif +- +-#ifdef Z_U4 +- typedef Z_U4 z_crc_t; +-#else +- typedef unsigned long z_crc_t; +-#endif +- +-#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +-# define Z_HAVE_UNISTD_H +-#endif +- +-#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +-# define Z_HAVE_STDARG_H +-#endif +- +-#ifdef STDC +-# ifndef Z_SOLO +-# include /* for off_t */ +-# endif +-#endif +- +-#if defined(STDC) || defined(Z_HAVE_STDARG_H) +-# ifndef Z_SOLO +-# include /* for va_list */ +-# endif +-#endif +- +-#ifdef _WIN32 +-# ifndef Z_SOLO +-# include /* for wchar_t */ +-# endif +-#endif +- +-/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and +- * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even +- * though the former does not conform to the LFS document), but considering +- * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as +- * equivalently requesting no 64-bit operations +- */ +-#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +-# undef _LARGEFILE64_SOURCE +-#endif +- +-#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +-# define Z_HAVE_UNISTD_H +-#endif +-#ifndef Z_SOLO +-# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +-# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +-# ifdef VMS +-# include /* for off_t */ +-# endif +-# ifndef z_off_t +-# define z_off_t off_t +-# endif +-# endif +-#endif +- +-#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +-# define Z_LFS64 +-#endif +- +-#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +-# define Z_LARGE64 +-#endif +- +-#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +-# define Z_WANT64 +-#endif +- +-#if !defined(SEEK_SET) && !defined(Z_SOLO) +-# define SEEK_SET 0 /* Seek from beginning of file. */ +-# define SEEK_CUR 1 /* Seek from current position. */ +-# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +-#endif +- +-#ifndef z_off_t +-# define z_off_t long +-#endif +- +-#if !defined(_WIN32) && defined(Z_LARGE64) +-# define z_off64_t off64_t +-#else +-# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +-# define z_off64_t __int64 +-# else +-# define z_off64_t z_off_t +-# endif +-#endif +- +-/* MVS linker does not support external names larger than 8 bytes */ +-#if defined(__MVS__) +- #pragma map(deflateInit_,"DEIN") +- #pragma map(deflateInit2_,"DEIN2") +- #pragma map(deflateEnd,"DEEND") +- #pragma map(deflateBound,"DEBND") +- #pragma map(inflateInit_,"ININ") +- #pragma map(inflateInit2_,"ININ2") +- #pragma map(inflateEnd,"INEND") +- #pragma map(inflateSync,"INSY") +- #pragma map(inflateSetDictionary,"INSEDI") +- #pragma map(compressBound,"CMBND") +- #pragma map(inflate_table,"INTABL") +- #pragma map(inflate_fast,"INFA") +- #pragma map(inflate_copyright,"INCOPY") +-#endif +- +-#endif /* ZCONF_H */ diff --git a/third-party/zlib/2.includes.patch b/third-party/zlib/2.includes.patch new file mode 100644 index 0000000..b39d18d --- /dev/null +++ b/third-party/zlib/2.includes.patch @@ -0,0 +1,28 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-03 01:56:30.848795009 +0100 ++++ b/CMakeLists.txt 2024-03-03 01:57:13.198796744 +0100 +@@ -63,7 +63,6 @@ + set(CMAKE_DEBUG_POSTFIX "d") + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) +- include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + endif() + + set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) +@@ -71,7 +70,6 @@ + ${ZLIB_PC} @ONLY) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) +-include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + + + #============================================================================ +@@ -173,6 +171,8 @@ + + add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) + add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) ++target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) ++target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) + set_target_properties(zlib PROPERTIES SOVERSION 1) + diff --git a/third-party/zlib/3.aliases.patch b/third-party/zlib/3.aliases.patch new file mode 100644 index 0000000..27cd075 --- /dev/null +++ b/third-party/zlib/3.aliases.patch @@ -0,0 +1,12 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-03 01:57:46.865464794 +0100 ++++ b/CMakeLists.txt 2024-03-03 01:58:11.902132479 +0100 +@@ -175,6 +175,8 @@ + target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) + set_target_properties(zlib PROPERTIES SOVERSION 1) ++add_library(Zlib::zlib ALIAS zlib) ++add_library(Zlib::zlibstatic ALIAS zlibstatic) + + if(NOT CYGWIN) + # This property causes shared libraries on Linux to have the full version diff --git a/third-party/zlib/4.examples.patch b/third-party/zlib/4.examples.patch new file mode 100644 index 0000000..3c21686 --- /dev/null +++ b/third-party/zlib/4.examples.patch @@ -0,0 +1,29 @@ +diff '--color=auto' -arNu a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2024-03-03 01:58:26.368799737 +0100 ++++ b/CMakeLists.txt 2024-03-03 01:58:33.615466706 +0100 +@@ -215,25 +215,3 @@ + if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") + endif() +- +-#============================================================================ +-# Example binaries +-#============================================================================ +- +-add_executable(example test/example.c) +-target_link_libraries(example zlib) +-add_test(example example) +- +-add_executable(minigzip test/minigzip.c) +-target_link_libraries(minigzip zlib) +- +-if(HAVE_OFF64_T) +- add_executable(example64 test/example.c) +- target_link_libraries(example64 zlib) +- set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") +- add_test(example64 example64) +- +- add_executable(minigzip64 test/minigzip.c) +- target_link_libraries(minigzip64 zlib) +- set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") +-endif() diff --git a/third-party/zlib/CMakeLists.txt b/third-party/zlib/CMakeLists.txt new file mode 100644 index 0000000..d7a5aec --- /dev/null +++ b/third-party/zlib/CMakeLists.txt @@ -0,0 +1,9 @@ +FetchContent_Declare( + zlib + URL https://www.zlib.net/fossils/zlib-1.2.11.tar.gz https://ftp.ignore.pl/starshatter/mirror/zlib-1.2.11.tar.gz + URL_HASH SHA1=e6d119755acdf9104d7ba236b1242696940ed6dd + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/1.zconf.patch" -P ${PATCH_SCRIPT} + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/2.includes.patch" -P ${PATCH_SCRIPT} + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/3.aliases.patch" -P ${PATCH_SCRIPT} + PATCH_COMMAND ${CMAKE_COMMAND} -D "PATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/4.examples.patch" -P ${PATCH_SCRIPT} + DOWNLOAD_EXTRACT_TIMESTAMP No) diff --git a/third-party/zlib/LICENSE b/third-party/zlib/LICENSE new file mode 100644 index 0000000..4bcfe18 --- /dev/null +++ b/third-party/zlib/LICENSE @@ -0,0 +1,27 @@ +zlib.h -- interface of the 'zlib' general purpose compression library +version 1.2.11, January 15th, 2017 + +Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +The data format used by the zlib library is described by RFCs (Request for +Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 -- cgit v1.1