Mô phỏng hành động nhân vật trong xây dựng mô hình 3d

CHƯƠNG I . TỔNG QUAN VỀ THỰC TẠI ẢO VÀ 3D ANIMATION TRONG THỰC TẠI ẢO . 1.1. Tổng quan về thực tại ảo 1.1.1. Sơ lược lịch sử phát triển . 1.1.2. Các lĩnh vực ứng dụng của Thực tại ảo. 1.2 Hành động của nhân vật (3D Animation) trong thực tại ảo. 1.2.1. Animation trong thực tại ảo là gì? . 1.2.2. Hiệu ứng Animation trong thực tại ảo 1.2.3. Cơ sở mô phỏng 3D Animation. 1.2.4. Các vấn đề gặp phải trong quá trình nghiên cứu 1.2.5. Hướng giải quyết CHƯƠNG II KỸ THUẬT MÔ PHỎNG 2.1. Đặt vấn đề . 2.2. Kỹ thuật mô phỏng 2.2.1 Khởi tạo nhân vật và trang phục 2.2.2 Điều khiển mô phỏng các trạng thái hành động của nhân vật 2.2.3 Các vấn đề liên quan tới camera và các phím điều khiển. CHƯƠNG III . CHƯƠNG TRÌNH MÔ PHỎNG. 3.1. Bài toán 3.2. Mục đích và yêu cầu bài toán 3.3. Phương pháp giải quyết bài toán . 3.4 Một số kết quả bài toán

pdf77 trang | Chia sẻ: lvcdongnoi | Lượt xem: 2751 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Mô phỏng hành động nhân vật trong xây dựng mô hình 3d, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
r::set_animation_sequence(char *sequence_name, int transition_duration) { DWORD anim3d = Morfit_object_get_3D_animation(m_player_object); DWORD sequence = Morfit_3D_sequence_get_using_name(anim3d, sequence_name); if(sequence == NULL) return(NULL); Morfit_object_set_3D_sequence(m_player_object, sequence, transition_duration); return(sequence); } e. Hàm lựa chọn trình tự cho nhân vật Việc lựa chọn trình tự cho nhân vật được thực hiện khi ta thiết lập các trình tự đã có như trình tự đi bộ, trình tự tấn công bị thương, trình tự đứng,…Với mỗi trình tự sẽ được gắn một số id (m_sequence_id_num) vì vậy mà sẽ rất dễ dàng cho việc lựa chọn, quản lý các trình tự. Ở đây chúng ta sẽ cố gắng giữ m_sequence_id_num được cập nhập nhưng trong một số trường hợp thì không thể. Ví dụ nếu trình tự hiện tại (m_current_sequence) là trình tự tấn công (m_attack_sequence) và sẽ được phép làm như sau: Morfit_object_set_3D_sequence(m_player_object, m_attack_sequence, 0); Morfit_object_replace_3D_sequence_when_finished(m_player_object, m_stand_sequence,300); Trong trường hợp không biết chính xác thì trình đứng sẽ trở thành trình tự hiện tại. Vì vậy mà ở đây sẽ truy vấn tới trình tự hiện tại và sẽ cập nhập m_sequence_id_num và m_current_sequence phù hợp. Để hiểu rõ ý này xem đoạn mã sau: 30 DWORD sequence = Morfit_object_get_3D_sequence(m_player_object); if(sequence == m_stand_sequence) { m_sequence_id_num = STAND; m_current_sequence = m_stand_sequence; } else { if(sequence == m_walk_sequence) m_sequence_id_num = WALK; m_current_sequence = m_walk_sequence; } Chú ý điều quan trọng là khi chúng ta thiết lập một trình tự riêng biệt (specific sequence) thì đầu tiên sẽ thiết lập một trạng thái trình tự hành động và chỉ sau khi trình tự trạng thái hành động kết thúc thì nó sẽ tự động thiết lập trình tự muốn có. Có nghĩa là nếu muốn tạo trình tự đi bộ (walk_sequence) ta sẽ gọi hàm Morfit_object_set_3D_sequence(m_player_object,walk_sequence); Và ngay sau đó gọi hàm : sequence=Morfit_object_get_3D_sequence(m_player_object); thì kết quả trình tự trả về sẽ nhận được không phải là trình tự đi bộ (sequence!=walk_sequence !!!). Chỉ sau khi trình tự trạng thái hành động kết thúc thì trình tự walk_sequence mới được sử dụng. Sau đây là đoạn mã của quá trình lựa chọn một trình tự: void player::select_sequence() { DWORD sequence = Morfit_object_get_3D_sequence(m_player_object); if(sequence == m_stand_sequence) { 31 m_sequence_id_num = STAND; m_current_sequence = m_stand_sequence; } else { if(sequence == m_walk_sequence) m_sequence_id_num = WALK; m_current_sequence = m_walk_sequence; } if( (sequence == m_walk_sequence) && (m_speed < m_min_speed && m_speed > -m_min_speed)) { m_current_sequence = set_animation_sequence("stand",100); m_sequence_id_num = STAND; } else if((sequence == m_stand_sequence) && (m_speed >= m_min_speed || m_speed <= -m_min_speed)) { m_current_sequence = set_animation_sequence("walk",100); m_sequence_id_num = WALK; } else if((sequence == m_fall_sequence) && (m_speed < m_min_speed && m_speed > -m_min_speed)) { //kiểm tra trình tự ngã (fall_sequence) đã kết thúc hay chưa DWORD anim3d = Morfit_object_get_3D_animation(m_player_object); 32 DWORD fall_sequence = Morfit_3D_sequence_get_using_name(anim3d, "death"); int num_of_frames = Morfit_3D_sequence_get_number_of_frames(fall_sequence); double current_position = Morfit_3D_sequence_get_current_frame(fall_sequence); if(current_position >= num_of_frames - 2) { m_current_sequence = set_animation_sequence("stand",1000); m_sequence_id_num = STAND; } } if(m_sequence_id_num!=FALL) { //thiết lập một trình tự đúng if(m_speed<0 ) { Morfit_3D_sequence_backwards_play(m_current_sequence,YES); } else { Morfit_3D_sequence_backwards_play(m_current_sequence,NO); } } set_sequence_speed(); } 33 f. Hàm di chuyển trạng thái hành động của nhân vật Di chuyển trạng thái hành động của nhân vật là việc thực hiện các thao tác điều khiển cho nhân vật thực hiện một hành động để chuyển từ vị trí này sang vị trí khác như tiến lên trước, lùi về phía sau, sang phải, sang trái… Để thực hiện việc di chuyển cho nhân vật trước tiên phải xác định vị trí mà nhân vật cần đi tới. Việc này được thực hiện một cách dễ dàng qua hàm : Morfit_object_get_location(m_player_object,&save_location[0], &save_location[1], &save_location[2]); Sau đó sẽ tạo một trình tự cho nhân vật qua hàm: DWORD sequence = Morfit_object_get_3D_sequence(m_player_object); Có nghĩa là giả sử m_sequence_id_num==WALK là một trình tự đi bộ hoặc là một vài trình tự vận chuyển ban đầu của trình tự đi bộ, nếu ta có thể thay thế sequence==m_walk_sequence thì nó sẽ không thể bắt kịp sự chuyển vận từ trạng thái đứng sang trạng thái đi bộ được. Nên nhớ rằng trình tự vận chuyển đã được phát sinh một cách tự động bởi các engine vì vậy mà việc chuyển đổi từ một trình tự này sang một trình tự khác được thực hiện một cách mềm mại và nhịp nhàng. Nếu không muốn trình tự vận chuyển phát sinh một cách tự động thì đơn giản có thể gọi hàm sau : Morfit_object_set_3D_sequence( ,0); Trong đó với 0 là khoảng thời gian tồn tại cho sự vận chuyển. Cũng như vậy trong quá trình di chuyển phải xác định lực đã sử dụng hay chính xác hơn chính là lực tác dụng vào nhân vật, vì vậy mà biến int muscle_force_used = NO; được khai báo có ý nghĩa ban đầu là chưa có lực nào tác dụng. Như đã nói ở trên thì tốc độ của nhân vật phụ thuộc vào các thành phần lực vì vậy mà dựa vào đó mà có thể thấy rõ sự nhanh hay chậm của nhân vật trong từng trình tự trạng thái chuyển động. Sau đây là một đoạn chương trình mô phỏng việc dịch chuyển tiến phía trước, lùi phía sau, sang trái, sang phải của nhân vật: void player::move(void) { 34 int muscle_force_used = NO; // ko có lực tác dụng double save_location[3]; //Xác định vị trí nhân vật cần di chuyển tới Morfit_object_get_location(m_player_object, &save_location[0], &save_location[1], &save_location[2]); DWORD sequence = Morfit_object_get_3D_sequence(m_player_object); if(m_sequence_id_num == WALK || sequence == m_stand_sequence) { //tiến phía trước if(GetAsyncKeyState(VK_UP) < 0) { m_speed += m_acceleration; muscle_force_used = YES; } //lùi phía sau if(GetAsyncKeyState(VK_DOWN) < 0) { muscle_force_used = YES; m_speed -= m_acceleration; } } if(m_sequence_id_num == WALK || sequence == m_stand_sequence || sequence == m_attack_sequence || sequence == m_pain_sequence) { //sang trái if(GetAsyncKeyState(VK_LEFT) < 0) { Morfit_object_rotate_z(m_player_object, 6, WORLD_SPACE); } 35 //sang phải if(GetAsyncKeyState(VK_RIGHT) < 0) { Morfit_object_rotate_z(m_player_object, -6, WORLD_SPACE); } } // xác định vận tốc và lực đã sử dụng double gravity_and_friction_factor = get_friction_and_gravity_factor(); if(muscle_force_used == NO || fabs(m_speed) > m_min_speed) { m_speed *= gravity_and_friction_factor; if(muscle_force_used == YES) if(fabs(m_speed) < fabs(m_min_speed)) m_speed = m_min_speed * m_speed / fabs(m_speed); } if(m_speed > m_max_speed) m_speed = m_max_speed; if(m_speed < -m_max_speed) m_speed = -m_max_speed; Morfit_object_move(m_player_object,OBJECT_SPACE, -m_speed,0,0); // Lựa chọn trình tự đúng select_sequence(); // Xác địn vùng nền dưới double point_below[3]; get_polygon_below(point_below); // Xác định một trạng thái mới if(new_altitude > save_location[2] + m_height / 3) { 36 Morfit_object_set_location(m_player_object,save_location[0], save_location[1], save_location[2]); m_speed = -m_speed * 0.5; } else { double location[3]; Morfit_object_get_location(m_player_object, &location[0], &location[1], &location[2]); Morfit_object_set_location(m_player_object, location[0], location[1], new_altitude); } } g. Một số trạng thái chuyển động của nhân vật * Trạng thái tấn công (Attack) Ở đây sẽ mô phỏng nhân vật trong tư thế dùng vũ khí tấn công một đối tượng khác. Một trình tự tấn công thực tế được xây dựng từ rất nhiều các trình tự tấn công khác. Như tấn công với súng, phóng đạn, bắn trúng mục tiêu với cùng một điều khiển…Trong game thì nó rất dễ dàng có được các trạng thái riêng biệt đối với các trình tự khác nhau. Có thể tham khảo đoạn mã sau để hiểu rõ hơn về một trình tự trạng thái tấn công: void player::attack(void) { if(m_attack_sequence==NULL) return; Morfit_object_set_3D_sequence(m_player_object, m_attack_sequence, 0); Morfit_object_replace_3D_sequence_when_finished(m_player_obj ect, m_stand_sequence,300); m_current_sequence=m_attack_sequence; 37 m_sequence_id_num=ATTACK; } * Trạng thái bị thương Cũng giống như trạng thái tấn công thì trạng thái bị thương sẽ mô phỏng khi nhân vật bị trúng đạn và nó cũng được tạo lên bằng hàng loạt các trình tự bị thương khác như sẽ giảm tốc độ, có thể khụy xuống và hiện chỗ thương trúng đạn tại vị trí đó. Và sau đây là đoạn mã mô phỏng trạng thái bị thương: void player::pain(void) { if(m_pain_sequence==NULL) return; Morfit_object_set_3D_sequence(m_player_object, m_pain_sequence, 0); Morfit_object_replace_3D_sequence_when_finished(m_player_obj ect, m_stand_sequence,400); m_current_sequence=m_pain_sequence; m_sequence_id_num=PAIN; } * Cập nhập theo một trạng thái hành động mới Như đã nói khi một trạng thái được thay đổi thì các tham số hành động một hành động của nhân vật sẽ thay đổi theo sao cho phù hợp với từng trình tự mô phỏng hành động đó. Ở đây có thể “load” chúng khi mà cần tới những ảnh mô phỏng đó trong khi các “engine” sẽ không đủ nhanh để “load” những ảnh đã có sẵn trong bộ nhớ. Có thể theo dõi đoạn mã sau để thấy được sự thay đổi giữa các trạng thái: int player::update_according_to_new_animation(void) { char buff[MAX_PATH]; strcpy(buff,m_bitmap_path); 38 strcat(buff,"\\skin.bmp"); m_skin_bitmap = Morfit_bitmap_load(buff,-1); strcpy(buff,m_bitmap_path); strcat(buff,"\\pain.bmp"); m_pain_bitmap = Morfit_bitmap_load(buff,-1); //Thiết lập trang phục Morfit_object_set_bitmap(m_player_object, m_skin_bitmap); // Thiết lập tham số theo tỉ lệ kích thước set_parameters_according_to_scale(); m_current_sequence = set_animation_sequence("stand", 0); m_sequence_id_num = STAND; m_stand_sequence = m_current_sequence; DWORD anim3d = Morfit_object_get_3D_animation(m_player_object); m_fall_sequence = Morfit_3D_sequence_get_using_name(anim3d, "death"); if(m_fall_sequence != NULL) { int num_of_frames = Morfit_3D_sequence_get_number_of_frames(m_fall_sequence); //Dừng quá trình đang ngã trong một trạng thái riêng. Morfit_3D_sequence_set_frame_duration(m_fall_sequence, num_of_frames-2, 1000000); Morfit_3D_sequence_set_speed(m_fall_sequence,0.5); } m_walk_sequence = Morfit_3D_sequence_get_using_name(anim3d, "walk"); if(m_walk_sequence == NULL) return(VR_ERROR); m_attack_sequence = Morfit_3D_sequence_get_using_name(anim3d, "attak"); m_pain_sequence = Morfit_3D_sequence_get_using_name(anim3d, "pain"); return(OK); } 39 2.2.3 Các vấn đề liên quan tới camera và các phím điều khiển. a. Các vấn đề liên quan tới camera. Camera là thành phần vô cùng quan trọng trong kĩ thuật mô phỏng vì nó quyết định tới góc nhìn, khoảng cách nhìn, không gian nhìn đối với các đối tượng trong không gian thới giới ảo. Việc liên kết giữa camera và đối tượng sẽ làm cho quá trình mô phỏng sẽ được linh động hơn, mềm mại và chân thật hơn đối với người quan sát. Với mỗi chế độ camera khác nhau ta cũng có các hiệu ứng khác nhau vì vậy mà sau đây là một số chế độ camera và hiệu ứng cơ bản về camera đã sử dụng để mô phỏng nhân vật trong đề tài này: * Thiết lập camera ở chế độ chase_flexible Ở chế độ này camera sẽ di chuyển mềm mại, uyển chuyển theo đối tượng mà nó bám theo. Chúng ta có thể thiết lập kiểu theo cho đối tượng bằng hàm: STATE_object_set_chase_type(Handle,chase_type) Với kiểu theo là flexible, ta có thể thiết lập độ mềm dẻo của đường rẽ bằng hàm STATE_object_set_chase_softness(object_handle,softness) và tương tự có hàm lấy sự mềm dẻo hiện tại của đối tượng theo là: STATE_object_get_chase_softness(object_handle). Giá trị softness nằm trong khoảng [0-1]. Khoảng cách theo (chase offset): Chase offset xác định khoảng cách từ đối tượng theo đến đối tượng bị theo. Ví dụ: char offset là [0,0,10] có nghĩa là đối tượng theo sẽ theo đối tượng nhưng nó sẽ ở bên trên đối tượng cách đối tượng 10 đơn vị. Ta có thể thiết lập char offset bằng hàm sau: STATE_object_set_chase_offset(object_handle,offset[3]). Ta cũng có thể lấy char offset hiện tại của đối tượng bằng hàm sau: STATE_object_get_chase_offset(object_handle,offset[3]). Sau đây là đoạn mã mô phỏng thiết lập camera ở chế độ chase_flexible: void camera::set_ chase_flexible_mode(void) { 40 Morfit_camera_set_chase_type(m_camera_handle, CHASE_FLEXIBLE); double chase_offset[3] = {0,0,0}; Morfit_camera_set_chase_offset(m_camera_handle, chase_offset); update_chase_params(); } * Thiết lập camera ở chế độ chase_location Cũng giống như ở chế độ chase_flexible nó cũng có nhiệm vụ bám theo đối tượng và tính khoảng cách tới đối tượng xong có sự khác biệt ở đây là camera sẽ không quay khi đối tượng bị theo quay. Sau đây là đoạn mã mô phỏng thiết lập camera ở chế độ chase_location: void camera::set_chase_location_mode(void) { Morfit_camera_set_chase_type(m_camera_handle, CHASE_LOCATION); double box[2][3]; Morfit_object_get_bounding_box(m_object_to_chase, box); double height = box[1][2] - box[0][2]; double distance = height * 1.5 + 40; // double scale[3]; // Morfit_object_get_scale(m_camera_handle, scale); // double distance=scale[2]*100+100; double direction[3]; Morfit_object_get_direction(m_object_to_chase,&direction[0], &direction[1], &direction[2]); Double chase_offset[3] = {-direction[0]*distance, -direction[1]*distance, 20}; 41 Morfit_camera_set_chase_offset(m_camera_handle, chase_offset); double location[3];Morfit_object_get_location(m_object_to_chase, &location[0], &location[1], &location[2]); Morfit_camera_point_at(m_camera_handle,location[0],location[1], location[2]); } * Tạm dừng một chế độ camera (stop_chasing): Việc tạm dừng một chế độ camera theo đối tượng được thực hiện một cách đơn giản khi dùng hàm sau : Morfit_camera_set_chase_type(m_camera_handle, NO_CHASE); * Thiết lập camera ở chế độ zoom_in và zoom_out: Thiết lập camera ở chế độ zoom_out là quá trình di chuyển camera ra xa từ đối tượng bị theo. Chú ý rằng ở đây không phải là một zoom_out thực sư, để tạo một zoom_out thực sự thì có thể sự dụng hàm sau: Morfit_camera_set_field_of_view() Sau đây là đoạn mã mô phỏng thiết lập camera ở chế độ zoom_out: void camera::zoom_out(void) { int chase_type = Morfit_camera_get_chase_type(m_camera_handle); if(chase_type == CHASE_LOCATION) { // chase_distance không thích hợp ở chế độ CHASE_LOCATION double chase_offset[3]; Morfit_camera_get_chase_offset(m_camera_handle, chase_offset); chase_offset[0] *= 1.1; chase_offset[1] *= 1.1; chase_offset[2] *= 1.1; Morfit_camera_set_chase_offset(m_camera_handle, chase_offset); return; 42 } if(chase_type == CHASE_FLEXIBLE) { double distance = Morfit_camera_get_chase_distance(m_camera_handle); Morfit_camera_set_chase_distance(m_camera_handle,distance*1.1); return; } } Thiết lập camera ở chế độ zoom_in là quá trình đưa camera lại gần đối tượng bị theo. Chú ý rằng ở đây cũng như chế độ zoom_out thì đây cũng không phải là một chế độ zoom_in thực sự, để tạo một zoom_out thực sự thì có thể sự dụng hàm sau: Morfit_camera_set_field_of_view() Sau đây là đoạn mã mô phỏng thiết lập camera ở chế độ zoom_in: void camera::zoom_in(void) { int chase_type = Morfit_camera_get_chase_type(m_camera_handle); if(chase_type == CHASE_LOCATION) { // chase_distance không thích hợp ở chế độ CHASE_LOCATION double chase_offset[3]; Morfit_camera_get_chase_offset(m_camera_handle, chase_offset); chase_offset[0] *= 0.9; chase_offset[1] *= 0.9; chase_offset[2] *= 0.9; Morfit_camera_set_chase_offset(m_camera_handle, chase_offset); return; } if(chase_type == CHASE_FLEXIBLE) { 43 double distance = Morfit_camera_get_chase_distance(m_camera_handle); Morfit_camera_set_chase_distance(m_camera_handle,distance*0.9); return; } } b. Các vần đề liên quan tới các phím điều khiển. Trong quá trình mô phỏng trạng thái hành động của nhân vật thì việc dùng các phím điều khiển để thay đổi các tùy chọn, thiết lập hoặc điều khiển di chuyển của nhân vật là rất cần thiết. Chính vì vậy để cho quá trình sử dụng chương trình một cách dễ dàng mà trong chương trình đã thiết lập cài đặt sử dụng các phím điều khiển tương ứng với các nhiệm vụ và tác dụng của nó như sau: + Phím “A” : Zoom out với camera. + Phím “Z” : Zoom in với camera + Phím “S” : Phóng to kích thước tương ứng với kích thước của nhân vật + Phím “X” : Thu nhỏ thước tương ứng với kích thước của nhân vật + Phím “W” : Thiết lập tỉ lệ kích thước mặc định + Phím “D” : Tỉ lệ kích thước theo trục X (tạo cho nhân vật “mập” lên) + Phím “C” : Tỉ lệ kích thước theo trục X (tạo cho nhân vật “gầy” xuống) + Phím “G” : Tỉ lệ kích thước theo trục Y (tạo cho nhân vật “rộng” lên) + Phím “B” : Tỉ lệ kích thước theo trục Y (tạo cho nhân vật “hẹp” xuống) + Phím “H” : Tỉ lệ kích thước theo trục Z (tạo cho nhân vật “cao” lên) + Phím “N” : Tỉ lệ kích thước theo trục Z (tạo cho nhân vật “Thấp” xuống) + Phím “F” : Không sử dụng chế độ full_screen (màn hình 800x600) + Phím “V” : Sử dụng chế độ full_screen (màn hình 800x600) + Phím “R” : Không sử dụng card đồ họa thiết lập cửa sổ mặc định (240,180,400,400) + Phím “1” : Thiết lập camera ở chế độ chase_location + Phím “2” : Thiết lập camera ở chế độ chase_flexible + Phím “3” : Thiết lập camera ở chế độ stop_chasing + Phím “4” : Thiết lập nhân vật ở trạng thái tấn công (attack) 44 + Phím “5” : Thiết lập nhân vật ở trạng thái tấn bị thương (pain) + Phím “6” : Thiết lập lại trang phục cho nhân vật (replace_skin) + Phím “7” : Thiết lập lại bề ngoài cho nhân vật (replace_shape) + Phím “F1” : Gọi một bảng HELP Sau đây là toàn bộ mã chương trình đặt chế độ điều khiển tương ứng với các phím như mô tả trên: void settings(camera *camera1, player *player1, DWORD anim1, DWORD anim2) { //Zoom out với camera if(GetAsyncKeyState('A')<0) { camera1->zoom_out(); } else if(GetAsyncKeyState('Z')<0) //Zoom in với camera { camera1->zoom_in(); } int scale_flag = 0; //Tỉ lệ kích thước tương ứng với kích thước của nhân vật if( GetAsyncKeyState('S')<0 ) { player1->scale(1.1, X_AXIS|Y_AXIS|Z_AXIS); scale_flag++; } else if( GetAsyncKeyState('X')<0 ) { player1->scale(0.9, X_AXIS|Y_AXIS|Z_AXIS); scale_flag++; } 45 else if(GetAsyncKeyState('W')<0) //Thiết lập tỉ lệ kích thước mặc định { player1->scale_default(); scale_flag++; } //Tỉ lệ kích thước theo trục X (tạo cho nhân vật mập lên) if( GetAsyncKeyState('D')<0) { player1->scale(1.1, X_AXIS); scale_flag++; } else if( GetAsyncKeyState('C')<0) { player1->scale(0.9, X_AXIS); scale_flag++; } //Tỉ lệ kích thước nhân vật theo trục Y (tạo cho nhân vật “rộng lên”) if( GetAsyncKeyState('G')<0) { player1->scale(1.1, Y_AXIS); scale_flag++; } else if( GetAsyncKeyState('B')<0) { player1->scale(0.9, Y_AXIS); scale_flag++; } // Tỉ lệ kích thước nhân vật theo trục Z (tạo cho nhân vật “cao lên”) if( GetAsyncKeyState('H')<0) { 46 player1->scale(1.1, Z_AXIS); scale_flag++; } else if( GetAsyncKeyState('N')<0) { player1->scale(0.9, Z_AXIS); scale_flag++; } if(scale_flag) camera1->update_chase_params(); if( (GetAsyncKeyState('F')&1) && (GetAsyncKeyState('F')<0)) { if(Morfit_3D_card_is_used() ==NO || Morfit_3D_card_is_full_screen_mode() == NO) { if(Morfit_3D_card_set_full_screen_mode(800,600) == VR_ERROR) { if(Morfit_3D_card_check_hardware_support() == YES) { MessageBox(NULL, "Failed to initialize your 3D card.\n This sample only works with hardware rendering\nPlease check that you have a 3D card and DirectX 6.1 and above\n","No 3D card", MB_OK); } } } } else if((GetAsyncKeyState('V')&1) && (GetAsyncKeyState('V')<0)) { 47 if(Morfit_3D_card_is_used() == NO || Morfit_3D_card_is_full_screen_mode() == YES) { Morfit_engine_maximize_default_rendering_window(); if(Morfit_3D_card_set_window_mode() == VR_ERROR) { if(Morfit_3D_card_check_hardware_support() == YES) { MessageBox(NULL, "Failed to initialize your 3D card.\n This sample only works with hardware rendering\nPlease check that you have a 3D card and DirectX 6.1 and above\n","No 3D card", MB_OK); } } } } else if((GetAsyncKeyState('R')&1)&& (GetAsyncKeyState('R')<0)) { Morfit_3D_card_use(NO); Morfit_engine_set_default_rendering_window_size(240,180,400,400); } if(GetAsyncKeyState('1')<0) { camera1->set_chase_location_mode(); } else if(GetAsyncKeyState('2')<0) { camera1->set_chase_flexible_mode(); } else if(GetAsyncKeyState('3')<0) { 48 camera1->stop_chasing(); } if(GetAsyncKeyState('4')<0) { player1->attack(); } else if(GetAsyncKeyState('5')<0) { player1->pain(); } if(GetAsyncKeyState('6')&1) { player1->replace_skin(); } static int anim_toggle = 0; if(GetAsyncKeyState('7')&1) { if(anim_toggle == 0) { player1->replace_shape(anim2, "..\\..\\..\\..\\..\\Worlds\\player2"); anim_toggle = 1; } else { player1->replace_shape(anim1, "..\\..\\..\\..\\..\\Worlds\\player1"); anim_toggle = 0; } } if(GetAsyncKeyState(VK_F1)&1) { help_popup(); } } 49 CHƯƠNG III CHƯƠNG TRÌNH MÔ PHỎNG 3.1. Bài toán Sau một thời gian tìm hiểu về Thực tại ảo và 3D animation trong Thực tại ảo, tác giả xin đưa ra một ứng dụng nhỏ; xây dựng một số hiệu ứng cho nhân vật trong môi trường thực tại ảo. Bài toán tác giả đưa ra trong đồ án này là bài toán mô phỏng một số hiệu ứng 3D animation trong môi trường thựct ại ảo. 3.2. Mục đích và yêu cầu bài toán. Mục đích của bài toán: Từ bài toán trên ta nhận thấy mục đích của bài toán bao gồm: +Nhằm giới thiệu một phương pháp tiếp cận mới đối với 3D animation, đó là phương pháp tiếp cận và xử lý dựa trên ảnh. + Nhằm giới thiệu một số thuật toán trong quá trình xây dựng các hiệu ứng 3D animation. + Nhằm giới thiệu một hướng nghiên cứu và xây dựng mới về hiệu ứng 3D trong môi trường thực tại ảo, đó chính là hiệu ứng 3D animation. Yêu cầu của bài toán: Từ mục đích của bài toán chúng ta nhận thấy những yêu cầu của bài toán như sau: + Vì bài toán mang mục đích tìm hiểu và giới thiệu phương pháp xây dựng mô phỏng hành động nhân vật trong môi trường thực tại ảo, vì vậy bài toán phải mang tính điển hình rễ hiểu và đáp ứng được những mục đích mà bài toán đề ra. + Bài toán phải cho thấy được vai trò cũng như tầm quan trọng của việc mô phỏng trong các hiệu ứng 3D animation nói riêng và trong môi trường thực tại ảo nói chung. + Bài toán phải thể hiện được một số hiệu ứng cơ bản của các hành động của nhân vật trong môi trường thực tại ảo. 3.3. Phương pháp giải quyết bài toán Từ những yêu cầu và mục đích trên tác giả đề ra phương hướng giải quyêt 50 bài toán như sau: Vì bài toán nhằm mục đích tìm hiểu về các hành động của nhân vật được mô phỏng trong môi trường thực tại ảo. Vì vậy tác giả đi mô phỏng các hiệu ứng mang tính đơn giả, dễ mô phỏng. Kết hợp các ảnh của nhân vật để mô phỏng các hiệu ứng . Ta sử dụng hai ngôn ngữ là Morfit 3D và Virsual C++ để mô phỏng và điều khiển các hành động nhân vật. 3.4 Một số kết quả bài toán. Các ảnh đầu vào: Ảnh mặt trước và sau của skin và pain: Các ảnh này được ghép vào các đa giác của khối hình nhân vật tạo từ 3dsmax. Cửa sổ Help hiện ra để hướng dẫn khi bắt đầu chạy chương trình hoặc khi ấn F1 51 Hình nhân vật khi khởi động chương trình ở trạng thái đứng yên: Một số hình ảnh về trạng thái tấn công, thương, lên dốc, xuống dốc của nhân vật. 52 53 54 55 KẾT LUẬN Sau một thời gian nghiên cứu, tìm hiểu thì đồ án đã hoàn thành và đạt được một số kết quả như sau: * Giới thiệu và tổng quan về thực tại ảo và 3D animation trong thực tại ảo. * Giới thiệu cách thức để khởi tạo một đối tượng trong thực tại ảo. * Giới thiệu một số thuật toán cơ bản trong quá trình điều khiển đố tượng. * Giới thiệu một số trạng thái của đối tượng. * Giới thiệu một số chế độ điều khiển camera và sự chuyển đổi giữa các chế độ đó. * Xây dựng một chương trình nhỏ mô phỏng hành động của nhân vật với một số hiệu ứng 3D animation trong môi trường thực tại ảo với các trạng thái cụ thể. 56 HƯỚNG PHÁT TRIỂN ĐỀ TÀI Trong tương lai tác giả sẽ cố gắng phát triển theo hướng sâu hơn, với quy mô lớn hơn và có tính thực tế cao hơn. Sẽ cố gắng hoàn thành và phát triển một game với ứng dụng của việc mô phỏng các hành động nhân vật với nhiều nhân vật và tương tác hơn với môi trường thế giới ảo. 57 PHỤ LỤC // player.h #ifndef PLAYER_H #define PLAYER_H #define ACCELERATION 4 #define MAX_SPEED 50 #define MIN_SPEED 2 #define STAND 0 #define WALK 1 #define FALL 2 #define ATTACK 3 #define PAIN 4 #define X_AXIS 1 #define Y_AXIS 2 #define Z_AXIS 4 //#include "Engine\\mrft_api.h" #include class player { public: player(); virtual ~player(); int init(char *file_name, char *bitmap_path); //di chuyen nhan vat void move(void); //ti le kich thuoc nhan vat theo cac truc x,y,x hoac co the ket hop giua cac truc void scale(double factor, int axis); //Thiet lap ti le kich thuoc mac dinh void scale_default(void); //trang thai tan cong void attack(void); //trang thai bi thuong void pain(void); //Lay lai trang phuc cho nhan vat,chinh la chuyen doi giua cac anh void replace_skin(void); //Lay lai hinh dang ban dau cho nhan vat void replace_shape(DWORD new_3d_animation, char *bitmap_path); DWORD m_player_object; private: 58 double m_speed; DWORD m_current_sequence; int m_sequence_id_num; DWORD m_walk_sequence, m_stand_sequence, m_fall_sequence, m_attack_sequence, m_pain_sequence; DWORD m_skin_bitmap, m_pain_bitmap; double m_acceleration; int m_effort; //su dung thiet lap nhip tho khi nhan vat dang dung double m_friction; double m_max_speed; double m_min_speed; int m_skin_id; // 0 khi su dung skin bitmap. 1 khi su dung pain bitmap double m_height; char m_bitmap_path[MAX_PATH]; //Tao cong thuc tinh luc ma sat va trong luc len nhan vat double get_friction_and_gravity_factor(void); DWORD set_animation_sequence(char *sequence_name, int transition_duration); //Thiet lap cac them so theo ti le kich thuoc //Khi trang thai nhan vat thay doi thi cac thuoc tinh cung thay doi void set_parameters_according_to_scale(void); //Lua chon mot trinh tu dung de mo phong tai mot vi tri //Nhu chuyen doi tu mot trang thai dang chay thanh trang thai dung void select_sequence(); //Tao trinh tu tho khi nhan vat dang dung double get_standing_sequence_speed(void); //Thiet lap trinh tu toc do void set_sequence_speed(void); //lap lai hanh dong nhan vat theo moi thoi gian co the int update_according_to_new_animation(void); //Xac dinh mot diem duoi nen DWORD get_polygon_below(double point_below[3]); }; #endif // PLAYER_H // camera.h #ifndef CAMERA_H #define CAMERA_H //#include "mrft_api.h" #include 59 class camera { public: camera(); virtual ~camera(); int init(DWORD object_to_chase); void move(void); void zoom_out(void); void zoom_in(void); void set_chase_flexible_mode(void); void set_chase_location_mode(void); void stop_chasing(void); void update_chase_params(void); DWORD m_camera_handle; private: DWORD m_object_to_chase; }; #endif // CAMERA_H / anim3d.cpp ////////////////////////////////////////////////////////////////////// #include #include #include //#include #include "..\\..\\..\\..\\..\\Engine\\Include\\mrft_api.h" #include "player.h" #include "camera.h" int init_stuff(player *player1, player *player2, camera *camera1, DWORD *animation1, DWORD *animation2); void settings(camera *camera1, player *player1, DWORD anim1, DWORD anim2); void help_popup(void); void set_vector(double vector[3], double x, double y, double z); void main() { player player1, player2; //thu voi player 1 camera camera1; DWORD animation1, animation2; 60 help_popup(); if(init_stuff(&player1,&player2, &camera1, &animation1, &animation2)==VR_ERROR) { printf("Co loi trong khi thiet lap the gioi\nAn mot nut bat ki de thoat"); getch(); return; } while( (GetAsyncKeyState(VK_ESCAPE)&1) ==0 ) //GetAsyncKeyState() la mot ham API cua WIN32 (not Morfit) { //Ham nay kiem tra xem nut Escape da duoc an chua player1.move(); camera1.move(); Morfit_engine_render(NULL,camera1.m_camera_handle); //Dua 1 anh toi camera va dat no vao cua so mo phong mac dinh settings(&camera1, &player1, animation1, animation2); //scan keyboard and thay doi global theo thiet lap } Morfit_engine_close(); } void help_popup(void) { if(Morfit_3D_card_is_used() == YES && Morfit_3D_card_is_full_screen_mode() == YES) return; int file_size; char *buff = (char *)Morfit_utilities_file_to_memory("help.txt", &file_size); MessageBox(NULL,buff,"Help", MB_ICONINFORMATION); Morfit_utilities_free_file_memory(buff); } //Thay doi thiet lap chuong trinh theo dau vao cua ban phim void settings(camera *camera1, player *player1, DWORD anim1, DWORD anim2) { //Zoom out voi camera if(GetAsyncKeyState('A')<0) { camera1->zoom_out(); } 61 else if(GetAsyncKeyState('Z')<0) //Zoom in voi camera { camera1->zoom_in(); } int scale_flag = 0; //Ti le kich thuoc tuong ung voi kich thuoc nhan vat if( GetAsyncKeyState('S')<0 ) { player1->scale(1.1, X_AXIS|Y_AXIS|Z_AXIS); scale_flag++; } else if( GetAsyncKeyState('X')<0 ) { player1->scale(0.9, X_AXIS|Y_AXIS|Z_AXIS); scale_flag++; } else if(GetAsyncKeyState('W')<0) //Thiet lap ti le kich thuoc mac dinh { player1->scale_default(); scale_flag++; } //Ti le kich thuoc theo truc X(tao cho nhan vat map len hay gay xuong) if( GetAsyncKeyState('D')<0) { player1->scale(1.1, X_AXIS); scale_flag++; } else if( GetAsyncKeyState('C')<0) { player1->scale(0.9, X_AXIS); scale_flag++; } //Ti le kich thuoc theo truc Y(tao cho nhan vat rong len hay hep di) if( GetAsyncKeyState('G')<0) { player1->scale(1.1, Y_AXIS); scale_flag++; } 62 else if( GetAsyncKeyState('B')<0) { player1->scale(0.9, Y_AXIS); scale_flag++; } //Ti le kich thuoc theo truc Z(tao cho nhan vat cao len hay thap xuong) if( GetAsyncKeyState('H')<0) { player1->scale(1.1, Z_AXIS); scale_flag++; } else if( GetAsyncKeyState('N')<0) { player1->scale(0.9, Z_AXIS); scale_flag++; } if(scale_flag) camera1->update_chase_params(); if( (GetAsyncKeyState('F')&1) && (GetAsyncKeyState('F')<0)) { if(Morfit_3D_card_is_used() == NO || Morfit_3D_card_is_full_screen_mode() == NO) { if(Morfit_3D_card_set_full_screen_mode(800,600) == VR_ERROR) { if(Morfit_3D_card_check_hardware_support() == YES) { MessageBox(NULL, "Loi cai dat 3D card.\n \nVui long kiem tra 3D card and DirectX 6.1 \n","No 3D card", MB_OK); } } } } else if((GetAsyncKeyState('V')&1) && (GetAsyncKeyState('V')<0)) { if(Morfit_3D_card_is_used() == NO || Morfit_3D_card_is_full_screen_mode() == YES) { 63 Morfit_engine_maximize_default_rendering_window(); if(Morfit_3D_card_set_window_mode() == VR_ERROR) { if(Morfit_3D_card_check_hardware_support() == YES) { MessageBox(NULL, "Loi cai dat 3D card.\n \nVui long kiem tra 3D card and DirectX 6.1 \n","No 3D card", MB_OK); } } } } else if((GetAsyncKeyState('R')&1)&& (GetAsyncKeyState('R')<0)) { Morfit_3D_card_use(NO); Morfit_engine_set_default_rendering_window_size(240,180,400,400); } if(GetAsyncKeyState('1')<0) { camera1->set_chase_location_mode(); } else if(GetAsyncKeyState('2')<0) { camera1->set_chase_flexible_mode(); } else if(GetAsyncKeyState('3')<0) { camera1->stop_chasing(); } if(GetAsyncKeyState('4')<0) { player1->attack(); } else if(GetAsyncKeyState('5')<0) { player1->pain(); } if(GetAsyncKeyState('6')&1) 64 { player1->replace_skin(); } static int anim_toggle = 0; if(GetAsyncKeyState('7')&1) { if(anim_toggle == 0) { player1->replace_shape(anim2, "..\\..\\..\\..\\..\\Worlds\\player2"); anim_toggle = 1; } else { player1->replace_shape(anim1, "..\\..\\..\\..\\..\\Worlds\\player1"); anim_toggle = 0; } } if(GetAsyncKeyState(VK_F1)&1) { help_popup(); } } int init_stuff(player *player1, player *player2, camera *camera1,DWORD *animation1, DWORD *animation2) { //Morfit_3D_card_use(YES); int rc = Morfit_engine_load_world("..\\..\\..\\..\\..\\worlds\\country.wld", NULL, "..\\..\\..\\..\\..\\worlds\\bitmaps", USER_DEFINED_BEHAVIOR); if(rc != OK) return(VR_ERROR); // Morfit_3D_sequence_duplicate() if(player1->init("..\\..\\..\\..\\..\\Worlds\\player1\\player.md2", "..\\..\\..\\..\\..\\Worlds\\player1") == VR_ERROR) return(VR_ERROR); if(player2->init("..\\..\\..\\..\\..\\Worlds\\player2\\player.md2", "..\\..\\..\\..\\..\\Worlds\\player2") == VR_ERROR) return(VR_ERROR); *animation1 = Morfit_object_get_3D_animation(player1->m_player_object); 65 *animation2 = Morfit_object_get_3D_animation(player2->m_player_object); //disable player2 Morfit_object_disable(player2->m_player_object); //Xac dinh vi tri nhan vat //Trong truong hop Z==10000 la vi itri cua nhan vat o duoi nen //Sau do nhan vat se duoc dieu chinh toi mot vi tri tot hon. Morfit_object_move(player1->m_player_object,OBJECT_SPACE, - 1000,0,10000); if(camera1->init(player1->m_player_object) != OK) return(VR_ERROR); //Vai thiet lap voi cua so // //Cac hieu ung nay chi tren pm mo phong Morfit_engine_set_picture_quality(640*480); Morfit_engine_maximize_default_rendering_window(); Morfit_engine_set_default_rendering_window_title("Do an tot nghiep. Cac phim dieu khien: F1, A,Z,X,S,W,1,2,3,4,5,6,7, V,F,R,D,C,H,N, ESC"); Morfit_engine_set_atmospheric_effect_intensity(0); ShowCursor(FALSE); if(Morfit_3D_card_set_window_mode() == VR_ERROR) { if(Morfit_3D_card_check_hardware_support() == YES) { MessageBox(NULL, "Failed to initialize your 3D card.\n This sample only works with hardware rendering\nPlease check that you have a 3D card and DirectX 6.1 and above\n","No 3D card", MB_OK); } //Tao ra mot cua so nho cho pm mo phong Morfit_engine_set_default_rendering_window_size(240,180,400,400); } Morfit_engine_hide_log_window(); return(OK); } //Ham tao vecto toa do void set_vector(double vector[3], double x, double y, double z) { vector[0] = x; vector[1] = y; vector[2] = z; 66 } // player.cpp // ////////////////////////////////////////////////////////////////////// #include #include #include "player.h" #include "..\\..\\..\\..\\..\\Engine\\Include\\mrft_api.h" //Ham tao vecto toa do void set_vector(double vector[3], double x, double y, double z); player::player() { } player::~player() { } int player::init(char *file_name, char *bitmap_path) { m_speed = 0; m_friction = 0.8; m_max_speed = 50; m_min_speed = 2; m_skin_id = 0; m_player_object = Morfit_object_create_from_file(file_name); if(m_player_object == NULL) return(VR_ERROR); double scale[3] = {3,3,3}; Morfit_object_set_scale(m_player_object, scale); strcpy(m_bitmap_path, bitmap_path); return(update_according_to_new_animation()); } int player::update_according_to_new_animation(void) { //load chung khi can toi anh. engine se ko du de load cac anh da co san trong bo nho char buff[MAX_PATH]; strcpy(buff,m_bitmap_path); strcat(buff,"\\skin.bmp"); m_skin_bitmap = Morfit_bitmap_load(buff,-1); strcpy(buff,m_bitmap_path); 67 strcat(buff,"\\pain.bmp"); m_pain_bitmap = Morfit_bitmap_load(buff,-1); //thiet lap trang phuc Morfit_object_set_bitmap(m_player_object, m_skin_bitmap); set_parameters_according_to_scale(); m_current_sequence = set_animation_sequence("stand", 0); m_sequence_id_num = STAND; m_stand_sequence = m_current_sequence; DWORD anim3d = Morfit_object_get_3D_animation(m_player_object); m_fall_sequence = Morfit_3D_sequence_get_using_name(anim3d, "death"); if(m_fall_sequence != NULL) { int num_of_frames = Morfit_3D_sequence_get_number_of_frames(m_fall_sequence); //dung trinh tu nga trong mot trang thai rieng Morfit_3D_sequence_set_frame_duration(m_fall_sequence, num_of_frames-2, 1000000); Morfit_3D_sequence_set_speed(m_fall_sequence,0.5); //times nhanh hon 2 lan } m_walk_sequence = Morfit_3D_sequence_get_using_name(anim3d, "walk"); if(m_walk_sequence == NULL) return(VR_ERROR); m_attack_sequence = Morfit_3D_sequence_get_using_name(anim3d, "attak"); m_pain_sequence = Morfit_3D_sequence_get_using_name(anim3d, "pain"); return(OK); } //Thiet lap cac them so theo ti le kich thuoc //Khi trang thai nhan vat thay doi thi cac thuoc tinh cung thay doi void player::set_parameters_according_to_scale() { double scale[3]; Morfit_object_get_scale(m_player_object, scale); m_acceleration = ACCELERATION * scale[2] / 5; if(m_acceleration < ACCELERATION) m_acceleration = ACCELERATION; m_max_speed = MAX_SPEED * scale[2] / 3; m_min_speed = MIN_SPEED * scale[2] / 3; //thiet lap chieu cao 68 double box[2][3]; Morfit_object_get_bounding_box(m_player_object, box); m_height = box[1][2] - box[0][2]; } DWORD player::set_animation_sequence(char *sequence_name, int transition_duration) { DWORD anim3d = Morfit_object_get_3D_animation(m_player_object); DWORD sequence = Morfit_3D_sequence_get_using_name(anim3d, sequence_name); if(sequence == NULL) return(NULL); Morfit_object_set_3D_sequence(m_player_object, sequence, transition_duration); return(sequence); } void player::move(void) { int muscle_force_used = NO; double save_location[3]; //ghi lai vi tri trong truong hop nhan vat muon toi. Morfit_object_get_location(m_player_object, &save_location[0], &save_location[1], &save_location[2]); DWORD sequence = Morfit_object_get_3D_sequence(m_player_object); if(m_sequence_id_num == WALK || sequence == m_stand_sequence) { //tien phia truoc if(GetAsyncKeyState(VK_UP) < 0) { m_speed += m_acceleration; muscle_force_used = YES; } //lui phia sau if(GetAsyncKeyState(VK_DOWN) < 0) { muscle_force_used = YES; m_speed -= m_acceleration; } } 69 if(m_sequence_id_num == WALK || sequence == m_stand_sequence || sequence == m_attack_sequence || sequence == m_pain_sequence) { //sang trai if(GetAsyncKeyState(VK_LEFT) < 0) { Morfit_object_rotate_z(m_player_object, 6, WORLD_SPACE); } //sang phai if(GetAsyncKeyState(VK_RIGHT) < 0) { Morfit_object_rotate_z(m_player_object, -6, WORLD_SPACE); } } double gravity_and_friction_factor = get_friction_and_gravity_factor(); if(muscle_force_used == NO || fabs(m_speed) > m_min_speed) { m_speed *= gravity_and_friction_factor; if(muscle_force_used == YES) if(fabs(m_speed) < fabs(m_min_speed)) m_speed = m_min_speed * m_speed / fabs(m_speed); } if(m_speed > m_max_speed) m_speed = m_max_speed; if(m_speed < -m_max_speed) m_speed = -m_max_speed; Morfit_object_move(m_player_object,OBJECT_SPACE, -m_speed,0,0); select_sequence(); // xac dinh mot diem duoi cung nen double point_below[3]; get_polygon_below(point_below); //chieu cao giua cua nhan vat co the la chieu cao len + chieu cao than tinh // tu giua xuong duoi (m_height/2) double new_altitude = point_below[2] + m_height / 2; if(new_altitude > save_location[2] + m_height / 3) { Morfit_object_set_location(m_player_object, save_location[0], save_location[1], save_location[2]); 70 m_speed = -m_speed * 0.5; } else { double location[3]; Morfit_object_get_location(m_player_object, &location[0], &location[1], &location[2]); Morfit_object_set_location(m_player_object, location[0], location[1], new_altitude); } } double player::get_friction_and_gravity_factor() { //cong thuc tinh trong luc // player_mass*earth_gravity*sin(alpha) double plane[4]; double point_below[3]; DWORD polygon = get_polygon_below(point_below); if(polygon==NULL) return(m_friction); Morfit_polygon_get_plane(polygon, plane); double gravity_direction[3]; double z_vector[3] = {0,0,1}; Morfit_math_cross(plane, z_vector, gravity_direction); Morfit_math_cross( plane, gravity_direction, gravity_direction); Morfit_math_normalize_vector(gravity_direction); if(plane[2] 1) return(m_friction); //khong co gi xay ra double cos_alpha = plane[2]; double alpha = acos(cos_alpha); double gravity_force = sin(alpha); //m*g*sin(alpha) . m*g==80. m==mass. g==earth gravity double direction[3]; Morfit_object_get_direction(m_player_object, &direction[0], &direction[1], &direction[2]); double gravity_factor = Morfit_math_product(gravity_direction, direction); if(m_speed < 0) gravity_factor = -gravity_factor; 71 //nhan vat nga xuong khi toc do qua cao hoac luc tac dung qua lon if((m_sequence_id_num != FALL) && (gravity_factor * gravity_force > 0.3) && (fabs(m_speed) > 0.8 * m_max_speed)) { m_current_sequence = set_animation_sequence("death",300); m_sequence_id_num = FALL; } double result = m_friction+gravity_factor * gravity_force; if(result < 0) result = 0; return(result); } void player::select_sequence() { DWORD sequence = Morfit_object_get_3D_sequence(m_player_object); if(sequence == m_stand_sequence) { m_sequence_id_num = STAND; m_current_sequence = m_stand_sequence; } else { if(sequence == m_walk_sequence) m_sequence_id_num = WALK; m_current_sequence = m_walk_sequence; } // chi mot trinh tu ket thuc thi trinh tu khac moi duoc bat dau // trinh tu van chuyen duoc tao ra tu dong if( (sequence == m_walk_sequence) && (m_speed < m_min_speed && m_speed > -m_min_speed)) { m_current_sequence = set_animation_sequence("stand",100); m_sequence_id_num = STAND; } else if((sequence == m_stand_sequence) && (m_speed >= m_min_speed || m_speed <= -m_min_speed)) { m_current_sequence = set_animation_sequence("walk",100); m_sequence_id_num = WALK; 72 } else if((sequence == m_fall_sequence) && (m_speed < m_min_speed && m_speed > -m_min_speed)) { //kiem tra trinh tu nga da ket thuc hay chua DWORD anim3d = Morfit_object_get_3D_animation(m_player_object); DWORD fall_sequence = Morfit_3D_sequence_get_using_name(anim3d, "death"); int num_of_frames = Morfit_3D_sequence_get_number_of_frames(fall_sequence); double current_position = Morfit_3D_sequence_get_current_frame(fall_sequence); if(current_position >= num_of_frames - 2) { m_current_sequence = set_animation_sequence("stand",1000); m_sequence_id_num = STAND; } } if(m_sequence_id_num!=FALL) { //thiet lap mot trinh tu dung if(m_speed<0 ) { Morfit_3D_sequence_backwards_play(m_current_sequence,YES); } else { Morfit_3D_sequence_backwards_play(m_current_sequence,NO); } } set_sequence_speed(); } void player::set_sequence_speed() { double sequence_speed=1; if(m_sequence_id_num==FALL || m_sequence_id_num==ATTACK || m_sequence_id_num==PAIN) return; 73 if(m_sequence_id_num==STAND) sequence_speed=get_standing_sequence_speed(); else { double abs_speed=m_speed; if(abs_speed<0) abs_speed=-abs_speed; m_effort++; //xay dung moi lien ket giua toc do va trinh tu toc do // sequence_speed=F(player_speed); //toc do nhan vat la 1 thi trinh tu toc do se la 0.7 //toc do nhan vat la to m_max_speed tthi trinh tu toc do se la 0.25 //thay doi cac thiet lap de nhin thay su thay doi cac hieu ung double seq_speed1=0.7; //trinh tu toc do khi toc do nguoi choi la 1. double seq_speed_max=0.35; //trinh tu toc do khi toc do nguoi choi la m_max_speed. //cap nhap toc do theo ti le kich thuoc nhan vat double scale[3]; Morfit_object_get_scale(m_player_object, scale); seq_speed1*=(1+scale[2]/200); seq_speed_max*=(1+scale[2]/200); //pt duong thang y=a*x+b if((m_max_speed-1) <=0) return; //bao dam de ko chia cho 0 double a=(seq_speed_max-seq_speed1)/(m_max_speed -1); double b=seq_speed1-a; sequence_speed=a*abs_speed+b; if(sequence_speed<seq_speed_max) sequence_speed=seq_speed_max; } Morfit_3D_sequence_set_speed(m_current_sequence, sequence_speed); } //Tao trinh tu tho khi nhan vat dang dung double player::get_standing_sequence_speed() { //This formula gives tempo==0.1 when effort=0 //and tempo 0.1 when effort==400 double tempo=-(double)m_effort/400+0.8; if(tempo<0.1) 74 tempo=0.1; m_effort=m_effort-1; if(m_effort<0) m_effort=0; if(m_effort>500) m_effort=500; return(tempo); } //Xac dinh vung duoi nen DWORD player::get_polygon_below(double point_below[3]) { double location[3]; Morfit_object_get_location(m_player_object, &location[0], &location[1], &location[2]); double up_location[3], down_location[3]; set_vector(up_location, location[0], location[1], 1000000); set_vector(down_location, location[0], location[1], -1000000); DWORD terrain_poly, blocking_object; int flag=Morfit_object_is_movement_possible(m_player_object, up_location, down_location, &terrain_poly, point_below, &blocking_object); if(flag==YES) { printf("An error occurred, there is now ground below !!!\n"); return(NULL); } return(terrain_poly); } //Thiet lap ti le kich thuoc mac dinh void player::scale_default(void) { double scale[3]={3,3,3}; Morfit_object_set_scale(m_player_object,scale); set_parameters_according_to_scale(); } //ti le kich thuoc nhan vat theo cac truc x,y,x hoac co the ket hop giua cac truc void player::scale(double factor, int axis) { double scale[3]; 75 Morfit_object_get_scale(m_player_object,scale); if(axis & X_AXIS) scale[0]*=factor; if(axis & Y_AXIS) scale[1]*=factor; if(axis & Z_AXIS) scale[2]*=factor; Morfit_object_set_scale(m_player_object,scale); set_parameters_according_to_scale(); } //trang thai tan cong void player::attack(void) { if(m_attack_sequence==NULL) return; //trinh tu tan cong duoc xay dung boi rat nhieu trang thai tan cong nhu cam sung,ban.... Morfit_object_set_3D_sequence(m_player_object, m_attack_sequence, 0); Morfit_object_replace_3D_sequence_when_finished(m_player_object, m_stand_sequence,300); m_current_sequence=m_attack_sequence; m_sequence_id_num=ATTACK; } //trang thai bi thuong void player::pain(void) { if(m_pain_sequence==NULL) return; Morfit_object_set_3D_sequence(m_player_object, m_pain_sequence, 0); Morfit_object_replace_3D_sequence_when_finished(m_player_object, m_stand_sequence,400); m_current_sequence=m_pain_sequence; m_sequence_id_num=PAIN; } //Lay lai trang phuc cho nhan vat,chinh la chuyen doi giua cac anh void player::replace_skin(void) { if(m_skin_id==0) { 76 Morfit_object_set_bitmap(m_player_object, m_pain_bitmap); m_skin_id=1; return; } Morfit_object_set_bitmap(m_player_object, m_skin_bitmap); m_skin_id=0; } //Lay lai hinh dang ban dau cho nhan vat void player::replace_shape(DWORD anim3d, char *bitmap_path) { Morfit_object_set_3D_animation(m_player_object, anim3d); strcpy(m_bitmap_path, bitmap_path); update_according_to_new_animation(); } 77 TÀI LIỆU THAM KHẢO [1]. Nguyễn Văn Huân- Vũ Đức Thái, Kỹ thuật lập trình mô phỏng thế giới thực dựa trên Morfit [2]. Một số trang web như: http:// www.3dnews.com - The site for the Morfit VC++ developers, run by Bucky (Brad Buchanan). - Morfit Developer Mailing List - The Morfit official mailing list. http:// www.3dng.com - Morfit 3D for Euphoria Web Page. Run by Mark Brown. - Morfit for Borland Builder C++ users. - Beros 3D World - One of the most promising arcade games under development. Visit to see screenshots and a demo. - Morfit Projects - This page includes links and information on different Morfit projects.

Các file đính kèm theo tài liệu này:

  • pdfMô phỏng hành động nhân vật trong xây dựng mô hình 3d.pdf