merge upstream/master -> andrew/inertia

This commit is contained in:
Andrew Meadows 2014-04-11 12:18:30 -07:00
commit 5ac7be8945
44 changed files with 3042 additions and 262 deletions

View file

@ -0,0 +1,68 @@
//
// avatarCollision.js
// examples
//
// Created by Andrew Meadows on 2014-04-09
// Copyright 2014 High Fidelity, Inc.
//
// Play a sound on collisions with your avatar
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
var SOUND_TRIGGER_CLEAR = 1000; // milliseconds
var SOUND_TRIGGER_DELAY = 200; // milliseconds
var soundExpiry = 0;
var DateObj = new Date();
var audioOptions = new AudioInjectionOptions();
audioOptions.volume = 0.5;
audioOptions.position = { x: 0, y: 0, z: 0 };
var hitSounds = new Array();
hitSounds[0] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit1.raw");
hitSounds[1] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit2.raw");
hitSounds[2] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit3.raw");
hitSounds[3] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit4.raw");
hitSounds[4] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit5.raw");
hitSounds[5] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit6.raw");
hitSounds[6] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit7.raw");
hitSounds[7] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit8.raw");
hitSounds[8] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit9.raw");
hitSounds[9] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit10.raw");
hitSounds[10] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit11.raw");
hitSounds[11] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit12.raw");
hitSounds[12] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit13.raw");
hitSounds[13] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit14.raw");
hitSounds[14] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit15.raw");
hitSounds[15] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit16.raw");
hitSounds[16] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit17.raw");
hitSounds[17] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit18.raw");
hitSounds[18] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit19.raw");
hitSounds[19] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit20.raw");
hitSounds[20] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit21.raw");
hitSounds[21] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Collisions-hitsandslaps/Hit22.raw");
function playHitSound(mySessionID, theirSessionID, collision) {
var now = new Date();
var msec = now.getTime();
if (msec > soundExpiry) {
// this is a new contact --> play a new sound
var soundIndex = Math.floor((Math.random() * hitSounds.length) % hitSounds.length);
audioOptions.position = collision.contactPoint;
Audio.playSound(hitSounds[soundIndex], audioOptions);
// bump the expiry
soundExpiry = msec + SOUND_TRIGGER_CLEAR;
// log the collision info
Uuid.print("my sessionID = ", mySessionID);
Uuid.print(" their sessionID = ", theirSessionID);
Vec3.print(" penetration = ", collision.penetration);
Vec3.print(" contactPoint = ", collision.contactPoint);
} else {
// this is a recurring contact --> continue to delay sound trigger
soundExpiry = msec + SOUND_TRIGGER_DELAY;
}
}
MyAvatar.collisionWithAvatar.connect(playHitSound);

274
interface/interface_en.ts Normal file
View file

@ -0,0 +1,274 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>Application</name>
<message>
<location filename="src/Application.cpp" line="1380"/>
<source>Export Voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="1381"/>
<source>Sparse Voxel Octree Files (*.svo)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3608"/>
<source>Open Script</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3609"/>
<source>JavaScript Files (*.js)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ChatWindow</name>
<message>
<location filename="ui/chatWindow.ui" line="20"/>
<location filename="../build/interface/ui_chatWindow.h" line="143"/>
<source>Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/chatWindow.ui" line="50"/>
<location filename="../build/interface/ui_chatWindow.h" line="144"/>
<source>Connecting to XMPP...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/chatWindow.ui" line="71"/>
<location filename="../build/interface/ui_chatWindow.h" line="145"/>
<source> online now:</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<source>day</source>
<translation>
<numerusform>%n day</numerusform>
<numerusform>%n days</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<source>hour</source>
<translation>
<numerusform>%n hour</numerusform>
<numerusform>%n hours</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<source>minute</source>
<translation>
<numerusform>%n minute</numerusform>
<numerusform>%n minutes</numerusform>
</translation>
</message>
<message numerus="yes">
<source>second</source>
<translation type="vanished">
<numerusform>%n second</numerusform>
<numerusform>%n seconds</numerusform>
</translation>
</message>
<message>
<location filename="src/ui/ChatWindow.cpp" line="183"/>
<source>%1 online now:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Dialog</name>
<message>
<location filename="ui/updateDialog.ui" line="20"/>
<location filename="ui/updateDialog.ui" line="73"/>
<location filename="../build/interface/ui_updateDialog.h" line="137"/>
<location filename="../build/interface/ui_updateDialog.h" line="138"/>
<source>Update Required</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/updateDialog.ui" line="129"/>
<location filename="../build/interface/ui_updateDialog.h" line="140"/>
<source>Download</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/updateDialog.ui" line="151"/>
<location filename="../build/interface/ui_updateDialog.h" line="141"/>
<source>Skip Version</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/updateDialog.ui" line="173"/>
<location filename="../build/interface/ui_updateDialog.h" line="142"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Menu</name>
<message>
<location filename="src/Menu.cpp" line="460"/>
<source>Open .ini config file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Menu.cpp" line="462"/>
<location filename="src/Menu.cpp" line="474"/>
<source>Text files (*.ini)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Menu.cpp" line="472"/>
<source>Save .ini config file</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreferencesDialog</name>
<message>
<location filename="ui/preferencesDialog.ui" line="90"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="618"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="125"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="619"/>
<source>Save all changes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="196"/>
<location filename="ui/preferencesDialog.ui" line="573"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="620"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="629"/>
<source>Avatar</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="230"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="621"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Avatar display name &lt;span style=&quot; color:#909090;&quot;&gt;(optional)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="266"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="622"/>
<source>Not showing a name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="294"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="623"/>
<source>Head</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="395"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="625"/>
<source>Body</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="506"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="627"/>
<source>Advanced Tuning</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="537"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="628"/>
<source>It&apos;s not recomended that you play with these settings unless you&apos;ve looked into exactly what they do.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="605"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="630"/>
<source>Vertical field of view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="708"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="631"/>
<source>Lean scale (applies to Faceshift users)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="793"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="632"/>
<source>Avatar scale &lt;span style=&quot; color:#909090;&quot;&gt;(default is 1.0)&lt;/span&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="875"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="633"/>
<source>Pupil dillation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="954"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="634"/>
<source>Audio Jitter Buffer Samples (0 for automatic)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="1045"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="635"/>
<source>Faceshift eye detection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="1125"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="636"/>
<source>Voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="1157"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="637"/>
<source>Maximum voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/preferencesDialog.ui" line="1236"/>
<location filename="../build/interface/ui_preferencesDialog.h" line="638"/>
<source>Max voxels sent each second</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="src/ui/ImportDialog.cpp" line="22"/>
<location filename="src/ui/ImportDialog.cpp" line="23"/>
<source>Import Voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/ui/ImportDialog.cpp" line="24"/>
<source>Loading ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/ui/ImportDialog.cpp" line="25"/>
<source>Place voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/ui/ImportDialog.cpp" line="26"/>
<source>&lt;b&gt;Import&lt;/b&gt; %1 as voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/ui/ImportDialog.cpp" line="27"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="44px"
height="44px"
viewBox="0 0 44 44"
version="1.1"
id="svg2"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="close.svg">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Slice 1</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview14"
showgrid="false"
inkscape:zoom="3.7926636"
inkscape:cx="57.156875"
inkscape:cy="33.978935"
inkscape:window-x="536"
inkscape:window-y="258"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<title
id="title4">Slice 1</title>
<description
id="description6">Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<defs
id="defs8" />
<g
id="Page-1"
sketch:type="MSPage"
transform="translate(0.52733383,0.52733392)"
style="fill:none;stroke:none" />
<rect
id="rect2993"
width="5.7796612"
height="26.101694"
x="19.730724"
y="16.374792"
ry="3.371469" />
<rect
id="rect2995"
width="35.423729"
height="2.9830508"
x="4.6290293"
y="2.3917408"
ry="1.4915254" />
<rect
id="rect2999"
width="31.135593"
height="21.067797"
x="6.6798768"
y="4.0697069"
ry="1.4915254" />
<rect
style="fill:#ff0000"
id="rect3003"
width="27.779657"
height="17.711861"
x="8.171401"
y="5.3747911"
ry="0.46610171" />
<rect
style="fill:#999999"
id="rect3011"
width="3.1694915"
height="13.983051"
x="21.035809"
y="25.883266"
ry="0.46610171" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="44px"
height="44px"
viewBox="0 0 44 44"
version="1.1"
id="svg2"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="pin.svg">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Slice 1</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1058"
id="namedview14"
showgrid="false"
inkscape:zoom="3.7926636"
inkscape:cx="39.754857"
inkscape:cy="33.978935"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<title
id="title4">Slice 1</title>
<description
id="description6">Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<defs
id="defs8" />
<g
id="Page-1"
sketch:type="MSPage"
transform="translate(0.52733383,0.52733392)"
style="fill:none;stroke:none" />
<rect
style="fill:#b3b3b3"
id="rect3013"
width="43.768692"
height="44.296078"
x="0.26366693"
y="-0.032378189"
ry="0.46610171" />
<rect
id="rect2993"
width="5.7796612"
height="26.101694"
x="19.730724"
y="16.374792"
ry="3.371469" />
<rect
id="rect2995"
width="35.423729"
height="2.9830508"
x="4.6290293"
y="2.3917408"
ry="1.4915254" />
<rect
id="rect2999"
width="31.135593"
height="21.067797"
x="6.6798768"
y="4.0697069"
ry="1.4915254" />
<rect
style="fill:#ff0000"
id="rect3003"
width="27.779657"
height="17.711861"
x="8.171401"
y="5.3747911"
ry="0.46610171" />
<rect
style="fill:#999999"
id="rect3011"
width="3.1694915"
height="13.983051"
x="21.035809"
y="25.883266"
ry="0.46610171" />
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -1,8 +1,11 @@
<RCC>
<qresource prefix="/">
<qresource prefix="/">
<file>styles/search.svg</file>
<file>images/close.svg</file>
<file>images/kill-script.svg</file>
<file>images/reload.svg</file>
<file>images/stop.svg</file>
<file>images/pin.svg</file>
<file>images/pinned.svg</file>
</qresource>
</RCC>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 20.6 25.5" enable-background="new 0 0 20.6 25.5" xml:space="preserve">
<g>
<path fill="#0E7077" d="M18,11.8c0.3-1.1,0.1-2.1-0.3-2.2c-0.4-0.1-0.9,0.8-1.2,1.9c-0.1-1-0.1-1.8,0-2.4l0,0
c-1.3-0.4-2.4-1.5-3.1-2.7c-0.6,1.1-2,2.3-3.8,3.4c-0.1,0-0.2,0.1-0.2,0.1c1,0.9,0.6,1.6-0.6,0.3c-0.3,0.2-0.6,0.3-0.9,0.4
c0.2,0,0.4,0.1,0.7,0.1c0.9,0.3,1.1,0.7,1.3,1.4c-0.2-0.3-0.5-0.6-0.9-0.8c0,0.1,0.1,0.2,0.1,0.3c0,0.3-0.3,0.6-0.6,0.6
c-0.3,0-0.6-0.3-0.6-0.6c0-0.2,0.1-0.4,0.3-0.5c-0.3,0-0.6,0-1.1,0c0.2,0.3,0.3,0.8,0.7,1.1c-0.5-0.2-0.9-0.7-1.2-1.2
c-0.3,0.1-0.6,0.2-0.9,0.2c-0.6,0.1-1.1,0.1-1.5,0c0,0.1,0,0.3,0.1,0.4c0.3,1.1,0.8,2,1.2,1.9c0.2,0,0.3-0.3,0.4-0.7
c0.1,0.7,0.2,1.5,0.3,2.4c0.2,1.8,4.2,4.8,4.2,4.8h1.5c0,0,4-3.1,4.2-4.8c0.1-0.9,0.2-1.8,0.3-2.4c0.1,0.4,0.2,0.6,0.4,0.7
C17.2,13.8,17.7,12.9,18,11.8L18,11.8z M8.4,11.6c0,0.1,0.1,0.2,0.2,0.2c0.1,0,0.2-0.1,0.2-0.2c0-0.1-0.1-0.2-0.2-0.2
C8.5,11.4,8.4,11.5,8.4,11.6L8.4,11.6z M7.8,1.1c3.4-1.7,6.4-1.4,6.9,0.7c0.7-0.5,1.3-0.6,2-0.3c2.6,1.4,3.8,9.8,3.9,18.8
c0,1.8,0,3.3,0,4.7c-1.8-0.5-4.2-1.3-4.7-1.6c-1.3-0.6-1.6-3.1-1.6-5c-0.9,0.9-1.9,1.7-2.4,2h-1.7c0,0-1.1-0.8-2.1-1.8
c-0.1-0.1-0.2-0.2-0.3-0.3c0,1.9-0.2,4.4-1.5,5.1c-0.7,0.3-4.7,1.6-6.2,2C0.3,13.9,1.7,4.2,7.8,1.1L7.8,1.1z M12,18
C12.1,17.9,12.1,17.9,12,18c0-0.1,0-0.2,0-0.2c0,0-0.1,0.1-0.1,0.1C11.9,17.9,12,18,12,18L12,18z M11.8,18c0,0,0.1-0.1,0.1-0.1
c0,0-0.1-0.1-0.1-0.1l-0.1,0c0,0-0.1,0.1-0.1,0.1C11.7,18.1,11.7,18.1,11.8,18L11.8,18L11.8,18z M11,17.4L11,17.4
c0.5,0,1-0.3,0.6-0.3H11h-0.6C10,17.1,10.5,17.4,11,17.4L11,17.4z M12.6,16.6c0.4,0.1,0.8,0,0.7,0c-0.1,0.1-0.6,0.5-0.6,0.5l0,0.1
c0,0.6-0.7,1.2-1.7,1.2c-0.9,0-1.7-0.5-1.7-1.2l0-0.1c0,0-0.5-0.4-0.6-0.5c0,0,0.3,0.2,0.7,0c1-0.3,1.4-0.1,1.6,0.1
C11.2,16.5,11.6,16.3,12.6,16.6L12.6,16.6z M13.5,10.9c1-0.3,1.4,0.1,2.3-0.4c0,0-0.5,1.6-1.5,1.9c0.4-0.3,0.6-0.8,0.7-1.1
c-0.4,0-0.7-0.1-1.1,0c0.2,0.1,0.3,0.3,0.3,0.5c0,0.3-0.3,0.6-0.6,0.6c-0.3,0-0.6-0.3-0.6-0.6c0-0.1,0-0.2,0.1-0.3
c-0.4,0.2-0.7,0.5-0.9,0.8C12.5,11.6,12.7,11.2,13.5,10.9L13.5,10.9z M14.1,11.6c0-0.1-0.1-0.2-0.2-0.2c-0.1,0-0.2,0.1-0.2,0.2
c0,0.1,0.1,0.2,0.2,0.2C14,11.8,14.1,11.7,14.1,11.6L14.1,11.6z M14,9c1.2-0.6,1.8,0.4,1.8,0.4s-1.2-0.8-2.1,0.3
C11.8,12.2,11.3,10.5,14,9L14,9z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 15.9 15.9" enable-background="new 0 0 15.9 15.9" xml:space="preserve">
<g>
<g>
<path fill="#666666" d="M15.5,13.7l-1.8,1.8c-0.2,0.2-0.6,0.4-0.9,0.4s-0.7-0.1-0.9-0.4L8,11.6L4,15.5c-0.2,0.2-0.6,0.4-0.9,0.4
s-0.7-0.1-0.9-0.4l-1.8-1.8C0.1,13.5,0,13.1,0,12.8s0.1-0.7,0.4-0.9L4.3,8L0.4,4C0.1,3.8,0,3.4,0,3.1s0.1-0.7,0.4-0.9l1.8-1.8
C2.4,0.1,2.8,0,3.1,0S3.8,0.1,4,0.4L8,4.3l3.9-3.9C12.1,0.1,12.5,0,12.8,0s0.7,0.1,0.9,0.4l1.8,1.8c0.2,0.2,0.4,0.6,0.4,0.9
S15.8,3.8,15.5,4L11.6,8l3.9,3.9c0.2,0.2,0.4,0.6,0.4,0.9S15.8,13.5,15.5,13.7z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 944 B

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 13.9 8.8" enable-background="new 0 0 13.9 8.8" xml:space="preserve">
<path fill="#666666" d="M13.6,2.6L7.8,8.4C7.6,8.6,7.3,8.8,7,8.8S6.4,8.6,6.2,8.4L0.3,2.6C0.1,2.4,0,2.1,0,1.8S0.1,1.2,0.3,1L1,0.3
C1.2,0.1,1.5,0,1.8,0s0.6,0.1,0.8,0.3L7,4.7l4.3-4.3C11.5,0.1,11.8,0,12.1,0s0.6,0.1,0.8,0.3L13.6,1c0.2,0.2,0.3,0.5,0.3,0.8
S13.8,2.4,13.6,2.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 733 B

View file

@ -0,0 +1,113 @@
* {
padding: 0;
margin: 0;
}
FramelessDialog {
font-family: Helvetica, Arial, sans-serif;
font-size: 16px;
}
QLineEdit {
background-color: rgba(255, 255, 255, 1);
border-style: solid;
border-width: 1px;
border-color: #ccc;
padding: 8px;
font-size: 16px;
color: rgb(51, 51, 51);
}
QLabel p {
color: #0e7077;
font-size: 23px;
}
QPushButton {
border-width: 0;
border-radius: 9px;
font-family: Arial;
font-size: 18px;
color: #ffffff;
padding: 10px 0px;
}
QSpinBox, QDoubleSpinBox {
padding: 5px;
border-width: 1;
font-size: 16px;
color: rgb(51, 51, 51);
}
QDoubleSpinBox::up-arrow,
QSpinBox::up-arrow {
background-image: url(styles/up.svg);
background-repeat: no-repeat;
background-position: center center;
}
QDoubleSpinBox::down-arrow,
QSpinBox::down-arrow {
background-image: url(styles/down.svg);
background-repeat: no-repeat;
background-position: center center;
}
QDoubleSpinBox::up-button,
QSpinBox::up-button,
QDoubleSpinBox::down-button,
QSpinBox::down-button {
width: 26px;
height: 13px;
background-color: #f2f2f2;
border-color: #ccc;
border-style: solid;
border-width: 1px;
}
QDoubleSpinBox::up-button,
QSpinBox::up-button {
margin-top:2px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
QDoubleSpinBox::down-button,
QSpinBox::down-button {
margin-bottom:3px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
QSlider {
width: 125px;
height: 18px;
}
QSlider::groove:horizontal {
border: none;
background-image: url(styles/slider-bg.svg);
background-repeat: no-repeat;
background-position: center center;
}
QSlider::handle:horizontal {
width: 18px;
height: 18px;
background-image: url(styles/slider-handle.svg);
background-repeat: no-repeat;
background-position: center center;
}
QPushButton#closeButton {
border-color: #ccc;
border-style: solid;
border-width: 1px;
border-radius: 0;
background-color: #fff;
background-image: url(styles/close.svg);
background-repeat: no-repeat;
background-position: center center;
}

View file

@ -0,0 +1,21 @@
QLabel#avatarLabel {
background-image: url(styles/avatar.svg);
background-repeat: no-repeat;
background-position: left center;
}
QLabel#advancedTuningLabel {
background-image: url(styles/wrench.svg);
background-repeat: no-repeat;
background-position: left center;
}
QPushButton#buttonBrowseHead,
QPushButton#buttonBrowseBody {
background-image: url(styles/search.svg);
background-repeat: no-repeat;
background-position: center center;
background-color: #fff;
border-radius: 0;
padding: 0;
}

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 125 9" enable-background="new 0 0 125 9" xml:space="preserve">
<g>
<path fill="#CCCCCC" d="M120.5,9H4.5C2,9,0,7,0,4.5S2,0,4.5,0h116c2.5,0,4.5,2,4.5,4.5S123,9,120.5,9z M4.5,1C2.6,1,1,2.6,1,4.5
S2.6,8,4.5,8h116c1.9,0,3.5-1.6,3.5-3.5S122.4,1,120.5,1H4.5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 654 B

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 17 17" enable-background="new 0 0 17 17" xml:space="preserve">
<g>
<circle fill="#0E7077" cx="8.5" cy="8.5" r="8.5"/>
<circle fill="#669999" cx="8.5" cy="8.5" r="5.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 567 B

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 13.9 8.8" enable-background="new 0 0 13.9 8.8" xml:space="preserve">
<path fill="#666666" d="M13.6,7.8l-0.7,0.7c-0.2,0.2-0.5,0.3-0.8,0.3s-0.6-0.1-0.8-0.3L7,4.1L2.6,8.4C2.4,8.6,2.1,8.8,1.8,8.8
S1.2,8.6,1,8.4L0.3,7.8C0.1,7.6,0,7.3,0,7s0.1-0.6,0.3-0.8l5.8-5.8C6.4,0.1,6.6,0,7,0s0.6,0.1,0.8,0.3l5.8,5.8
c0.2,0.2,0.3,0.5,0.3,0.8S13.8,7.6,13.6,7.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 738 B

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 19.2 19.9" enable-background="new 0 0 19.2 19.9" xml:space="preserve">
<path fill="#0E7077" d="M1.3,7.7C2.6,9,4.5,9.3,6.1,8.6l10.4,10.8c0.6,0.6,1.6,0.6,2.2,0c0.6-0.6,0.6-1.7,0-2.3L8.3,6.3
c0.7-1.6,0.4-3.6-0.9-5c-1.1-1.1-2.6-1.5-4-1.2L4,0.8l0.7,0.7L6,2.8L5.3,5.5L4,5.9L2.7,6.2l-1-1L1.4,4.9L0.1,3.5
C-0.2,5,0.2,6.5,1.3,7.7z M16.6,18.2c0-0.6,0.4-1,0.9-1c0.5,0,0.9,0.5,0.9,1c0,0.6-0.4,1-0.9,1C17,19.2,16.6,18.7,16.6,18.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 813 B

View file

@ -151,6 +151,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_lastQueriedViewFrustum(),
_lastQueriedTime(usecTimestampNow()),
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
_cameraPushback(0.0f),
_mouseX(0),
_mouseY(0),
_lastMouseMove(usecTimestampNow()),
@ -521,6 +522,8 @@ void Application::paintGL() {
glEnable(GL_LINE_SMOOTH);
float pushback = 0.0f;
float pushbackFocalLength = 0.0f;
if (OculusManager::isConnected()) {
_myCamera.setUpShift(0.0f);
_myCamera.setDistance(0.0f);
@ -533,6 +536,41 @@ void Application::paintGL() {
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
_myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
glm::vec3 planeNormal = _myCamera.getTargetRotation() * IDENTITY_FRONT;
const float BASE_PUSHBACK_RADIUS = 0.25f;
float pushbackRadius = _myCamera.getNearClip() + _myAvatar->getScale() * BASE_PUSHBACK_RADIUS;
glm::vec4 plane(planeNormal, -glm::dot(planeNormal, _myCamera.getTargetPosition()) - pushbackRadius);
// push camera out of any intersecting avatars
foreach (const AvatarSharedPointer& avatarData, _avatarManager.getAvatarHash()) {
Avatar* avatar = static_cast<Avatar*>(avatarData.data());
if (avatar->isMyAvatar()) {
continue;
}
if (glm::distance(avatar->getPosition(), _myCamera.getTargetPosition()) >
avatar->getBoundingRadius() + pushbackRadius) {
continue;
}
float angle = angleBetween(avatar->getPosition() - _myCamera.getTargetPosition(), planeNormal);
if (angle > PI_OVER_TWO) {
continue;
}
float scale = 1.0f - angle / PI_OVER_TWO;
scale = qMin(1.0f, scale * 2.5f);
static CollisionList collisions(64);
collisions.clear();
if (!avatar->findPlaneCollisions(plane, collisions)) {
continue;
}
for (int i = 0; i < collisions.size(); i++) {
pushback = qMax(pushback, glm::length(collisions.getCollision(i)->_penetration) * scale);
}
}
const float MAX_PUSHBACK = 0.35f;
pushback = qMin(pushback, MAX_PUSHBACK * _myAvatar->getScale());
const float BASE_PUSHBACK_FOCAL_LENGTH = 0.5f;
pushbackFocalLength = BASE_PUSHBACK_FOCAL_LENGTH * _myAvatar->getScale();
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
_myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition());
@ -549,13 +587,26 @@ void Application::paintGL() {
// if the head would intersect the near clip plane, we must push the camera out
glm::vec3 relativePosition = glm::inverse(_myCamera.getTargetRotation()) *
(eyePosition - _myCamera.getTargetPosition());
const float PUSHBACK_RADIUS = 0.2f;
float pushback = relativePosition.z + _myCamera.getNearClip() +
_myAvatar->getScale() * PUSHBACK_RADIUS - _myCamera.getDistance();
if (pushback > 0.0f) {
const float BASE_PUSHBACK_RADIUS = 0.2f;
float pushbackRadius = _myCamera.getNearClip() + _myAvatar->getScale() * BASE_PUSHBACK_RADIUS;
pushback = relativePosition.z + pushbackRadius - _myCamera.getDistance();
pushbackFocalLength = _myCamera.getDistance();
}
// handle pushback, if any
if (pushbackFocalLength > 0.0f) {
const float PUSHBACK_DECAY = 0.5f;
_cameraPushback = qMax(pushback, _cameraPushback * PUSHBACK_DECAY);
if (_cameraPushback > EPSILON) {
_myCamera.setTargetPosition(_myCamera.getTargetPosition() +
_myCamera.getTargetRotation() * glm::vec3(0.0f, 0.0f, pushback));
_myCamera.getTargetRotation() * glm::vec3(0.0f, 0.0f, _cameraPushback));
float enlargement = pushbackFocalLength / (pushbackFocalLength + _cameraPushback);
_myCamera.setFieldOfView(glm::degrees(2.0f * atanf(enlargement * tanf(
glm::radians(Menu::getInstance()->getFieldOfView() * 0.5f)))));
} else {
_myCamera.setFieldOfView(Menu::getInstance()->getFieldOfView());
}
updateProjectionMatrix(_myCamera, true);
}
// Update camera position
@ -2563,6 +2614,12 @@ void Application::displayOverlay() {
}
bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));
if ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
const float MAX_MAGNITUDE = 0.7f;
float magnitude = MAX_MAGNITUDE * (1 - _audio.getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME);
renderCollisionOverlay(_glWidget->width(), _glWidget->height(), magnitude, 1.0f);
}
_audio.renderToolBox(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP,
audioMeterY,

View file

@ -435,6 +435,7 @@ private:
QRect _mirrorViewRect;
RearMirrorTools* _rearMirrorTools;
float _cameraPushback;
glm::mat4 _untranslatedViewMatrix;
glm::vec3 _viewMatrixTranslation;
glm::mat4 _projectionMatrix;

View file

@ -86,7 +86,8 @@ Menu::Menu() :
_lastAvatarDetailDrop(usecTimestampNow()),
_fpsAverage(FIVE_SECONDS_OF_FRAMES),
_fastFPSAverage(ONE_SECOND_OF_FRAMES),
_loginAction(NULL)
_loginAction(NULL),
_preferencesDialog(NULL)
{
Application *appInstance = Application::getInstance();
@ -708,7 +709,12 @@ bool Menu::isOptionChecked(const QString& menuOption) {
}
void Menu::triggerOption(const QString& menuOption) {
_actionHash.value(menuOption)->trigger();
QAction* action = _actionHash.value(menuOption);
if (action) {
action->trigger();
} else {
qDebug() << "NULL Action for menuOption '" << menuOption << "'";
}
}
QAction* Menu::getActionForOption(const QString& menuOption) {
@ -767,165 +773,12 @@ void Menu::loginForCurrentDomain() {
}
void Menu::editPreferences() {
Application* applicationInstance = Application::getInstance();
ModelsBrowser headBrowser(Head);
ModelsBrowser skeletonBrowser(Skeleton);
const QString BROWSE_BUTTON_TEXT = "Browse";
QDialog dialog(applicationInstance->getWindow());
dialog.setWindowTitle("Interface Preferences");
QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
dialog.setLayout(layout);
QFormLayout* form = new QFormLayout();
layout->addLayout(form, 1);
QHBoxLayout headModelLayout;
QString faceURLString = applicationInstance->getAvatar()->getHead()->getFaceModel().getURL().toString();
QLineEdit headURLEdit(faceURLString);
QPushButton headBrowseButton(BROWSE_BUTTON_TEXT);
connect(&headBrowseButton, SIGNAL(clicked()), &headBrowser, SLOT(browse()));
connect(&headBrowser, SIGNAL(selected(QString)), &headURLEdit, SLOT(setText(QString)));
headURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH);
headURLEdit.setPlaceholderText(DEFAULT_HEAD_MODEL_URL.toString());
headModelLayout.addWidget(&headURLEdit);
headModelLayout.addWidget(&headBrowseButton);
form->addRow("Head URL:", &headModelLayout);
QHBoxLayout skeletonModelLayout;
QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString();
QLineEdit skeletonURLEdit(skeletonURLString);
QPushButton SkeletonBrowseButton(BROWSE_BUTTON_TEXT);
connect(&SkeletonBrowseButton, SIGNAL(clicked()), &skeletonBrowser, SLOT(browse()));
connect(&skeletonBrowser, SIGNAL(selected(QString)), &skeletonURLEdit, SLOT(setText(QString)));
skeletonURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH);
skeletonURLEdit.setPlaceholderText(DEFAULT_BODY_MODEL_URL.toString());
skeletonModelLayout.addWidget(&skeletonURLEdit);
skeletonModelLayout.addWidget(&SkeletonBrowseButton);
form->addRow("Skeleton URL:", &skeletonModelLayout);
QString displayNameString = applicationInstance->getAvatar()->getDisplayName();
QLineEdit* displayNameEdit = new QLineEdit(displayNameString);
displayNameEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Display name:", displayNameEdit);
QSlider* pupilDilation = new QSlider(Qt::Horizontal);
pupilDilation->setValue(applicationInstance->getAvatar()->getHead()->getPupilDilation() * pupilDilation->maximum());
form->addRow("Pupil Dilation:", pupilDilation);
QSlider* faceshiftEyeDeflection = new QSlider(Qt::Horizontal);
faceshiftEyeDeflection->setValue(_faceshiftEyeDeflection * faceshiftEyeDeflection->maximum());
form->addRow("Faceshift Eye Deflection:", faceshiftEyeDeflection);
QSpinBox* fieldOfView = new QSpinBox();
fieldOfView->setMaximum(180.f);
fieldOfView->setMinimum(1.f);
fieldOfView->setValue(_fieldOfView);
form->addRow("Vertical Field of View (Degrees):", fieldOfView);
QDoubleSpinBox* leanScale = new QDoubleSpinBox();
leanScale->setValue(applicationInstance->getAvatar()->getLeanScale());
form->addRow("Lean Scale:", leanScale);
QDoubleSpinBox* avatarScale = new QDoubleSpinBox();
avatarScale->setValue(applicationInstance->getAvatar()->getScale());
form->addRow("Avatar Scale:", avatarScale);
QSpinBox* audioJitterBufferSamples = new QSpinBox();
audioJitterBufferSamples->setMaximum(10000);
audioJitterBufferSamples->setMinimum(-10000);
audioJitterBufferSamples->setValue(_audioJitterBufferSamples);
form->addRow("Audio Jitter Buffer Samples (0 for automatic):", audioJitterBufferSamples);
QSpinBox* maxVoxels = new QSpinBox();
const int MAX_MAX_VOXELS = 5000000;
const int MIN_MAX_VOXELS = 0;
const int STEP_MAX_VOXELS = 50000;
maxVoxels->setMaximum(MAX_MAX_VOXELS);
maxVoxels->setMinimum(MIN_MAX_VOXELS);
maxVoxels->setSingleStep(STEP_MAX_VOXELS);
maxVoxels->setValue(_maxVoxels);
form->addRow("Maximum Voxels:", maxVoxels);
QSpinBox* maxVoxelsPPS = new QSpinBox();
const int MAX_MAX_VOXELS_PPS = 6000;
const int MIN_MAX_VOXELS_PPS = 60;
const int STEP_MAX_VOXELS_PPS = 10;
maxVoxelsPPS->setMaximum(MAX_MAX_VOXELS_PPS);
maxVoxelsPPS->setMinimum(MIN_MAX_VOXELS_PPS);
maxVoxelsPPS->setSingleStep(STEP_MAX_VOXELS_PPS);
maxVoxelsPPS->setValue(_maxVoxelPacketsPerSecond);
form->addRow("Maximum Voxels Packets Per Second:", maxVoxelsPPS);
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept()));
dialog.connect(buttons, SIGNAL(rejected()), SLOT(reject()));
layout->addWidget(buttons);
int ret = dialog.exec();
if (ret == QDialog::Accepted) {
bool shouldDispatchIdentityPacket = false;
if (headURLEdit.text() != faceURLString) {
// change the faceModelURL in the profile, it will also update this user's BlendFace
if (headURLEdit.text().isEmpty()) {
applicationInstance->getAvatar()->setFaceModelURL(QUrl(headURLEdit.placeholderText()));
} else {
applicationInstance->getAvatar()->setFaceModelURL(QUrl(headURLEdit.text()));
}
shouldDispatchIdentityPacket = true;
}
if (skeletonURLEdit.text() != skeletonURLString) {
// change the skeletonModelURL in the profile, it will also update this user's Body
if (skeletonURLEdit.text().isEmpty()) {
applicationInstance->getAvatar()->setSkeletonModelURL(QUrl(skeletonURLEdit.placeholderText()));
} else {
applicationInstance->getAvatar()->setSkeletonModelURL(QUrl(skeletonURLEdit.text()));
}
shouldDispatchIdentityPacket = true;
}
QString displayNameStr(displayNameEdit->text());
if (displayNameStr != displayNameString) {
applicationInstance->getAvatar()->setDisplayName(displayNameStr);
shouldDispatchIdentityPacket = true;
}
if (shouldDispatchIdentityPacket) {
applicationInstance->getAvatar()->sendIdentityPacket();
applicationInstance->bumpSettings();
}
applicationInstance->getAvatar()->getHead()->setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());
_maxVoxels = maxVoxels->value();
applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels);
_maxVoxelPacketsPerSecond = maxVoxelsPPS->value();
applicationInstance->getAvatar()->setLeanScale(leanScale->value());
applicationInstance->getAvatar()->setClampedTargetScale(avatarScale->value());
_audioJitterBufferSamples = audioJitterBufferSamples->value();
if (_audioJitterBufferSamples != 0) {
applicationInstance->getAudio()->setJitterBufferSamples(_audioJitterBufferSamples);
}
_fieldOfView = fieldOfView->value();
applicationInstance->resizeGL(applicationInstance->getGLWidget()->width(), applicationInstance->getGLWidget()->height());
_faceshiftEyeDeflection = faceshiftEyeDeflection->value() / (float)faceshiftEyeDeflection->maximum();
if (!_preferencesDialog) {
_preferencesDialog = new PreferencesDialog(Application::getInstance()->getWindow());
_preferencesDialog->show();
} else {
_preferencesDialog->close();
}
QMetaObject::invokeMethod(applicationInstance->getAudio(), "reset", Qt::QueuedConnection);
sendFakeEnterEvent();
}
void Menu::goToDomain(const QString newDomain) {
@ -1208,7 +1061,7 @@ void Menu::showMetavoxelEditor() {
void Menu::showChat() {
QMainWindow* mainWindow = Application::getInstance()->getWindow();
if (!_chatWindow) {
mainWindow->addDockWidget(Qt::NoDockWidgetArea, _chatWindow = new ChatWindow());
mainWindow->addDockWidget(Qt::RightDockWidgetArea, _chatWindow = new ChatWindow());
}
if (!_chatWindow->toggleViewAction()->isChecked()) {
int width = _chatWindow->width();

View file

@ -22,6 +22,7 @@
#include <OctreeConstants.h>
#include "location/LocationManager.h"
#include "ui/PreferencesDialog.h"
#include "ui/ChatWindow.h"
const float ADJUST_LOD_DOWN_FPS = 40.0;
@ -71,10 +72,13 @@ public:
void triggerOption(const QString& menuOption);
QAction* getActionForOption(const QString& menuOption);
float getAudioJitterBufferSamples() const { return _audioJitterBufferSamples; }
void setAudioJitterBufferSamples(float audioJitterBufferSamples) { _audioJitterBufferSamples = audioJitterBufferSamples; }
float getFieldOfView() const { return _fieldOfView; }
void setFieldOfView(float fieldOfView) { _fieldOfView = fieldOfView; }
float getFaceshiftEyeDeflection() const { return _faceshiftEyeDeflection; }
void setFaceshiftEyeDeflection(float faceshiftEyeDeflection) { _faceshiftEyeDeflection = faceshiftEyeDeflection; }
BandwidthDialog* getBandwidthDialog() const { return _bandwidthDialog; }
FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; }
ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; }
@ -97,6 +101,7 @@ public:
// User Tweakable PPS from Voxel Server
int getMaxVoxelPacketsPerSecond() const { return _maxVoxelPacketsPerSecond; }
void setMaxVoxelPacketsPerSecond(int maxVoxelPacketsPerSecond) { _maxVoxelPacketsPerSecond = maxVoxelPacketsPerSecond; }
QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
const QString& actionName,
@ -222,6 +227,7 @@ private:
SimpleMovingAverage _fpsAverage;
SimpleMovingAverage _fastFPSAverage;
QAction* _loginAction;
QPointer<PreferencesDialog> _preferencesDialog;
QAction* _chatAction;
};

View file

@ -307,13 +307,13 @@ bool ModelUploader::addTextures(const QString& texdir, const QString fbxFile) {
foreach (FBXMesh mesh, geometry.meshes) {
foreach (FBXMeshPart part, mesh.parts) {
if (!part.diffuseFilename.isEmpty()) {
if (!addPart(QFileInfo(fbxFile).path() + "/" + part.diffuseFilename,
if (!addPart(texdir + "/" + part.diffuseFilename,
QString("texture%1").arg(++_texturesCount))) {
return false;
}
}
if (!part.normalFilename.isEmpty()) {
if (!addPart(QFileInfo(fbxFile).path() + "/" + part.normalFilename,
if (!addPart(texdir + "/" + part.normalFilename,
QString("texture%1").arg(++_texturesCount))) {
return false;
}

View file

@ -351,10 +351,10 @@ void drawvec3(int x, int y, float scale, float radians, float thick, int mono, g
glPopMatrix();
}
void renderCollisionOverlay(int width, int height, float magnitude) {
void renderCollisionOverlay(int width, int height, float magnitude, float red, float blue, float green) {
const float MIN_VISIBLE_COLLISION = 0.01f;
if (magnitude > MIN_VISIBLE_COLLISION) {
glColor4f(0, 0, 0, magnitude);
glColor4f(red, blue, green, magnitude);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glVertex2d(width, 0);

View file

@ -62,7 +62,7 @@ float extractUniformScale(const glm::vec3& scale);
double diffclock(timeval *clock1,timeval *clock2);
void renderCollisionOverlay(int width, int height, float magnitude);
void renderCollisionOverlay(int width, int height, float magnitude, float red = 0, float blue = 0, float green = 0);
void renderOrientationDirections( glm::vec3 position, const glm::quat& orientation, float size );

View file

@ -210,7 +210,14 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
{
// glow when moving far away
const float GLOW_DISTANCE = 20.0f;
Glower glower(_moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE ? 1.0f : 0.0f);
const float GLOW_MAX_LOUDNESS = 2500.0f;
const float MAX_GLOW = 0.5f;
const float GLOW_FROM_AVERAGE_LOUDNESS = ((this == Application::getInstance()->getAvatar())
? 0.0f
: MAX_GLOW * getHeadData()->getAudioLoudness() / GLOW_MAX_LOUDNESS);
Glower glower(_moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE
? 1.0f
: GLOW_FROM_AVERAGE_LOUDNESS);
// render body
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
@ -233,22 +240,22 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
// quick check before falling into the code below:
// (a 10 degree breadth of an almost 2 meter avatar kicks in at about 12m)
const float MIN_VOICE_SPHERE_DISTANCE = 12.f;
const float MIN_VOICE_SPHERE_DISTANCE = 12.0f;
if (distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) {
// render voice intensity sphere for avatars that are farther away
const float MAX_SPHERE_ANGLE = 10.f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_ANGLE = 1.f * RADIANS_PER_DEGREE;
const float MAX_SPHERE_ANGLE = 10.0f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_ANGLE = 1.0f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_SIZE = 0.01f;
const float SPHERE_LOUDNESS_SCALING = 0.0005f;
const float SPHERE_COLOR[] = { 0.5f, 0.8f, 0.8f };
float height = getSkeletonHeight();
glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.f;
glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.0f;
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
if (renderMode == NORMAL_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) &&
(angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE);
glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.0f - angle / MAX_SPHERE_ANGLE);
glPushMatrix();
glTranslatef(_position.x, _position.y, _position.z);
glScalef(height, height, height);
@ -280,9 +287,9 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
glm::vec3 chatAxis = glm::axis(chatRotation);
glRotatef(glm::degrees(glm::angle(chatRotation)), chatAxis.x, chatAxis.y, chatAxis.z);
glColor3f(0.f, 0.8f, 0.f);
glRotatef(180.f, 0.f, 1.f, 0.f);
glRotatef(180.f, 0.f, 0.f, 1.f);
glColor3f(0.0f, 0.8f, 0.0f);
glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
glScalef(_scale * CHAT_MESSAGE_SCALE, _scale * CHAT_MESSAGE_SCALE, 1.0f);
glDisable(GL_LIGHTING);
@ -298,7 +305,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
_chatMessage[lastIndex] = '\0';
textRenderer(CHAT)->draw(-width / 2.0f, 0, _chatMessage.c_str());
_chatMessage[lastIndex] = lastChar;
glColor3f(0.f, 1.f, 0.f);
glColor3f(0.0f, 1.0f, 0.0f);
textRenderer(CHAT)->draw(width / 2.0f - lastWidth, 0, _chatMessage.c_str() + lastIndex);
}
glEnable(GL_LIGHTING);
@ -522,6 +529,11 @@ bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penet
//return getHead()->getFaceModel().findSphereCollisions(penetratorCenter, penetratorRadius, collisions);
}
bool Avatar::findPlaneCollisions(const glm::vec4& plane, CollisionList& collisions) {
return _skeletonModel.findPlaneCollisions(plane, collisions) ||
getHead()->getFaceModel().findPlaneCollisions(plane, collisions);
}
void Avatar::updateShapePositions() {
_skeletonModel.updateShapePositions();
Model& headModel = getHead()->getFaceModel();
@ -550,7 +562,7 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti
const PalmData* palm = handData->getPalm(i);
if (palm && palm->hasPaddle()) {
// create a disk collision proxy where the hand is
glm::vec3 fingerAxis(0.f);
glm::vec3 fingerAxis(0.0f);
for (size_t f = 0; f < palm->getNumFingers(); ++f) {
const FingerData& finger = (palm->getFingers())[f];
if (finger.isActive()) {
@ -692,8 +704,8 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2,
glm::vec3 perpCos = glm::normalize(glm::cross(axis, perpSin));
perpSin = glm::cross(perpCos, axis);
float anglea = 0.f;
float angleb = 0.f;
float anglea = 0.0f;
float angleb = 0.0f;
for (int i = 0; i < NUM_BODY_CONE_SIDES; i ++) {
@ -743,8 +755,8 @@ void Avatar::updateCollisionFlags() {
void Avatar::setScale(float scale) {
_scale = scale;
if (_targetScale * (1.f - RESCALING_TOLERANCE) < _scale &&
_scale < _targetScale * (1.f + RESCALING_TOLERANCE)) {
if (_targetScale * (1.0f - RESCALING_TOLERANCE) < _scale &&
_scale < _targetScale * (1.0f + RESCALING_TOLERANCE)) {
_scale = _targetScale;
}
}

View file

@ -64,7 +64,7 @@ enum ScreenTintLayer {
// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found)
// this is basically in the center of the ground plane. Slightly adjusted. This was asked for by
// Grayson as he's building a street around here for demo dinner 2
const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE);
const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.0f, 0.5f * TREE_SCALE);
class Texture;
@ -119,6 +119,12 @@ public:
bool findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius,
CollisionList& collisions, int skeletonSkipIndex = -1);
/// Checks for penetration between the described plane and the avatar.
/// \param plane the penetration plane
/// \param collisions[out] a list to which collisions get appended
/// \return whether or not the plane penetrated
bool findPlaneCollisions(const glm::vec4& plane, CollisionList& collisions);
/// Checks for collision between the a spherical particle and the avatar (including paddle hands)
/// \param collisionCenter the center of particle's bounding sphere
/// \param collisionRadius the radius of particle's bounding sphere
@ -143,8 +149,6 @@ public:
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
/// \return true if we expect the avatar would move as a result of the collision
bool collisionWouldMoveAvatar(CollisionInfo& collision) const;
@ -157,6 +161,9 @@ public:
public slots:
void updateCollisionFlags();
signals:
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
protected:
SkeletonModel _skeletonModel;
float _bodyYawDelta;

View file

@ -163,6 +163,11 @@ void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) {
// TODO: submit collision info to MyAvatar which should lean accordingly
averageContactPoint /= (float)handCollisions.size();
avatar->applyCollision(averageContactPoint, totalPenetration);
CollisionInfo collision;
collision._penetration = totalPenetration;
collision._contactPoint = averageContactPoint;
emit avatar->collisionWithAvatar(avatar->getSessionUUID(), _owningAvatar->getSessionUUID(), collision);
}
}
}

View file

@ -647,7 +647,7 @@ void MyAvatar::renderBody(RenderMode renderMode) {
_skeletonModel.render(1.0f, modelRenderMode);
// Render head so long as the camera isn't inside it
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.40f;
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
Camera* myCamera = Application::getInstance()->getCamera();
if (renderMode != NORMAL_RENDER_MODE || (glm::length(myCamera->getPosition() - getHead()->calculateAverageEyePosition()) >
RENDER_HEAD_CUTOFF_DISTANCE * _scale)) {
@ -896,8 +896,7 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float
return false;
}
static CollisionList bodyCollisions(16);
const float BODY_COLLISION_RESOLVE_TIMESCALE = 0.5f; // seconds
const float BODY_COLLISION_RESOLUTION_TIMESCALE = 0.5f; // seconds
void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
// Reset detector for nearest avatar
@ -910,7 +909,7 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
updateShapePositions();
float myBoundingRadius = getBoundingRadius();
const float BODY_COLLISION_RESOLVE_FACTOR = deltaTime / BODY_COLLISION_RESOLVE_TIMESCALE;
const float BODY_COLLISION_RESOLUTION_FACTOR = deltaTime / BODY_COLLISION_RESOLUTION_TIMESCALE;
foreach (const AvatarSharedPointer& avatarPointer, avatars) {
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
@ -930,26 +929,19 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
_skeletonModel.getBodyShapes(myShapes);
QVector<const Shape*> theirShapes;
avatar->getSkeletonModel().getBodyShapes(theirShapes);
bodyCollisions.clear();
// TODO: add method to ShapeCollider for colliding lists of shapes
foreach (const Shape* myShape, myShapes) {
foreach (const Shape* theirShape, theirShapes) {
ShapeCollider::shapeShape(myShape, theirShape, bodyCollisions);
CollisionInfo collision;
if (ShapeCollider::collideShapesCoarse(myShapes, theirShapes, collision)) {
if (glm::length2(collision._penetration) > EPSILON) {
setPosition(getPosition() - BODY_COLLISION_RESOLUTION_FACTOR * collision._penetration);
_lastBodyPenetration += collision._penetration;
emit collisionWithAvatar(getSessionUUID(), avatar->getSessionUUID(), collision);
}
}
glm::vec3 totalPenetration(0.0f);
for (int j = 0; j < bodyCollisions.size(); ++j) {
CollisionInfo* collision = bodyCollisions.getCollision(j);
totalPenetration = addPenetrations(totalPenetration, collision->_penetration);
}
if (glm::length2(totalPenetration) > EPSILON) {
setPosition(getPosition() - BODY_COLLISION_RESOLVE_FACTOR * totalPenetration);
}
_lastBodyPenetration += totalPenetration;
// collide our hands against them
// TODO: make this work when we can figure out when the other avatar won't yeild
// (for example, we're colling against their chest or leg)
// (for example, we're colliding against their chest or leg)
//getHand()->collideAgainstAvatar(avatar, true);
// collide their hands against us

View file

@ -595,7 +595,7 @@ bool Model::findCollisions(const QVector<const Shape*> shapes, CollisionList& co
const Shape* theirShape = shapes[i];
for (int j = 0; j < _jointShapes.size(); ++j) {
const Shape* ourShape = _jointShapes[j];
if (ShapeCollider::shapeShape(theirShape, ourShape, collisions)) {
if (ShapeCollider::collideShapes(theirShape, ourShape, collisions)) {
collided = true;
}
}
@ -622,7 +622,7 @@ bool Model::findSphereCollisions(const glm::vec3& sphereCenter, float sphereRadi
} while (ancestorIndex != -1);
}
}
if (ShapeCollider::shapeShape(&sphere, _jointShapes[i], collisions)) {
if (ShapeCollider::collideShapes(&sphere, _jointShapes[i], collisions)) {
CollisionInfo* collision = collisions.getLastCollision();
collision->_type = MODEL_COLLISION;
collision->_data = (void*)(this);
@ -634,6 +634,21 @@ bool Model::findSphereCollisions(const glm::vec3& sphereCenter, float sphereRadi
return collided;
}
bool Model::findPlaneCollisions(const glm::vec4& plane, CollisionList& collisions) {
bool collided = false;
PlaneShape planeShape(plane);
for (int i = 0; i < _jointShapes.size(); i++) {
if (ShapeCollider::collideShapes(&planeShape, _jointShapes[i], collisions)) {
CollisionInfo* collision = collisions.getLastCollision();
collision->_type = MODEL_COLLISION;
collision->_data = (void*)(this);
collision->_flags = i;
collided = true;
}
}
return collided;
}
class Blender : public QRunnable {
public:

View file

@ -176,6 +176,8 @@ public:
bool findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius,
CollisionList& collisions, int skipIndex = -1);
bool findPlaneCollisions(const glm::vec4& plane, CollisionList& collisions);
/// \param collision details about the collisions
/// \return true if the collision is against a moveable joint

View file

@ -12,10 +12,12 @@
#include <QGridLayout>
#include <QFrame>
#include <QLayoutItem>
#include <QMainWindow>
#include <QPalette>
#include <QScrollBar>
#include <QSizePolicy>
#include <QTimer>
#include <QWidget>
#include "Application.h"
#include "FlowLayout.h"
@ -35,7 +37,9 @@ ChatWindow::ChatWindow() :
{
ui->setupUi(this);
// remove the title bar (see the Qt docs on setTitleBarWidget)
// remove the title bar (see the Qt docs on setTitleBarWidget), but we keep it for undocking
//
titleBar = titleBarWidget();
setTitleBarWidget(new QWidget());
FlowLayout* flowLayout = new FlowLayout(0, 4, 4);
@ -260,3 +264,16 @@ void ChatWindow::messageReceived(const QXmppMessage& message) {
}
#endif
void ChatWindow::togglePinned() {
QMainWindow* mainWindow = Application::getInstance()->getWindow();
mainWindow->removeDockWidget(this);
if (ui->togglePinnedButton->isChecked()) {
mainWindow->addDockWidget(ui->togglePinnedButton->isChecked() ? Qt::RightDockWidgetArea : Qt::NoDockWidgetArea, this);
}
if (!this->toggleViewAction()->isChecked()) {
this->toggleViewAction()->trigger();
}
this->setFloating(!ui->togglePinnedButton->isChecked());
setTitleBarWidget(ui->togglePinnedButton->isChecked()?new QWidget():titleBar);
}

View file

@ -50,12 +50,14 @@ private:
void addTimeStamp();
Ui::ChatWindow* ui;
QWidget* titleBar;
int numMessagesAfterLastTimeStamp;
QDateTime lastMessageStamp;
private slots:
void connected();
void timeout();
void togglePinned();
#ifdef HAVE_QXMPP
void error(QXmppClient::Error error);
void participantsChanged();

View file

@ -0,0 +1,100 @@
//
// FramelessDialog.cpp
// interface/src/ui
//
// Created by Stojce Slavkovski on 2/20/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Application.h"
#include "FramelessDialog.h"
const int RESIZE_HANDLE_WIDTH = 7;
FramelessDialog::FramelessDialog(QWidget *parent, Qt::WindowFlags flags) :
QDialog(parent, flags | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) {
setAttribute(Qt::WA_DeleteOnClose);
// handle rezize and move events
parentWidget()->installEventFilter(this);
// handle minimize, restore and focus events
Application::getInstance()->installEventFilter(this);
}
bool FramelessDialog::eventFilter(QObject* sender, QEvent* event) {
switch (event->type()) {
case QEvent::Move:
if (sender == parentWidget()) {
// move to upper left corner on app move
move(parentWidget()->geometry().topLeft());
}
break;
case QEvent::Resize:
if (sender == parentWidget()) {
// keep full app height on resizing the app
setFixedHeight(parentWidget()->size().height());
}
break;
case QEvent::WindowStateChange:
if (parentWidget()->isMinimized()) {
setHidden(true);
} else {
setHidden(false);
}
break;
case QEvent::ApplicationDeactivate:
// hide on minimize and focus lost
setHidden(true);
break;
case QEvent::ApplicationActivate:
setHidden(false);
break;
default:
break;
}
return false;
}
void FramelessDialog::setStyleSheetFile(const QString& fileName) {
QFile globalStyleSheet(Application::resourcesPath() + "styles/global.qss");
QFile styleSheet(Application::resourcesPath() + fileName);
if (styleSheet.open(QIODevice::ReadOnly) && globalStyleSheet.open(QIODevice::ReadOnly) ) {
QDir::setCurrent(Application::resourcesPath());
setStyleSheet(globalStyleSheet.readAll() + styleSheet.readAll());
}
}
void FramelessDialog::showEvent(QShowEvent* event) {
// move to upper left corner
move(parentWidget()->geometry().topLeft());
// keep full app height
setFixedHeight(parentWidget()->size().height());
// resize parrent if width is smaller than this dialog
if (parentWidget()->size().width() < size().width()) {
parentWidget()->resize(size().width(), parentWidget()->size().height());
}
}
void FramelessDialog::mousePressEvent(QMouseEvent* mouseEvent) {
if (abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH && mouseEvent->button() == Qt::LeftButton) {
_isResizing = true;
QApplication::setOverrideCursor(Qt::SizeHorCursor);
}
}
void FramelessDialog::mouseReleaseEvent(QMouseEvent* mouseEvent) {
QApplication::restoreOverrideCursor();
_isResizing = false;
}
void FramelessDialog::mouseMoveEvent(QMouseEvent* mouseEvent) {
if (_isResizing) {
resize(mouseEvent->pos().x(), size().height());
}
}

View file

@ -0,0 +1,38 @@
//
// FramelessDialog.h
// interface/src/ui
//
// Created by Stojce Slavkovski on 2/20/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_FramelessDialog_h
#define hifi_FramelessDialog_h
#include <QDialog>
class FramelessDialog : public QDialog {
Q_OBJECT
public:
FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0);
void setStyleSheetFile(const QString& fileName);
protected:
virtual void mouseMoveEvent(QMouseEvent* mouseEvent);
virtual void mousePressEvent(QMouseEvent* mouseEvent);
virtual void mouseReleaseEvent(QMouseEvent* mouseEvent);
virtual void showEvent(QShowEvent* event);
bool eventFilter(QObject* sender, QEvent* event);
private:
bool _isResizing;
};
#endif // hifi_FramelessDialog_h

View file

@ -65,7 +65,7 @@ static const QString propertiesIds[MODEL_METADATA_COUNT] = {
};
ModelsBrowser::ModelsBrowser(ModelType modelsType, QWidget* parent) :
QWidget(parent),
QWidget(parent, Qt::WindowStaysOnTopHint),
_handler(new ModelHandler(modelsType))
{
connect(_handler, SIGNAL(doneDownloading()), SLOT(resizeView()));

View file

@ -0,0 +1,164 @@
//
// PreferencesDialog.cpp
// interface/src/ui
//
// Created by Stojce Slavkovski on 2/20/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Application.h"
#include "Menu.h"
#include "PreferencesDialog.h"
#include "ModelsBrowser.h"
const int SCROLL_PANEL_BOTTOM_MARGIN = 30;
const int OK_BUTTON_RIGHT_MARGIN = 30;
const int BUTTONS_TOP_MARGIN = 24;
PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags flags) : FramelessDialog(parent, flags) {
ui.setupUi(this);
setStyleSheetFile("styles/preferences.qss");
loadPreferences();
connect(ui.closeButton, &QPushButton::clicked, this, &QDialog::close);
connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &PreferencesDialog::openHeadModelBrowser);
connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &PreferencesDialog::openBodyModelBrowser);
}
void PreferencesDialog::accept() {
savePreferences();
close();
}
void PreferencesDialog::setHeadUrl(QString modelUrl) {
ui.faceURLEdit->setText(modelUrl);
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
}
void PreferencesDialog::setSkeletonUrl(QString modelUrl) {
ui.skeletonURLEdit->setText(modelUrl);
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
}
void PreferencesDialog::openHeadModelBrowser() {
setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
ModelsBrowser modelBrowser(Head);
connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setHeadUrl);
modelBrowser.browse();
}
void PreferencesDialog::openBodyModelBrowser() {
setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
ModelsBrowser modelBrowser(Skeleton);
connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setSkeletonUrl);
modelBrowser.browse();
}
void PreferencesDialog::resizeEvent(QResizeEvent *resizeEvent) {
// keep buttons panel at the bottom
ui.buttonsPanel->setGeometry(0, size().height() - ui.buttonsPanel->height(), size().width(), ui.buttonsPanel->height());
// set width and height of srcollarea to match bottom panel and width
ui.scrollArea->setGeometry(ui.scrollArea->geometry().x(), ui.scrollArea->geometry().y(),
size().width(),
size().height() - ui.buttonsPanel->height() -
SCROLL_PANEL_BOTTOM_MARGIN - ui.scrollArea->geometry().y());
// move Save button to left position
ui.defaultButton->move(size().width() - OK_BUTTON_RIGHT_MARGIN - ui.defaultButton->size().width(), BUTTONS_TOP_MARGIN);
// move Save button to left position
ui.cancelButton->move(ui.defaultButton->pos().x() - ui.cancelButton->size().width(), BUTTONS_TOP_MARGIN);
// move close button
ui.closeButton->move(size().width() - OK_BUTTON_RIGHT_MARGIN - ui.closeButton->size().width(), ui.closeButton->pos().y());
}
void PreferencesDialog::loadPreferences() {
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
Menu* menuInstance = Menu::getInstance();
_displayNameString = myAvatar->getDisplayName();
ui.displayNameEdit->setText(_displayNameString);
_faceURLString = myAvatar->getHead()->getFaceModel().getURL().toString();
ui.faceURLEdit->setText(_faceURLString);
_skeletonURLString = myAvatar->getSkeletonModel().getURL().toString();
ui.skeletonURLEdit->setText(_skeletonURLString);
ui.pupilDilationSlider->setValue(myAvatar->getHead()->getPupilDilation() *
ui.pupilDilationSlider->maximum());
ui.faceshiftEyeDeflectionSider->setValue(menuInstance->getFaceshiftEyeDeflection() *
ui.faceshiftEyeDeflectionSider->maximum());
ui.audioJitterSpin->setValue(menuInstance->getAudioJitterBufferSamples());
ui.fieldOfViewSpin->setValue(menuInstance->getFieldOfView());
ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
ui.avatarScaleSpin->setValue(myAvatar->getScale());
ui.maxVoxelsSpin->setValue(menuInstance->getMaxVoxels());
ui.maxVoxelsPPSSpin->setValue(menuInstance->getMaxVoxelPacketsPerSecond());
}
void PreferencesDialog::savePreferences() {
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
bool shouldDispatchIdentityPacket = false;
QString displayNameStr(ui.displayNameEdit->text());
if (displayNameStr != _displayNameString) {
myAvatar->setDisplayName(displayNameStr);
shouldDispatchIdentityPacket = true;
}
QUrl faceModelURL(ui.faceURLEdit->text());
if (faceModelURL.toString() != _faceURLString) {
// change the faceModelURL in the profile, it will also update this user's BlendFace
myAvatar->setFaceModelURL(faceModelURL);
shouldDispatchIdentityPacket = true;
}
QUrl skeletonModelURL(ui.skeletonURLEdit->text());
if (skeletonModelURL.toString() != _skeletonURLString) {
// change the skeletonModelURL in the profile, it will also update this user's Body
myAvatar->setSkeletonModelURL(skeletonModelURL);
shouldDispatchIdentityPacket = true;
}
if (shouldDispatchIdentityPacket) {
myAvatar->sendIdentityPacket();
Application::getInstance()->bumpSettings();
}
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
myAvatar->setLeanScale(ui.leanScaleSpin->value());
myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value());
Application::getInstance()->getVoxels()->setMaxVoxels(ui.maxVoxelsSpin->value());
Application::getInstance()->resizeGL(Application::getInstance()->getGLWidget()->width(),
Application::getInstance()->getGLWidget()->height());
Menu::getInstance()->setFieldOfView(ui.fieldOfViewSpin->value());
Menu::getInstance()->setFaceshiftEyeDeflection(ui.faceshiftEyeDeflectionSider->value() /
(float)ui.faceshiftEyeDeflectionSider->maximum());
Menu::getInstance()->setMaxVoxelPacketsPerSecond(ui.maxVoxelsPPSSpin->value());
Menu::getInstance()->setAudioJitterBufferSamples(ui.audioJitterSpin->value());
Application::getInstance()->resizeGL(Application::getInstance()->getGLWidget()->width(),
Application::getInstance()->getGLWidget()->height());
}

View file

@ -0,0 +1,47 @@
//
// PreferencesDialog.h
// interface/src/ui
//
// Created by Stojce Slavkovski on 2/20/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_PreferencesDialog_h
#define hifi_PreferencesDialog_h
#include "FramelessDialog.h"
#include "ui_preferencesDialog.h"
#include <QString>
class PreferencesDialog : public FramelessDialog {
Q_OBJECT
public:
PreferencesDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0);
protected:
void resizeEvent(QResizeEvent* resizeEvent);
private:
void loadPreferences();
void savePreferences();
void openHeadModelBrowser();
void openBodyModelBrowser();
Ui_PreferencesDialog ui;
QString _faceURLString;
QString _skeletonURLString;
QString _displayNameString;
private slots:
void accept();
void setHeadUrl(QString modelUrl);
void setSkeletonUrl(QString modelUrl);
};
#endif // hifi_PreferencesDialog_h

View file

@ -20,7 +20,7 @@
<string notr="true">font-family: Helvetica, Arial, sans-serif;</string>
</property>
<property name="features">
<set>QDockWidget::NoDockWidgetFeatures</set>
<set>QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
</property>
<property name="allowedAreas">
<set>Qt::NoDockWidgetArea</set>
@ -79,6 +79,45 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="togglePinnedButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/images/pin.svg</normaloff>
<normalon>:/images/pinned.svg</normalon>:/images/pin.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="sizePolicy">
@ -204,6 +243,22 @@
<include location="../resources/resources.qrc"/>
</resources>
<connections>
<connection>
<sender>togglePinnedButton</sender>
<signal>clicked()</signal>
<receiver>ChatWindow</receiver>
<slot>togglePinned()</slot>
<hints>
<hint type="sourcelabel">
<x>390</x>
<y>42</y>
</hint>
<hint type="destinationlabel">
<x>550</x>
<y>42</y>
</hint>
</hints>
</connection>
<connection>
<sender>closeButton</sender>
<signal>clicked()</signal>

File diff suppressed because it is too large Load diff

View file

@ -95,8 +95,9 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL,
QUrl url(scriptURL);
// if the scheme is empty, maybe they typed in a file, let's try
if (url.scheme().isEmpty()) {
// if the scheme length is one or lower, maybe they typed in a file, let's try
const int WINDOWS_DRIVE_LETTER_SIZE = 1;
if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
url = QUrl::fromLocalFile(scriptURLString);
}

View file

@ -116,7 +116,6 @@ private:
static VoxelsScriptingInterface _voxelsScriptingInterface;
static ParticlesScriptingInterface _particlesScriptingInterface;
static int _scriptNumber;
AbstractControllerScriptingInterface* _controllerScriptingInterface;
AudioScriptingInterface _audioScriptingInterface;

View file

@ -0,0 +1,36 @@
//
// PlaneShape.cpp
// libraries/shared/src
//
// Created by Andrzej Kapolka on 4/10/2014.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "PlaneShape.h"
#include "SharedUtil.h"
const glm::vec3 UNROTATED_NORMAL(0.0f, 1.0f, 0.0f);
PlaneShape::PlaneShape(const glm::vec4& coefficients) :
Shape(Shape::PLANE_SHAPE) {
glm::vec3 normal = glm::vec3(coefficients);
_position = -normal * coefficients.w;
float angle = acosf(glm::dot(normal, UNROTATED_NORMAL));
if (angle > EPSILON) {
if (angle > PI - EPSILON) {
_rotation = glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f));
} else {
_rotation = glm::angleAxis(angle, glm::normalize(glm::cross(UNROTATED_NORMAL, normal)));
}
}
}
glm::vec4 PlaneShape::getCoefficients() const {
glm::vec3 normal = _rotation * UNROTATED_NORMAL;
return glm::vec4(normal.x, normal.y, normal.z, -glm::dot(normal, _position));
}

View file

@ -0,0 +1,24 @@
//
// PlaneShape.h
// libraries/shared/src
//
// Created by Andrzej Kapolka on 4/9/2014.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_PlaneShape_h
#define hifi_PlaneShape_h
#include "Shape.h"
class PlaneShape : public Shape {
public:
PlaneShape(const glm::vec4& coefficients = glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
glm::vec4 getCoefficients() const;
};
#endif // hifi_PlaneShape_h

View file

@ -22,6 +22,7 @@ public:
UNKNOWN_SHAPE = 0,
SPHERE_SHAPE,
CAPSULE_SHAPE,
PLANE_SHAPE,
BOX_SHAPE,
LIST_SHAPE
};

View file

@ -13,6 +13,7 @@
#include <glm/gtx/norm.hpp>
#include "GeometryUtil.h"
#include "ShapeCollider.h"
// NOTE:
@ -22,7 +23,7 @@
namespace ShapeCollider {
bool shapeShape(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) {
bool collideShapes(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) {
// ATM we only have two shape types so we just check every case.
// TODO: make a fast lookup for correct method
int typeA = shapeA->getType();
@ -33,6 +34,8 @@ bool shapeShape(const Shape* shapeA, const Shape* shapeB, CollisionList& collisi
return sphereSphere(sphereA, static_cast<const SphereShape*>(shapeB), collisions);
} else if (typeB == Shape::CAPSULE_SHAPE) {
return sphereCapsule(sphereA, static_cast<const CapsuleShape*>(shapeB), collisions);
} else if (typeB == Shape::PLANE_SHAPE) {
return spherePlane(sphereA, static_cast<const PlaneShape*>(shapeB), collisions);
}
} else if (typeA == Shape::CAPSULE_SHAPE) {
const CapsuleShape* capsuleA = static_cast<const CapsuleShape*>(shapeA);
@ -40,6 +43,17 @@ bool shapeShape(const Shape* shapeA, const Shape* shapeB, CollisionList& collisi
return capsuleSphere(capsuleA, static_cast<const SphereShape*>(shapeB), collisions);
} else if (typeB == Shape::CAPSULE_SHAPE) {
return capsuleCapsule(capsuleA, static_cast<const CapsuleShape*>(shapeB), collisions);
} else if (typeB == Shape::PLANE_SHAPE) {
return capsulePlane(capsuleA, static_cast<const PlaneShape*>(shapeB), collisions);
}
} else if (typeA == Shape::PLANE_SHAPE) {
const PlaneShape* planeA = static_cast<const PlaneShape*>(shapeA);
if (typeB == Shape::SPHERE_SHAPE) {
return planeSphere(planeA, static_cast<const SphereShape*>(shapeB), collisions);
} else if (typeB == Shape::CAPSULE_SHAPE) {
return planeCapsule(planeA, static_cast<const CapsuleShape*>(shapeB), collisions);
} else if (typeB == Shape::PLANE_SHAPE) {
return planePlane(planeA, static_cast<const PlaneShape*>(shapeB), collisions);
}
} else if (typeA == Shape::LIST_SHAPE) {
const ListShape* listA = static_cast<const ListShape*>(shapeA);
@ -47,11 +61,37 @@ bool shapeShape(const Shape* shapeA, const Shape* shapeB, CollisionList& collisi
return listSphere(listA, static_cast<const SphereShape*>(shapeB), collisions);
} else if (typeB == Shape::CAPSULE_SHAPE) {
return listCapsule(listA, static_cast<const CapsuleShape*>(shapeB), collisions);
} else if (typeB == Shape::PLANE_SHAPE) {
return listPlane(listA, static_cast<const PlaneShape*>(shapeB), collisions);
}
}
return false;
}
static CollisionList tempCollisions(32);
bool collideShapesCoarse(const QVector<const Shape*>& shapesA, const QVector<const Shape*>& shapesB, CollisionInfo& collision) {
tempCollisions.clear();
foreach (const Shape* shapeA, shapesA) {
foreach (const Shape* shapeB, shapesB) {
ShapeCollider::collideShapes(shapeA, shapeB, tempCollisions);
}
}
if (tempCollisions.size() > 0) {
glm::vec3 totalPenetration(0.0f);
glm::vec3 averageContactPoint(0.0f);
for (int j = 0; j < tempCollisions.size(); ++j) {
CollisionInfo* c = tempCollisions.getCollision(j);
totalPenetration = addPenetrations(totalPenetration, c->_penetration);
averageContactPoint += c->_contactPoint;
}
collision._penetration = totalPenetration;
collision._contactPoint = averageContactPoint / (float)(tempCollisions.size());
return true;
}
return false;
}
bool sphereSphere(const SphereShape* sphereA, const SphereShape* sphereB, CollisionList& collisions) {
glm::vec3 BA = sphereB->getPosition() - sphereA->getPosition();
float distanceSquared = glm::dot(BA, BA);
@ -61,7 +101,7 @@ bool sphereSphere(const SphereShape* sphereA, const SphereShape* sphereB, Collis
float distance = sqrtf(distanceSquared);
if (distance < EPSILON) {
// the spheres are on top of each other, so we pick an arbitrary penetration direction
BA = glm::vec3(0.f, 1.f, 0.f);
BA = glm::vec3(0.0f, 1.0f, 0.0f);
distance = totalRadius;
} else {
BA /= distance;
@ -96,7 +136,7 @@ bool sphereCapsule(const SphereShape* sphereA, const CapsuleShape* capsuleB, Col
}
if (absAxialDistance > capsuleB->getHalfHeight()) {
// sphere hits capsule on a cap --> recompute radialAxis to point from spherA to cap center
float sign = (axialDistance > 0.f) ? 1.f : -1.f;
float sign = (axialDistance > 0.0f) ? 1.0f : -1.0f;
radialAxis = BA + (sign * capsuleB->getHalfHeight()) * capsuleAxis;
radialDistance2 = glm::length2(radialAxis);
if (radialDistance2 > totalRadius2) {
@ -128,12 +168,12 @@ bool sphereCapsule(const SphereShape* sphereA, const CapsuleShape* capsuleB, Col
return false;
}
// ... but still defined for the cap case
if (axialDistance < 0.f) {
if (axialDistance < 0.0f) {
// we're hitting the start cap, so we negate the capsuleAxis
capsuleAxis *= -1;
}
// penetration points from A into B
float sign = (axialDistance > 0.f) ? -1.f : 1.f;
float sign = (axialDistance > 0.0f) ? -1.0f : 1.0f;
collision->_penetration = (sign * (totalRadius + capsuleB->getHalfHeight() - absAxialDistance)) * capsuleAxis;
// contactPoint is on surface of sphereA
collision->_contactPoint = sphereA->getPosition() + (sign * sphereA->getRadius()) * capsuleAxis;
@ -143,6 +183,20 @@ bool sphereCapsule(const SphereShape* sphereA, const CapsuleShape* capsuleB, Col
return false;
}
bool spherePlane(const SphereShape* sphereA, const PlaneShape* planeB, CollisionList& collisions) {
glm::vec3 penetration;
if (findSpherePlanePenetration(sphereA->getPosition(), sphereA->getRadius(), planeB->getCoefficients(), penetration)) {
CollisionInfo* collision = collisions.getNewCollision();
if (!collision) {
return false; // collision list is full
}
collision->_penetration = penetration;
collision->_contactPoint = sphereA->getPosition() + sphereA->getRadius() * glm::normalize(penetration);
return true;
}
return false;
}
bool capsuleSphere(const CapsuleShape* capsuleA, const SphereShape* sphereB, CollisionList& collisions) {
// find sphereB's closest approach to axis of capsuleA
glm::vec3 AB = capsuleA->getPosition() - sphereB->getPosition();
@ -166,7 +220,7 @@ bool capsuleSphere(const CapsuleShape* capsuleA, const SphereShape* sphereB, Col
if (absAxialDistance > capsuleA->getHalfHeight()) {
// sphere hits capsule on a cap
// --> recompute radialAxis and closestApproach
float sign = (axialDistance > 0.f) ? 1.f : -1.f;
float sign = (axialDistance > 0.0f) ? 1.0f : -1.0f;
closestApproach = capsuleA->getPosition() + (sign * capsuleA->getHalfHeight()) * capsuleAxis;
radialAxis = closestApproach - sphereB->getPosition();
radialDistance2 = glm::length2(radialAxis);
@ -199,11 +253,11 @@ bool capsuleSphere(const CapsuleShape* capsuleA, const SphereShape* sphereB, Col
return false;
}
// ... but still defined for the cap case
if (axialDistance < 0.f) {
if (axialDistance < 0.0f) {
// we're hitting the start cap, so we negate the capsuleAxis
capsuleAxis *= -1;
}
float sign = (axialDistance > 0.f) ? 1.f : -1.f;
float sign = (axialDistance > 0.0f) ? 1.0f : -1.0f;
collision->_penetration = (sign * (totalRadius + capsuleA->getHalfHeight() - absAxialDistance)) * capsuleAxis;
// contactPoint is on surface of sphereA
collision->_contactPoint = closestApproach + (sign * capsuleA->getRadius()) * capsuleAxis;
@ -226,7 +280,7 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB,
// d = [(B - A) . (a - (a.b)b)] / (1 - (a.b)^2)
float aDotB = glm::dot(axisA, axisB);
float denominator = 1.f - aDotB * aDotB;
float denominator = 1.0f - aDotB * aDotB;
float totalRadius = capsuleA->getRadius() + capsuleB->getRadius();
if (denominator > EPSILON) {
// distances to points of closest approach
@ -236,12 +290,12 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB,
// clamp the distances to the ends of the capsule line segments
float absDistanceA = fabs(distanceA);
if (absDistanceA > capsuleA->getHalfHeight() + capsuleA->getRadius()) {
float signA = distanceA < 0.f ? -1.f : 1.f;
float signA = distanceA < 0.0f ? -1.0f : 1.0f;
distanceA = signA * capsuleA->getHalfHeight();
}
float absDistanceB = fabs(distanceB);
if (absDistanceB > capsuleB->getHalfHeight() + capsuleB->getRadius()) {
float signB = distanceB < 0.f ? -1.f : 1.f;
float signB = distanceB < 0.0f ? -1.0f : 1.0f;
distanceB = signB * capsuleB->getHalfHeight();
}
@ -268,7 +322,7 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB,
{
// the capsule centers are on top of each other!
// give up on a valid penetration direction and just use the yAxis
BA = glm::vec3(0.f, 1.f, 0.f);
BA = glm::vec3(0.0f, 1.0f, 0.0f);
distance = glm::max(capsuleB->getRadius(), capsuleA->getRadius());
}
} else {
@ -300,7 +354,7 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB,
float distance = sqrtf(distanceSquared);
if (distance < EPSILON) {
// the spheres are on top of each other, so we pick an arbitrary penetration direction
BA = glm::vec3(0.f, 1.f, 0.f);
BA = glm::vec3(0.0f, 1.0f, 0.0f);
} else {
BA /= distance;
}
@ -349,6 +403,63 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB,
return false;
}
bool capsulePlane(const CapsuleShape* capsuleA, const PlaneShape* planeB, CollisionList& collisions) {
glm::vec3 start, end, penetration;
capsuleA->getStartPoint(start);
capsuleA->getEndPoint(end);
glm::vec4 plane = planeB->getCoefficients();
if (findCapsulePlanePenetration(start, end, capsuleA->getRadius(), plane, penetration)) {
CollisionInfo* collision = collisions.getNewCollision();
if (!collision) {
return false; // collision list is full
}
collision->_penetration = penetration;
glm::vec3 deepestEnd = (glm::dot(start, glm::vec3(plane)) < glm::dot(end, glm::vec3(plane))) ? start : end;
collision->_contactPoint = deepestEnd + capsuleA->getRadius() * glm::normalize(penetration);
return true;
}
return false;
}
bool planeSphere(const PlaneShape* planeA, const SphereShape* sphereB, CollisionList& collisions) {
glm::vec3 penetration;
if (findSpherePlanePenetration(sphereB->getPosition(), sphereB->getRadius(), planeA->getCoefficients(), penetration)) {
CollisionInfo* collision = collisions.getNewCollision();
if (!collision) {
return false; // collision list is full
}
collision->_penetration = -penetration;
collision->_contactPoint = sphereB->getPosition() +
(sphereB->getRadius() / glm::length(penetration) - 1.0f) * penetration;
return true;
}
return false;
}
bool planeCapsule(const PlaneShape* planeA, const CapsuleShape* capsuleB, CollisionList& collisions) {
glm::vec3 start, end, penetration;
capsuleB->getStartPoint(start);
capsuleB->getEndPoint(end);
glm::vec4 plane = planeA->getCoefficients();
if (findCapsulePlanePenetration(start, end, capsuleB->getRadius(), plane, penetration)) {
CollisionInfo* collision = collisions.getNewCollision();
if (!collision) {
return false; // collision list is full
}
collision->_penetration = -penetration;
glm::vec3 deepestEnd = (glm::dot(start, glm::vec3(plane)) < glm::dot(end, glm::vec3(plane))) ? start : end;
collision->_contactPoint = deepestEnd + (capsuleB->getRadius() / glm::length(penetration) - 1.0f) * penetration;
return true;
}
return false;
}
bool planePlane(const PlaneShape* planeA, const PlaneShape* planeB, CollisionList& collisions) {
// technically, planes always collide unless they're parallel and not coincident; however, that's
// not going to give us any useful information
return false;
}
bool sphereList(const SphereShape* sphereA, const ListShape* listB, CollisionList& collisions) {
bool touching = false;
for (int i = 0; i < listB->size() && !collisions.isFull(); ++i) {
@ -358,6 +469,8 @@ bool sphereList(const SphereShape* sphereA, const ListShape* listB, CollisionLis
touching = sphereSphere(sphereA, static_cast<const SphereShape*>(subShape), collisions) || touching;
} else if (subType == Shape::CAPSULE_SHAPE) {
touching = sphereCapsule(sphereA, static_cast<const CapsuleShape*>(subShape), collisions) || touching;
} else if (subType == Shape::PLANE_SHAPE) {
touching = spherePlane(sphereA, static_cast<const PlaneShape*>(subShape), collisions) || touching;
}
}
return touching;
@ -372,6 +485,24 @@ bool capsuleList(const CapsuleShape* capsuleA, const ListShape* listB, Collision
touching = capsuleSphere(capsuleA, static_cast<const SphereShape*>(subShape), collisions) || touching;
} else if (subType == Shape::CAPSULE_SHAPE) {
touching = capsuleCapsule(capsuleA, static_cast<const CapsuleShape*>(subShape), collisions) || touching;
} else if (subType == Shape::PLANE_SHAPE) {
touching = capsulePlane(capsuleA, static_cast<const PlaneShape*>(subShape), collisions) || touching;
}
}
return touching;
}
bool planeList(const PlaneShape* planeA, const ListShape* listB, CollisionList& collisions) {
bool touching = false;
for (int i = 0; i < listB->size() && !collisions.isFull(); ++i) {
const Shape* subShape = listB->getSubShape(i);
int subType = subShape->getType();
if (subType == Shape::SPHERE_SHAPE) {
touching = planeSphere(planeA, static_cast<const SphereShape*>(subShape), collisions) || touching;
} else if (subType == Shape::CAPSULE_SHAPE) {
touching = planeCapsule(planeA, static_cast<const CapsuleShape*>(subShape), collisions) || touching;
} else if (subType == Shape::PLANE_SHAPE) {
touching = planePlane(planeA, static_cast<const PlaneShape*>(subShape), collisions) || touching;
}
}
return touching;
@ -386,6 +517,8 @@ bool listSphere(const ListShape* listA, const SphereShape* sphereB, CollisionLis
touching = sphereSphere(static_cast<const SphereShape*>(subShape), sphereB, collisions) || touching;
} else if (subType == Shape::CAPSULE_SHAPE) {
touching = capsuleSphere(static_cast<const CapsuleShape*>(subShape), sphereB, collisions) || touching;
} else if (subType == Shape::PLANE_SHAPE) {
touching = planeSphere(static_cast<const PlaneShape*>(subShape), sphereB, collisions) || touching;
}
}
return touching;
@ -400,6 +533,24 @@ bool listCapsule(const ListShape* listA, const CapsuleShape* capsuleB, Collision
touching = sphereCapsule(static_cast<const SphereShape*>(subShape), capsuleB, collisions) || touching;
} else if (subType == Shape::CAPSULE_SHAPE) {
touching = capsuleCapsule(static_cast<const CapsuleShape*>(subShape), capsuleB, collisions) || touching;
} else if (subType == Shape::PLANE_SHAPE) {
touching = planeCapsule(static_cast<const PlaneShape*>(subShape), capsuleB, collisions) || touching;
}
}
return touching;
}
bool listPlane(const ListShape* listA, const PlaneShape* planeB, CollisionList& collisions) {
bool touching = false;
for (int i = 0; i < listA->size() && !collisions.isFull(); ++i) {
const Shape* subShape = listA->getSubShape(i);
int subType = subShape->getType();
if (subType == Shape::SPHERE_SHAPE) {
touching = spherePlane(static_cast<const SphereShape*>(subShape), planeB, collisions) || touching;
} else if (subType == Shape::CAPSULE_SHAPE) {
touching = capsulePlane(static_cast<const CapsuleShape*>(subShape), planeB, collisions) || touching;
} else if (subType == Shape::PLANE_SHAPE) {
touching = planePlane(static_cast<const PlaneShape*>(subShape), planeB, collisions) || touching;
}
}
return touching;
@ -410,7 +561,7 @@ bool listList(const ListShape* listA, const ListShape* listB, CollisionList& col
for (int i = 0; i < listA->size() && !collisions.isFull(); ++i) {
const Shape* subShape = listA->getSubShape(i);
for (int j = 0; j < listB->size() && !collisions.isFull(); ++j) {
touching = shapeShape(subShape, listB->getSubShape(j), collisions) || touching;
touching = collideShapes(subShape, listB->getSubShape(j), collisions) || touching;
}
}
return touching;

View file

@ -15,6 +15,7 @@
#include "CapsuleShape.h"
#include "CollisionInfo.h"
#include "ListShape.h"
#include "PlaneShape.h"
#include "SharedUtil.h"
#include "SphereShape.h"
@ -22,9 +23,15 @@ namespace ShapeCollider {
/// \param shapeA pointer to first shape
/// \param shapeB pointer to second shape
/// \param[out] collisions where to append collision details
/// \param collisions[out] collision details
/// \return true if shapes collide
bool shapeShape(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions);
bool collideShapes(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions);
/// \param shapesA list of shapes
/// \param shapeB list of shapes
/// \param collisions[out] average collision details
/// \return true if any shapes collide
bool collideShapesCoarse(const QVector<const Shape*>& shapesA, const QVector<const Shape*>& shapesB, CollisionInfo& collision);
/// \param sphereA pointer to first shape
/// \param sphereB pointer to second shape
@ -38,6 +45,12 @@ namespace ShapeCollider {
/// \return true if shapes collide
bool sphereCapsule(const SphereShape* sphereA, const CapsuleShape* capsuleB, CollisionList& collisions);
/// \param sphereA pointer to first shape
/// \param planeB pointer to second shape
/// \param[out] collisions where to append collision details
/// \return true if shapes collide
bool spherePlane(const SphereShape* sphereA, const PlaneShape* planeB, CollisionList& collisions);
/// \param capsuleA pointer to first shape
/// \param sphereB pointer to second shape
/// \param[out] collisions where to append collision details
@ -50,6 +63,30 @@ namespace ShapeCollider {
/// \return true if shapes collide
bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB, CollisionList& collisions);
/// \param capsuleA pointer to first shape
/// \param planeB pointer to second shape
/// \param[out] collisions where to append collision details
/// \return true if shapes collide
bool capsulePlane(const CapsuleShape* capsuleA, const PlaneShape* planeB, CollisionList& collisions);
/// \param planeA pointer to first shape
/// \param sphereB pointer to second shape
/// \param[out] collisions where to append collision details
/// \return true if shapes collide
bool planeSphere(const PlaneShape* planeA, const SphereShape* sphereB, CollisionList& collisions);
/// \param planeA pointer to first shape
/// \param capsuleB pointer to second shape
/// \param[out] collisions where to append collision details
/// \return true if shapes collide
bool planeCapsule(const PlaneShape* planeA, const CapsuleShape* capsuleB, CollisionList& collisions);
/// \param planeA pointer to first shape
/// \param planeB pointer to second shape
/// \param[out] collisions where to append collision details
/// \return true if shapes collide
bool planePlane(const PlaneShape* planeA, const PlaneShape* planeB, CollisionList& collisions);
/// \param sphereA pointer to first shape
/// \param listB pointer to second shape
/// \param[out] collisions where to append collision details
@ -62,6 +99,12 @@ namespace ShapeCollider {
/// \return true if shapes collide
bool capsuleList(const CapsuleShape* capsuleA, const ListShape* listB, CollisionList& collisions);
/// \param planeA pointer to first shape
/// \param listB pointer to second shape
/// \param[out] collisions where to append collision details
/// \return true if shapes collide
bool planeList(const PlaneShape* planeA, const ListShape* listB, CollisionList& collisions);
/// \param listA pointer to first shape
/// \param sphereB pointer to second shape
/// \param[out] collisions where to append collision details
@ -74,6 +117,12 @@ namespace ShapeCollider {
/// \return true if shapes collide
bool listCapsule(const ListShape* listA, const CapsuleShape* capsuleB, CollisionList& collisions);
/// \param listA pointer to first shape
/// \param planeB pointer to second shape
/// \param[out] collisions where to append collision details
/// \return true if shapes collide
bool listPlane(const ListShape* listA, const PlaneShape* planeB, CollisionList& collisions);
/// \param listA pointer to first shape
/// \param capsuleB pointer to second shape
/// \param[out] collisions where to append collision details

View file

@ -43,7 +43,7 @@ void ShapeColliderTests::sphereMissesSphere() {
// collide A to B...
{
bool touching = ShapeCollider::shapeShape(&sphereA, &sphereB, collisions);
bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions);
if (touching) {
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphereA and sphereB should NOT touch" << std::endl;
@ -52,7 +52,7 @@ void ShapeColliderTests::sphereMissesSphere() {
// collide B to A...
{
bool touching = ShapeCollider::shapeShape(&sphereB, &sphereA, collisions);
bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions);
if (touching) {
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphereA and sphereB should NOT touch" << std::endl;
@ -61,7 +61,7 @@ void ShapeColliderTests::sphereMissesSphere() {
// also test shapeShape
{
bool touching = ShapeCollider::shapeShape(&sphereB, &sphereA, collisions);
bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions);
if (touching) {
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphereA and sphereB should NOT touch" << std::endl;
@ -93,7 +93,7 @@ void ShapeColliderTests::sphereTouchesSphere() {
// collide A to B...
{
bool touching = ShapeCollider::shapeShape(&sphereA, &sphereB, collisions);
bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions);
if (!touching) {
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphereA and sphereB should touch" << std::endl;
@ -136,7 +136,7 @@ void ShapeColliderTests::sphereTouchesSphere() {
// collide B to A...
{
bool touching = ShapeCollider::shapeShape(&sphereB, &sphereA, collisions);
bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions);
if (!touching) {
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphereA and sphereB should touch" << std::endl;
@ -199,7 +199,7 @@ void ShapeColliderTests::sphereMissesCapsule() {
sphereA.setPosition(rotation * localPosition + translation);
// sphereA agains capsuleB
if (ShapeCollider::shapeShape(&sphereA, &capsuleB, collisions))
if (ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphere and capsule should NOT touch"
@ -207,7 +207,7 @@ void ShapeColliderTests::sphereMissesCapsule() {
}
// capsuleB against sphereA
if (ShapeCollider::shapeShape(&capsuleB, &sphereA, collisions))
if (ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphere and capsule should NOT touch"
@ -241,7 +241,7 @@ void ShapeColliderTests::sphereTouchesCapsule() {
{ // sphereA collides with capsuleB's cylindrical wall
sphereA.setPosition(radialOffset * xAxis);
if (!ShapeCollider::shapeShape(&sphereA, &capsuleB, collisions))
if (!ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphere and capsule should touch"
@ -272,7 +272,7 @@ void ShapeColliderTests::sphereTouchesCapsule() {
}
// capsuleB collides with sphereA
if (!ShapeCollider::shapeShape(&capsuleB, &sphereA, collisions))
if (!ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and sphere should touch"
@ -308,7 +308,7 @@ void ShapeColliderTests::sphereTouchesCapsule() {
glm::vec3 axialOffset = (halfHeightB + alpha * radiusA + beta * radiusB) * yAxis;
sphereA.setPosition(axialOffset * yAxis);
if (!ShapeCollider::shapeShape(&sphereA, &capsuleB, collisions))
if (!ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphere and capsule should touch"
@ -339,7 +339,7 @@ void ShapeColliderTests::sphereTouchesCapsule() {
}
// capsuleB collides with sphereA
if (!ShapeCollider::shapeShape(&capsuleB, &sphereA, collisions))
if (!ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and sphere should touch"
@ -375,7 +375,7 @@ void ShapeColliderTests::sphereTouchesCapsule() {
glm::vec3 axialOffset = - (halfHeightB + alpha * radiusA + beta * radiusB) * yAxis;
sphereA.setPosition(axialOffset * yAxis);
if (!ShapeCollider::shapeShape(&sphereA, &capsuleB, collisions))
if (!ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: sphere and capsule should touch"
@ -406,7 +406,7 @@ void ShapeColliderTests::sphereTouchesCapsule() {
}
// capsuleB collides with sphereA
if (!ShapeCollider::shapeShape(&capsuleB, &sphereA, collisions))
if (!ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and sphere should touch"
@ -462,13 +462,13 @@ void ShapeColliderTests::capsuleMissesCapsule() {
// side by side
capsuleB.setPosition((1.01f * totalRadius) * xAxis);
if (ShapeCollider::shapeShape(&capsuleA, &capsuleB, collisions))
if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should NOT touch"
<< std::endl;
}
if (ShapeCollider::shapeShape(&capsuleB, &capsuleA, collisions))
if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should NOT touch"
@ -477,13 +477,13 @@ void ShapeColliderTests::capsuleMissesCapsule() {
// end to end
capsuleB.setPosition((1.01f * totalHalfLength) * xAxis);
if (ShapeCollider::shapeShape(&capsuleA, &capsuleB, collisions))
if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should NOT touch"
<< std::endl;
}
if (ShapeCollider::shapeShape(&capsuleB, &capsuleA, collisions))
if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should NOT touch"
@ -494,13 +494,13 @@ void ShapeColliderTests::capsuleMissesCapsule() {
glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis);
capsuleB.setRotation(rotation);
capsuleB.setPosition((1.01f * (totalRadius + capsuleB.getHalfHeight())) * xAxis);
if (ShapeCollider::shapeShape(&capsuleA, &capsuleB, collisions))
if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should NOT touch"
<< std::endl;
}
if (ShapeCollider::shapeShape(&capsuleB, &capsuleA, collisions))
if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should NOT touch"
@ -532,7 +532,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
{ // side by side
capsuleB.setPosition((0.99f * totalRadius) * xAxis);
if (!ShapeCollider::shapeShape(&capsuleA, &capsuleB, collisions))
if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"
@ -540,7 +540,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
} else {
++numCollisions;
}
if (!ShapeCollider::shapeShape(&capsuleB, &capsuleA, collisions))
if (!ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"
@ -553,7 +553,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
{ // end to end
capsuleB.setPosition((0.99f * totalHalfLength) * yAxis);
if (!ShapeCollider::shapeShape(&capsuleA, &capsuleB, collisions))
if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"
@ -561,7 +561,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
} else {
++numCollisions;
}
if (!ShapeCollider::shapeShape(&capsuleB, &capsuleA, collisions))
if (!ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"
@ -576,7 +576,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
capsuleB.setRotation(rotation);
capsuleB.setPosition((0.99f * (totalRadius + capsuleB.getHalfHeight())) * xAxis);
if (!ShapeCollider::shapeShape(&capsuleA, &capsuleB, collisions))
if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"
@ -584,7 +584,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
} else {
++numCollisions;
}
if (!ShapeCollider::shapeShape(&capsuleB, &capsuleA, collisions))
if (!ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"
@ -602,7 +602,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
capsuleB.setPosition(positionB);
// capsuleA vs capsuleB
if (!ShapeCollider::shapeShape(&capsuleA, &capsuleB, collisions))
if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"
@ -631,7 +631,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
}
// capsuleB vs capsuleA
if (!ShapeCollider::shapeShape(&capsuleB, &capsuleA, collisions))
if (!ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"
@ -669,7 +669,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() {
capsuleB.setPosition(positionB);
// capsuleA vs capsuleB
if (!ShapeCollider::shapeShape(&capsuleA, &capsuleB, collisions))
if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions))
{
std::cout << __FILE__ << ":" << __LINE__
<< " ERROR: capsule and capsule should touch"