Название: ColladaImport и DetecMouseCollision Отправлено: Deepl от 13 Сентября 2010, 15:22:35 Добре, Уважаемые.
Подскажите как заставить вставленный с помощью ColladaImport объект работать с DetecMouseCollision. Буду чрезвычайно благодарен! Название: Re: ColladaImport и DetecMouseCollision Отправлено: Deepl от 16 Сентября 2010, 19:17:48 Неужели у местных Гуру нет никаких идей??
Название: Re: ColladaImport и DetecMouseCollision Отправлено: Deepl от 28 Сентября 2010, 20:09:35 Ну, что же. Я решил проблему. Судя по количеству просмотров и количеству ответов - всем интересно и никто не знает. Если надо - могу приблизительно написать как, что и куда. не знаю насколько академически правильно, но это работает.
Название: Re: ColladaImport и DetecMouseCollision Отправлено: DimiS от 29 Сентября 2010, 10:10:02 наливай ;)
Название: Re: ColladaImport и DetecMouseCollision Отправлено: Deepl от 29 Сентября 2010, 15:53:11 Итак, как же заставить работать DetectMouseCollision, который работает с 3D Object(и только с ним), когда у нас есть разрозненный пакет данных, полученный в результате работы ColladaImport? В принципе, ответ я уже написал. Надо сделать из полученных данных 3D Object. Все проще пареной репы, приступим.
Работать будем с ОО системой квеста. Теперь по пунктам с картинками: 1. Изучим, что же мы получаем благодаря ColladaImport: У нас три класса: a. cImportObject b. cImportSurface c. cImportTexture в а. формально хранится вся информация, необходимая для создания объекта: - ImportObject (так и не понял что в нем хранится, но обошелся и без него) - MotionSet(грубо говоря, это список матриц объекта. используется если объект анимирован. Я не пользовался, т.к. объекты у меня без анимации) - Normalized Matrix(матрица объекта. Положение, ориентация и масштаб объекта в пространстве. Грубо говоря тот самый Motion). - Surfaces(Интересная штука. Это OO_Container. Т.е. такая штука, которая содержит множество ОО_Instances. Другими словами, это такой массив в котором содержаться... Внимание!.. ...объекты класса cImportSurface! В b. Формально хранится вся инфа для создания поверхности: - Diffuse(Цвет диффуза) - Emissive(цвет самосвечения) - Object Data(собственно инфа о вершинах) - Specular(блеск) - SpecularPower(сила блеска) - TextureList(опять же СПИСОК! ClassInstanceContainer объектов класса сImportTexture) В c. Тут хранится вся информация, необходимая для создания ноды Texture. - Texture Таким образом получается следующая иерархия: cImportObject -> cImportSurface -> cImportTexture Я намеренно упустил из описания класса cImportSurface один пункт - функцию Draw. Эта функция прорисовывает все поверхности, используя матрицу объекта, получая ее из внешнего параметра-матрицы World. А теперь давайте посмотрим какие входы есть у ноды 3D Object: - Matrix (Положение, ориентация и масштаб объекта в пространстве. Грубо говоря тот самый Motion. Обязательная нода) - Offset Matrix(Дополнительная матрица, которая накладывает свое действие на основную. Другими словами таким образом можно "Припарентить" объект к другому. Не обязательна) - Surface(Данные о поверхности. Нода множественная и обязательная. Сюда подключается информация о всех поверхностях, составляющих объект) - Draw object (рисует объект или нет) Таким образом для создания объекта нам необходимы всего два входа: Matrix и Surface. Matrix у нас есть. Нет ноды Surface. Зато есть данные для создания этого сюрфейса. Ну, так вперед! В интерфейсе iImportSurface Содаем новую функцию MakeSurface типа Channel->Surface: www.avdeevk.ru/3qdLess/001.jpg (http://www.avdeevk.ru/3qdLess/001.jpg) http://www.avdeevk.ru/3qdLess/002.jpg (http://www.avdeevk.ru/3qdLess/002.jpg) http://www.avdeevk.ru/3qdLess/003.jpg (http://www.avdeevk.ru/3qdLess/003.jpg) Убеждаемся что все точно как у меня. http://www.avdeevk.ru/3qdLess/004.jpg (http://www.avdeevk.ru/3qdLess/004.jpg) Обратите внимание что в поле Target стоит Target not found! Это означает, что у этой функции есть объявление, но нету исполняемой части. Теперь эту часть и надо сделать. Нажмите кнопку F2 на клаве, переведя Quest в режим Dual ChannelGraph. В верхней части выберите OO Editor, в нижней группу OO 3D Object Template. И просто перетащите функцию MakeSurface сверху из OO Editor'a в ChannelGraph внизу. Получите следующее: http://www.avdeevk.ru/3qdLess/005.jpg (http://www.avdeevk.ru/3qdLess/005.jpg) Сверху нода Surface, а снизу указатель на то от какого элемента класса надо брать параметры diffuse, emissive и т.д. Вы же помните, что поверхностей в объекте может быть много, следовательно у каждой из них будут свои параметры. Именно для этого и служит нода THIS. Теперь надо перетащить в ChannelGraph необходимые параметры. Делается это следующим образом. Откройте закладку ProjectTree. Раскройте папку Include, в ней раскройте группу OO 3D Object Template. Внутри которой раскройте класс cImportSurface и увидите все параметры и функции, присутствующие в этом классе. http://www.avdeevk.ru/3qdLess/006.jpg (http://www.avdeevk.ru/3qdLess/006.jpg) http://www.avdeevk.ru/3qdLess/007.jpg (http://www.avdeevk.ru/3qdLess/007.jpg) Перетащите из этого списка в ChannelGraph следующие параметры: - Diffuse - Emissive - Specular - SpecularPower - ObjectData TextureList перетаскивать не надо, т.к. для коллизии с мышью нас текстуры мало интересуют. Получите следующий набор: http://www.avdeevk.ru/3qdLess/008.jpg (http://www.avdeevk.ru/3qdLess/008.jpg) Важный момент: у каждого из параметров снизу есть вход под названием OOClassInstance. Сюда надо подключить нашу ноду THIS, указывающую на то, параметры какого представителя класса(в данном случае поверхности) нас интересуют. Поэтому присоедините THIS ко всем параметрам: http://www.avdeevk.ru/3qdLess/009.jpg (http://www.avdeevk.ru/3qdLess/009.jpg) Также создайте новую ноду Material, удалите у нее всех Child'ов и подсоедините к ней наши соответствующие параметры: http://www.avdeevk.ru/3qdLess/010.jpg (http://www.avdeevk.ru/3qdLess/010.jpg) а затем к главной ноде подсоедините ноды ObjectData и Material. http://www.avdeevk.ru/3qdLess/011.jpg (http://www.avdeevk.ru/3qdLess/011.jpg) Вот и готова функция создания поверхности. Для проверки DetecMouseCollision создадим функцию CheckMouseCollision. Эта функция будет заниматься только одним: менять значение параметра MouseOver с 0 на 1, если мышь над этим объектом. Первоначальные действия примерно такие же: 1. добавляем в интерфейс iImportObject параметр типа Value с именем MouseOver. 2. добавляем в интерфейс iImportObject функцию CheckMouseCollision, оставляя стандартный ChannelCaller. Назовем ее CheckMouseCollision. http://www.avdeevk.ru/3qdLess/013.jpg (http://www.avdeevk.ru/3qdLess/013.jpg) Перетащим новую функцию в ChannelGraph прямо из этого списка. Нет времени дальше так подробно расписывать. Вот вся функция с описанием блоков: красная рамка: Логика функции. Если есть коллизия -> параметр MouseOver=1, если нет параметр MouseOver=0. Синяя рамка: По идее должен быть цикл. Но цикл работать так и не захотел. Все время выдавал одну поверхность объекта, а не все. Поэтому я забил в проекте 20 таких штук. По идее должно хватить. Зеленая рамка. Решение некой корявости NormilizedMatrix в ColladaImport. т.е. я просто пересоздаю матрицу заново. В своем проекте сделал это при импорте. http://www.avdeevk.ru/3qdLess/014.jpg (http://www.avdeevk.ru/3qdLess/014.jpg) Теперь самое интересное: У меня нода 3D Object соединена с главной нодой. Это дает возможноть увидеть объект для коллизи во вьюпорте. т.е. так как это объект он начинает визуализироваться. Очень удобно для дебага. Теперь как это все вписывается и где вызывается: http://www.avdeevk.ru/3qdLess/015.jpg (http://www.avdeevk.ru/3qdLess/015.jpg) Пояснения: Красная рамка вызов функции. Зеленая рамка: изменеие в алгоритме рендеринга. Вместо матрицы World мы подставляем матрицу NormiliaedMatrix нашего объекта. Все работает. Можно убедиться, запустив прогу и перейдя в группу OO 3D Object Template. А еще лучше сделав функцию HighLight в классе cImportObject Типа Этой: http://www.avdeevk.ru/3qdLess/015.jpg (http://www.avdeevk.ru/3qdLess/015.jpg) В зеленой рамке у меня параметр функции цвета. Если непонятно, можно заменить на ValueVector со значениями RGB. Вот ссылка на проект без Функции HighLight. http://www.avdeevk.ru/3qdLess/less.zip (http://www.avdeevk.ru/3qdLess/less.zip) Спасибо за внимание. Извините, что не расписал полностью - начальник пришел )) Задавайте вопросы. У меня заодно вопрос. Можно ли как-то отследить у FileDialog была нажата кнопка ОК или Отмена? Название: Re: ColladaImport и DetecMouseCollision Отправлено: andkash от 28 Октября 2010, 01:35:10 :o Ух... Даже не думал, что в простейшем действии скрывается такая сложность.
Как раз это мне сейчас и надо было применить. Надо чтоб при наведении мышки всплывало название элемента. Помнится в cult3d это делалось на раз. Я приложил пример файлика: http://narod.ru/disk/26654493000/2.4.3.rar.html (http://narod.ru/disk/26654493000/2.4.3.rar.html) Там всё сделано как надо, за исключением текста, который реагирует на целый объект, а надо, чтоб реагировал каждый элемент отдельно. Можно ли сделать это как-то проще, или надо разбираться с OO? У меня пока получается, что если я использую разложение на отдельные объекты, они у меня накладываются все в кучу. А потом собирать их и выстраивать, чёт как-то не хочется. Посоветуете что-нибудь? Название: Re: ColladaImport и DetecMouseCollision Отправлено: Deepl от 28 Октября 2010, 11:04:20 Да, ничего особо сложного нет, просто пытался расписать наиболее развернуто. Видимо не получилось.
Не совсем понял вашу задачу. У вас при динамической загрузке должно все происходить? Т.е. вы прямо из своего скомпилированного приложения загружаете модель, потом наводите на каждую поерхность и получаете разные подсказки? Потом загружаете другую модель и получаете другие подсказки? Тут да, придется малость попариться и да, без ОО не обойтись. Или у вас модель сначала импортируется в квест? Т.е. динамической загрузки не будет? Если так, то это очень просто. 1. Загружаете модель с несколькими элементами. 2. Подключаете ее к рендеру и т.д. - она начинает отображаться в сцене. 3. На каждый элемент делаете свой 3D Object и подключаете туда матрицу объекта и Surface соответствующего элемента. 4. К каждому объекту подключаете DetectMouseCollision - получается что при наведении на какой-то элемент в соответствующем ему DetectMouseCollision вы получаете 1. 5. Воспользовавшись каналами Trigger или ChannelSwitch спокойно реализуете необходимый функционал. Название: Re: ColladaImport и DetecMouseCollision Отправлено: andkash от 28 Октября 2010, 13:44:30 У меня как в предложеном файлике, без динамической загрузки. Сейчас попытался посоздавать объекты внутри, вроде работает, но как-то странно - если объекты перекрываются друг другом, названия всплывают всех наложенных друг на друга объектов, курсор "видит" их насквозь.
А можно как-то сделать, чтоб название отображалось только у объекта на переднем плане? Название: Re: ColladaImport и DetecMouseCollision Отправлено: Sqwer от 28 Октября 2010, 15:55:50 Есть несколько вариантов решения сей проблемы:
1) определять расстояние от объекта до камеры , и из всех объектов, прошедших тест на пересечения луча (маус дэтекшн) выбирать ближайший к камере (самый простой) 2) делать рендер в текстуру, и по ней определять, цвет(тексель) какого объекта находится под указателем курсора. (потяжелее) 3) это гибрид 1 и 2 методов , сперва находим массив объектов по пункту 1, а затем их отрисовываем , после чего вступает в силу алгоритм 2. Название: Re: ColladaImport и DetecMouseCollision Отправлено: andkash от 28 Октября 2010, 18:21:47 Вот первый вариант видится приемлемым, но, тем не менее не понятным. Чем определять расстояние? Ну и замороченная же прога!
Название: Re: ColladaImport и DetecMouseCollision Отправлено: Sqwer от 28 Октября 2010, 20:01:12 Есть матрица камеры? - есть
Есть матрица объекта? - есть следовательно можно получить мировые координаты в векторной форме как камеры так и объекта команда TranslationMatrix после ничего не состовляет труда узнать расстояние между векторами заносим все значения в массив и сортируем , что ближе - то и выбираем. Название: Re: ColladaImport и DetecMouseCollision Отправлено: andkash от 28 Октября 2010, 20:24:20 Спасибо большое, попробую разобраться.
Название: Re: ColladaImport и DetecMouseCollision Отправлено: Ruslan от 28 Октября 2010, 20:41:15 + есть еще способ:
ValueOperator -> Get distance to camera (matrix)) на вход подаешь матрицу объекта, на выходе получаешь расстояние от объекта до активной камеры. Цитировать Ну и замороченная же прога! нормальная прога!, только вначале разобраться в ней нужно. :PНазвание: Re: ColladaImport и DetecMouseCollision Отправлено: Deepl от 28 Октября 2010, 21:41:48 Вообще, пользоваться матрицами не самый лучший способ.
Представь, что в одной точке находится огромный шар и маленький куб. А еще лучше, длиииииный параллелепипед и сфера. Матрицы - одинаковые. А конец параллелепипеда к нам ближе. ) Название: Re: ColladaImport и DetecMouseCollision Отправлено: Ruslan от 28 Октября 2010, 21:46:45 Цитировать Вообще, пользоваться матрицами не самый лучший способ. зато быстрый.. в случае, когда объекты в одной позиции и разного размера, можно учитывать к дистанции еще и ААББ объектов Название: Re: ColladaImport и DetecMouseCollision Отправлено: Sqwer от 28 Октября 2010, 21:59:30 Цитировать Вообще, пользоваться матрицами не самый лучший способ. Представь, что в одной точке находится огромный шар и маленький куб. А еще лучше, длиииииный параллелепипед и сфера. Матрицы - одинаковые. А конец параллелепипеда к нам ближе. ) 2) делать рендер в текстуру, и по ней определять, цвет(тексель) какого объекта находится под указателем курсора. (потяжелее) не составит труда для знатоков С++ и DirectX ;) Название: Re: ColladaImport и DetecMouseCollision Отправлено: DimiS от 31 Октября 2010, 03:02:27 ппц, чёто вы перемудрили с баундбоксами
всё решается с помощью обычного коллижен рей чека, есть куча экзамплов, например \Examples\Advanced\Pick mesh with mouse.cgr Название: Re: ColladaImport и DetecMouseCollision Отправлено: Sqwer от 31 Октября 2010, 03:30:37 Сам алгоритм нахождения пересечения луча с мешем очень тяжёл (дефалтный метод в ДХ9, в ДХ10 и ДХ11 метод занесли в D3DX ) , при его выполнении проходит выборка из всех треугольников.
само сабой понятно, что быстродействия никакого. Поэтому придуман подход к сокращению вычислений. первый тест на пересечение производится по ААББ или сфере ( пересечение находится простеньким алгоритмом, который в разы быстрее перебора каждого треугольника модели) после этого теста у нас есть список объектов, которые прошли тест (их ААББ или сфера пересеклась с лучём) далее можно идти по 2 путям: 1) из списка произвести тест пересечения уже по реальной геометрии 2) каждому объекту присваиваем уникальный цвет и рендим его в текстуру по вектору луча, FOV узкий около 20*20 (получаем текстурку маленького разрешения 32*32 например) смотрим на цвет пикселя, что в середине , и сравниваем этот цвет с цветом объектов. (особой чертой похода является возможность смотреть, через прозрачные полигоны!!! например дерево рендися билбордом, и надо выбрать объект что за ним... по первому пути мы никак его не выберим если объект целиком спрятан за билборд дерева, а по второму пути есть шанс выбрать его через листву). Недостаток в том, что метод тяжёл в реализации. Если выборка идёт из малополигональных объектов или количество объектов мало, то нужно последовать совету Димиса. Название: Re: ColladaImport и DetecMouseCollision Отправлено: Ruslan от 31 Октября 2010, 03:56:01 Цитировать всё решается с помощью обычного коллижен рей чека речь ведь идет о проверки многих объектов, которые могут находится друг за другом.. в этом случае CollisionRayCheck выдаст истину на все объекты, что пересеклись с лучем, верно?Название: Re: ColladaImport и DetecMouseCollision Отправлено: anval от 31 Октября 2010, 09:27:29 Привет.Я делаю так-оо-ray check-position tree(get closet item).
Название: Re: ColladaImport и DetecMouseCollision Отправлено: DimiS от 31 Октября 2010, 17:06:13 да, я действительно не очень хорошо объяснил суть метода
смысл использования колижен рей чека в том что у него в пропертях можно поставить опцию находить ближайшую точку(без этой опции он просто перебирает все полики пока не найдёт такой с которым есть пересечение, с этой опцией он проходит все полики и потом выдаёт ближайшую). Далее, имея точку пересечения с каждым объектом сравниваем дистанции и запоминаем ближайший объект и дистанцию до точки пересечения с ним, чтобы сравнить её со следующей дистанцией и т.д. Колижен рей чек действительно очень тяжелая операция, чтобы ограничить количество его применений можно сначала воспользоваться проверкой пересечения лучом баунд бокса, или проверять с помощью ДетектМаусКоллижена. Я пользуюсь вторым вариантом, поскольку каждый вызов ДетектМаусКоллижена выполняется всё же очень быстро, а разница в скорости по сравнению с проверкой баунд бокса компенсируется более аккуратной выборкой объектов для проверки потом КолиженРейЧеком Да, методов существует много, основной плюс предложенного мной это оптимальное сочетание цены/качества (геморроя/производительности) |